I have written a COM visible dll, which will be called from a native Win32 program. For debugging purposes I added a simple WinForms client to the solution containing the dll.
Now when I set a breakpoint in the dll, that breakpoint is hit, but I can't step through the code: the debugger always jumps to the next breakpoint in the dll, or the first line of code in the client after the call to the dll.
How can I get the debugger to step through the dll code?
I thought it might be the "Enable Just My Code" option, but that is not set.
Update
jdv suggested setting "enable unmanaged code debugging" in the project properties, but that didn't have the desired effect.
Thanks, Miel.
Here are the steps I performed and which allowed me to successfully debug a .NET assembly exposed as COM component:
Start by creating a class library containing a class that will be exposed as COM object:
namespace COMTest
{
using System;
using System.Runtime.InteropServices;
public interface IFoo
{
void Bar();
}
[ComVisible(true)]
public class Foo : IFoo
{
public void Bar()
{
Console.WriteLine("Bar");
}
}
}
Sign the assembly with a strong key and register as COM object:
regasm.exe /codebase COMTest.dll
Once the COM object is registered you may create a new console application in a new Visual Studio instance to test the COM object:
class Program
{
static void Main()
{
var type = Type.GetTypeFromProgID("COMTest.Foo");
var instance = Activator.CreateInstance(type);
type.InvokeMember("Bar", BindingFlags.InvokeMethod, null, instance, new object[0]);
}
}
Place a breakpoint on the InvokeMember line and run the application. Once the breakpoint is hit open the Modules Window (Ctrl+D M) and make sure that symbols are loaded for the COM assembly:
Now if if you press F11 you can step into the COM class to debug.
Remark: You can also directly open the .cs file containing the Foo class and directly place a breakpoint there. Once again the important thing is to have the symbols loaded for the assembly or when you place your breakpoint Visual Studio will tell you that this breakpoint won't be hit.
There was a post VS2008 SP1 hotfix released that solves a number of debugging problems. The KB article is here, the hotfix download is here.
Related
I am writing a C# DLL which must be COM visible as it's main use case will be embedded into Microsoft Excel VBA (I know). Whilst developing I have been using Visual Studio's "Register for COM Interop" checkbox and having the process done for me. This has been working fine on my PC as I am able to get valid outputs in Excel, however now I am trying to register the DLL on client machines (manually) and I seem to be having issues with making valid calls as Excel only returns !VALUE.
This following has been my process:
AssemblyInfo.cs:
[assembly: ComVisible(true)]
Class1.cs:
namespace ManualRegister
{
public class Class1
{
public string test()
{
return "Working!";
}
}
}
Copy ManualRegister.dll into SysWOW64
Register.bat:
cd/
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe ManualRegister.dll /tlb:ManualRegister.tlb /codebase
pause
Adding reference to VBA module.
VBA Code:
Function test()
Dim object As New ManualRegister.Class1
test = object.test()
End Function
VBA error:
Can anyone see what step I'm missing / doing wrong?
(I have also tried specific CPU architecture builds to no avail)
I have a code running that successfully register Excel AddIn using C# Automation and talks to C++ though C# layer
// Tools -> Create GUID -> Register Format
namespace MyExcelAddins
{
[ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true)]
[Guid("6F89542F-3DAC-471F-86DD-145F5E456968")]
public class MyExcelFunctions : AddInRegistrator
{
[DllImport(#"C:\Users\Ilya\Documents\Visual Studio 2012\Projects\UnmanegedTester\x64\Debug\")]
public static extern double AddNumbers(double a, double b);
public double SampleAdd(double a, double b)
{
double res = AddNumbers(a, b);
return res;
}
}
}
Here is the view of my solution where C++ project I added from another directory.
I was able to debug C# code and now I want to try to debug the C++ part. I set the debug property of C# project to
and when click run, the error I got is
If I uncheck "Enable Native Code Debugging", I do not have the error but of course cannot debug C++. My guess I'm missing something in the settings. Please let me know if anyone has an idea how to fix that.
If I continue debugging I can hit breakpoint in C# but not in C++
That error message is telling you that you don't have debug symbols for excel.exe, which is not surprising since it is a Microsoft program. You can continue debugging, and your code (which should have debugging information) will still be debuggable. For example, you can set a breakpoint in some of your code that will be called by Excel and the debugger will stop on it when it is reached.
I have a TestClass.cs file that contains an interface, and a class, much like this:
namespace CPierce.CSharpBridge
{
[System.Runtime.InteropServices.Guid("3D08DF02-EFBA-4A65-AD84-B08ADEADBEEF")]
public interface ICSide
{
// interface definition omitted...
}
[System.Runtime.InteropServices.Guid("CBC04D81-398B-4B03-A3D1-C6D5DEADBEEF")]
public partial class CSide : ICSide
{
// class definition omitted...
}
}
When I compile this at the command line, and run regasm on it:
csc /debug /t:library TestClass.cs
regasm TestClass.dll /tlb:TestClass.tlb
I get a nice, big .tlb file suitable for including in a C++ project elsewhere....
10/27/2011 01:50 PM 3,616 TestClass.tlb
When I put TestClass.cs into a "Class Project" in Visual Studio, compile it, run regasm, the resulting .tlb is pathetic and nearly useless -- it has no interface, no method signatures, etc...
[Compiled TestClass.cs as part of Project "ClassProject" in Visual Studio]
regasm ClassProject.dll /tlb:ClassProject.dll
10/27/2011 01:58 PM 1,132 ClassProject.tlb
This is the same C# code in both cases, one being compiled with Visual Studio one at the command line, giving me completely different results.
What gives?
--
Update: Hans suggests that the [ComVisible(true)] attribute missing is causing the problem. Tried it, and it worked. But that still doesn't answer the question, why? Why do I get different results based on which compile method I use?
If you create a new Class Library in Visual Studio, the default AssemblyInfo.cs file includes the line:
[assembly: ComVisible(false)]
The command-line command you're using is only compiling your TestClass.cs file, so you get the default setting for ComVisible (which, judging from the available evidence, is probably true). When you compile from the IDE, you include AssemblyInfo.cs as well, so its explicit setting overrides the compiler's default.
Also check if your class has functions of accessor type public.
In our case, the project was working fine when it was being used from within the solution but when we extracted the logic to create a DLL, it stopped creating the TLB file with no indication on why...
So if you have a class like so,
public class tlbuser{
private void functionTLB(){
//function code
}
// rest of the class code
}
Ensure it is changed to:
public class tlbuser{
public void functionTLB(){
//function code
}
// rest of the class code
}
i have created a C# dll file on my machine as shown below:
namespace myDLL
{
public class myClass
{
public string myFunction()
{
return "I am Here";
}
}
}
then i created a tlb file with "tlbexp" command,
then i used the "regasm" command n registered this dll on my machine.
When i created an object of type myClass on my machine using VBScript, everything is working fine... here i used the CreateObject() method as shown below:
Set myObj = CreateObject("myDll.myClass")
Now i want to create an object of type myClass from VBScript that is running on another machine, how can i do this. please help me how can i access that dll file, am using the CreateObject() function as shown below:
Set HD = CreateObject("myDll.myClass","myMachineName")
now am getting error as "permission denied".
It appears that this is supported if the assembly is built with as COM visibility enabled.
Is it possible to execute a .NET assembly(dll) from vbscript?
By the way, I was pretty delighted to find out that there is a JScript compiler for .NET which allows one to write .NET code using JScript and also to target other .NET assemblies but unfortunately I haven't found anything similar for VBScript.
I have a simple class library written in c#.
using System;
namespace TestDll
{
public class Test
{
public string HelloWorld
{
get
{
return "Hello World";
}
}
}
}
My question is how can I call this HelloWorld function from Microsoft Office Visual Basic (which I think is VB6)?
My first step was to add the DLL as a reference - but on browsing and selecting the compiled DLL the message "Can't add a reference to the specified file." was thrown.
Can anyone point me in the right direction as to why/how to get this working?
Thanks in advance SO!
You can't access a static member via COM interop. In fact your code doesn't even compile, the method should be in a class. Here is how you can do it:
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("01A31113-9353-44cc-A1F4-C6F1210E4B30")] //Allocate your own GUID
public interface _Test
{
string HelloWorld { get; }
}
[ClassInterface(ClassInterfaceType.None)]
[Guid("E2F07CD4-CE73-4102-B35D-119362624C47")] //Allocate your own GUID
[ProgId("TestDll.Test")]
public class Test : _Test
{
public string HelloWorld { get { return "Hello, World! "; } }
}
The project properties Build tab, select Register for COM interop. So you can see the results quickly. To install the dll on another machine you need to use regasm.
To then consume this:
Dim o : Set o = CreateObject("TestDll.Test")
MsgBox o.HelloWorld
You can also reference the dll and use early binding:
Dim o As TestDll.Test
Set o = New TestDll.Text
MsgBox o.HelloWorld
And to expand on registering the DLL on different computers.
Once you compile and build the above code on your development machine, if you have
The project properties Build tab, select Register for COM interop.
your Visual Studio output folder (usually bin\Debug) where the compiled *.dll is found will also have a *.tlb file.
This *.tlb file is a 'Type Library'. And is needed by the client machine to understand the different 'Types' in your *.dll and to basically tell the client machine how to use it.
By setting the above 'Register for COM interop' -- aswell as a *.tlb file being produced, the assembly(dll) is registered on your machine, and is therefore accessible.
In VBA you can now add this file as a reference by
VBA Editor -> Tools -> References -> Browse -> Select
this will allow you to then declare the classes found in your library.
Dim TestClass As Test
Set TestClass = New Test
MsgBox TestClass.HelloWorld
HOWEVER - if you want to then use your dll on a different client machine, you will have to use regasm.exe - to register the assembly(dll) on that machine.
This can be done by the command line,
regasm.exe
in this case
regasm.exe TestDll.dll
once you have registered the assembly on the new client machine, you will be able to access it by again adding a reference to its *.tlb
Hope this helps!
Just wanted to comment that in Visual Studio 2008, to get the .tlb file generated you must also go under the Application | Assembly Information and select "Make Assembly COM visible". Took me a while to find that, so hope it helps others out.
To add to AnthonyWJones's good answer, you'll also need to register your DLL using Regasm.exe which adds the necessary registry entries.