Launching a C# dialog from an unmanaged C++ mfc active x dll - c#

I've been told to write a dialog in C# which must be instantiated from an unmanaged c++ dll. We do this in other places in our code by simply adding a managed c++ class to the C++ project, then calling the C# dll from the managed c++ class. However I'm finding that doesn't work for me from where I have to do it. I think because the c++ dll is an MFCActiveX project. As soon as i set the clr on any file in this project, it will no longer register correctly. When i attempt to register it, i get three errors, then a message that it registered. However when i try to use it i get a 0x80040111 "ClassFactory cannot supply requested class" error.
If anyone has any idea what the problem is here i would greatly appreciate it. I either need to be able to accomplish this (preferred) or prove that it's not possible.
Thanks

I can't see how a MFCActiveX project would prevent you from creating the C# class in this way. Unless it simply does not allow for a managed class to be added.
If you can't get the managed C++ class trick to work, another option is to use COM. It's possible to register a factory of sorts in the C# project as a COM object. Say give it the following interface
[ComVisible(true)]
[Guid("babe87fc-1467-4913-a1d3-47eeedf1afb5")]
public interface IDialogFactory {
void Create();
}
You'd also have to create a backing class as well. But then you could register the managed assembly and use COM to access it.

You must now register it with "regasm" instead of "regsvr32".

Related

Using DLLs in VBScript

I've compiled C# code into a DLL, but have little experience with them. My C# code contains a class HelloWorld with a static method Print(). I'd like to use this DLL in VBScript to call the method Print(). I know this is base, but I'm using this as a test for a larger scale project that will be compiled to DLL in the end. What's the declare look like for that and how would the method call look?
Important: Both methods will work only if the DLL exposes a COM interface.
If your dll is registered with the system, use CreateObject with it's ProgID.
Set myObject = CreateObject("MyReallyCoolObject.HelloWorld")
myObject.Print
If your object is not registered on the system, use GetObject with a path to the file containing your object. Make sure your object exposes the proper interface. (The second parameter is optional. Here you can provide a class name if your object exposes more than one.)
Set myObject = GetObject("C:\some\path\helloworld.dll", "appname.HelloWorld")
myObject.Print
I think you might be looking for Registration-Free COM. This SO answer regarding the Microsoft.Windows.ActCtx should help specifically for VBScript.
Keep in mind that COM doesn't support static methods, so you'll have to make your Print method into an instance method.
How to call a .NET DLL from a VBScript

Adding COM object to managed code

I have a header-file, the COM interface. I have created a small win32 program which works, but my main program is written in C#.
So I would like to import this COM object in my main program, but how do I do this, when the only thing I got is the header-file?
All places I've looked I need a tlb-file..?
I'm new to COM objects so just ask if you need some extra info, or have another workaround :)
[UPDATE]
First thanks for all the responses!
I've tried some different things, but haven't solved my issue yet. In my research, I've found an article describing COM Interop http://msdn.microsoft.com/en-us/library/aa645736(v=vs.71).aspx#vcwlkcominteroppart1cclienttutorialanchor2
This haven't helped me out. But I've found that I should be able to get moving if I can complete the following:
Declaring a COM coclass:
[ComImport, Guid("7C075F7F-FD71-40a2-AC63-0D0C4DB39ECA")]
class CCamera
{
// Cannot have any members here
// NOTE that the C# compiler will add a default constructor
// for you (no parameters).
}
Creating a COM class wrapper:
[Guid("AD87369B-3BBA-4f1c-81C5-B92FCEA9A1F4"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface ICamera
{
//static HRESULT GetCameraInterface();
bool StartPreview();
bool StopPreview();
}
Using Casts Instead of QueryInterface:
try
{
CCamera cam = new CCamera();
ICamera test = (ICamera)cam;
//test.StartPreview();
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
}
I get an invalid cast exception, so is this because I miss implementing some methods in the interface?
And how do I implement the following method from the c++ interface:
static HRESULT GetCameraInterface(void __RPC_FAR *__RPC_FAR *ppvObject);
[SOLUTION]
OK I got a solution, but I never solved to wrap the interface.
Instead I created a C++ dll project and exposed the methods I needed. Then in my C# project, could I use these methods with DllImport. If anybody need more explanation on how I archived this, send me a message.
If it is registered as a COM-Object, then you can import it via the Add Reference Dialog. Right click on the project --> Add Reference. Then select the Tab "COM" and you can select your COM Interface. Required Interop classes for .NET will be generated automatically.
you need to register the COM dll with the following line
regasm COMDll.DLL /tlb
then you can add it as a reference to your project.
I have completed some research and found that you can include a header file in an idl file in much the same way you do with C, below are the two links that show you how to include the header file in the idl and compile the idl to a tbl file which you can use in .Net:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa367049(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa367064(v=vs.85).aspx
I haven’t tried it and it looks like you may encounter some difficulty if the header file contains more than just the COM definitions, so good luck and please let me know how it went.

Marshaling unmanaged dll in C# through ComInterop without registering DLL

I have an unmanaged DLL which I'm currently calling from C# using a COM Class Wrapper.
[ComImport(), Guid("75E81043-CAD5-11D3-800D-00105A5E2FA0")]
public class MyObject { }
[ComImport(), Guid("75E81042-CAD5-11D3-800D-00105A5E2FA0"),
InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface MyInterface
{
string EncryptString([In, MarshalAs(UnmanagedType.BStr)] string bstrOrginal);
}
Then to call:
MyInterface obj = (MyInterface)new MyObject();
string crypt = obj.EncryptString("something");
This works, the return value is as I expect. However, it requires that the dll is registered with regsvr32.
I'm looking for a way to do this without the requirement of needing to regsvr32. Preferably, by just having a copy of the dll available. It is worth noting, I have the source for the unmanaged dll, and the ability to modify it if necessary.
A shove in the right direction would be greatly appreciated.
I have wanted to do the same thing myself. As Jim mentions it is possible to get the address of DllRegisterServer and call it, but that still modifies your registry with the various entries. If you don't want to do this (for example, you might not have the necessary privileges to write to the Registry), then there is another way.
Any DLL that houses one or more in-process COM objects must expose the DllGetClassObject function. This function is used to acquire an instance of the COM class factory that is used to create a COM object. What you need to do is:
Load the library (DLL) that houses the desired COM object
Locate the DllGetClassObject function
Call DllGetClassObject, passing it the CLSID of the desired COM object, this will return an IClassFactory instance.
Call the CreateInstance method on the class factory to get an instance of the COM object.
Cast the returned object to the interface you wish to use.
Note that there be dragons with this approach -- it is fairly low level. If you get anything wrong you will experience access violation exceptions or worse. (For instance, your interface declaration has to exactly match the COM interface).
I have included some sample code at gist which you might like to use if you want to go this way.
Using this code would look something like this:
// Load the library. You dispose this after you are finished with
// all of your COM objects.
var library = new LibraryModule();
library.Load("mylibrary.dll"); or whatever your dll is called
var clsid = new Guid("75E81043-CAD5-11D3-800D-00105A5E2FA0");
var myObject = (MyInterface)ComHelper.CreateInstance(library, clsid);
Just note that if you dispose of the LibraryModule object, then this will unload the DLL. Depending on your needs, you might just assign the value to a static field so that it exists for the lifetime of the program.
You need to set up your unmanaged DLL for registration-free COM. There's a pretty complete walkthrough here, with plenty of examples. Among other things, it involves using manifests to point to the file, side-by-side assemblies, and some interop.
An important note in the walkthrough is that registration is required for the initial setup of the client, but not later.
If your DLL has to be a COM object, then it must be registered. This registration does not need to be performed by regsvr32. All regsvr32 does is load the DLL, get the address of DllRegisterServer and call it it. DllRegisterServer adds the necessary entries to the registry for an application to use the object.
If your DLL does not need to be a COM object, you can modify it to simply export the function(s) you need and p-invoke it(them).

C# DLL Missing Public Functions

I am attempting to write a DLL using the C# .NET Framework 2.0. Everything compiles okay, but when I try to access the DLL from my application, it fails when attempting to get the procedure address. So, I oped the DLL in Dependency Walker, and all of my public functions are missing!
My DLL, so far, is fairly straightforward:
namespace MyDll_Namespace
{
public class MyDllClass
{
public static int Func1( /* params */ ) { /* ... */ }
public static int Func2( /* params */ ) { /* ... */ }
public static int Func3( /* params */ ) { /* ... */ }
public static int Func4( /* params */ ) { /* ... */ }
}
}
There's not much else, just a few constants and delegates defined inside the class, as well as outside the class in the namespace. Any thoughts or suggestions would be much appreciated. Thanks.
Dependency walker is for win32 DLLs (which is native code), not .NET assemblies (which is managed code). It won't find methods in an arbitrary class (even if they are static). If you need to call managed code from native code, there are ways of doing that, but it's not pretty.
If you want to use your dll from managed code, it's a lot easier. Check out System.Assembly and Activator.
An example of this:
var assembly = Assembly.LoadFile(#"\path\to\your.dll");
var mydllclass_type = assembly.GetType("MyDllClass");
var instance = Activator.CreateInstance(mydllclass_type);
The instance will be an object. To call the methods, you need to use reflection, because the interface is not known at compile-time.
If you are creating a plugin system, the best way is to have a common interface or abstract base for all plugins, and have that referenced by your program. Those third parties who implement a plugin, will also reference this contract. In this case, the last line changes a bit:
var instance = (IMyDllClass)Activator.CreateInstance(mydllclass_type);
Now you can use the methods like in a regularly constructed object.
Part of the problem here is that dependency walker is a tool for native applications. It doesn't understand managed code and hence won't display any of the managed types + methods that you've defined.
I'm confused by this line in your question
when I try to access the DLL from my application, it fails when attempting to get the procedure address
This sounds a bit like an error I would see in a native application, not a managed one. Are you trying to access the C# code from a native application? If so this can only be done via COM magic and not via direct calling. Can you explain in more detail what is going on here?
Try .net Reflector to see exactly what's inside your built DLL (in order to make sure everything is the way it is supposed to).
Also make sure you're in release mode while building your DLL before referencing it... I don't know if it's going to change anything, but it worths the try =)
You need to add a reference to your dll and the runtime will automatically allow you to call your function. Here is a little tutorial on writing a .net class library.
I decided to write my DLLs in C++. However, here is a bunch of useful information I found for using managed code from unmanaged code:
Is it possible to use a DLL created using C# in an unmanaged VC++ application?
How do I call C++/CLI (.NET) DLLs from standard, unmanaged non-.NET applications?
Using managed code in an unmanaged application
Using Managed Components from Unmanaged Code
An Overview of Managed/Unmanaged Code Interoperability
Unmanaged Exports
Calling Managed .NET C# COM Objects from Unmanaged C++ Code
All-In-One Code Framework
CLR Hosting APIs
How To: Migrate to /clr
How to call a managed DLL from native Visual C++ code in Visual Studio.NET or in Visual Studio 2005

Adding an in-proc COM Server object to a C# application

I am new to COM and need to add a Server COM object to my c# application so I can call its methods and implement events. The documentation I have says this requires a COM-aware language such as Visual C++. My app is written in C# so I'm not sure how this is going to work. Any direction would be appreciated.
I am writing an app that communicates with a serial hypercom terminal. The device came with a DLL (the com server interface) that I will need to figure out how to use in my c# application.
I added a reference to the DLL to my project, which shows up as a type library. In object explorer I get interfaces, and some classes etc.
Thanks,
Matt
You can add the COM object as a reference. .NET will create an interop assembly to work with the COM object, just like it was a .NET type.
CComObjectRoot can be used as a base class for all COM objects implemented with ATL. As such you don't have to worry to implement something similar in C#, the required methods (AddRef, Release, QueryInterface) will be generated by tlbexp for classes that are tagged with ClassInterface.
STDMETHODIMP is a define which serves to declare the most common methods that can be called from COM (#define STDMETHODIMP HRESULT STDMETHODCALLTYPE). Again if your class is tagged with ClassInterface you will not have to worry about.
Such construction is required in C++ when your class implements several interfaces. I think this is not required if you tell C# compiler that your C# object implement IDispatch, IFPESOlementationEvents. The appropriate code will be written automatically by the compiler.
Probably everything will not make much sense if you are new to COM and C#, I'll suggest to take a look at the various introduction that you may find on the web, like this.

Categories