Im trying to use the IAttachmentExecute interface in my C# application. (Using .NET4 and VS2010).
MSDN says it is in Shdocvw.dll (and its members says that IAttachmentExecute is specified in Shobjidl.h / Shobjidl.idl which leads me to a 73db1241-1e85-4581-8e4f-a81e1d0f8c57 GUID.)
When I add a reference to this DLL in VS I get the generated SHDocVw-Namespace, but it does not contain this interface.
Every other attempt with System.Type.GetTypeFromCLSID and System.Activator.CreateInstance or System.Activator.CreateComInstanceFrom fails with the message that there is no type with that GUID.
How can I use that interface?
(Dont think there are alternatives.)
Thanks in advance.
Edit:
Generated interface definition with:
MIDL.exe msdn.microsoft.com/en-us/library/ms680078.aspx
Tlbimp.exe msdn.microsoft.com/en-us/library/tt0cf3sx.aspx
Edit2:
Independent from interface def.:
Tries with CoCreateInstance fail with REGDB_E_CLASSNOTREG, so how could I make my program find IAttachmentExecute. Or am I wrong with my problem and simply miss the solution / my mistake?
This is exactly what I just investigated, here's the blog post: http://joco.name/2010/12/22/windows-antivirus-api-in-net-and-a-com-interop-crash-course/
Related
I create a C# COM interop for c++ to invoke.
I have registered the dll and tlb file by regasm.
everything goes well till one day i changed code of C# part (i didn't change the definition of interface, just implementation changed). one interface in COM returns an error 0x80131509. the strange thing is, it is only happened in some computers (my develop PC is works well so i can't debug this problem).
I'm not really clear on how the C# COM worked with C++, after i registered them, i just know they create key value in window registry.(like what regasm /regfile generated). how c++ knows where the COM dll is(search path environment variables)? and what the use of tlb file in run time?
any suggestion?
I got the same error as soon as I introduced a simple inheritance hierarchy to my COM library. A quick resolution was to set the ComVisible attribute to true on the base class. This fixed my problem immediately.
It does make a lot of sense when you think about it - the compiler doesn't allow you to build a hierarchy where the base class is less visible than the inheriting class. So it being the same for COM should come as no surprise - the only difference being, that it is failing at run-time instead of compile-time.
I would venture that the true reason for the error is a broken constructor chain, but I put no further research into it.
I think that your problem is related to the registry... You should try to unregister and register (using regasm) your dll in the computers that are having this problem.
If that doesn't work unregister the dll in those computers, than use regedit to search and delete any missing registry keys that refer to it, after that register your dll again. You could also use one of those registry cleaner programs after deleting the missing keys to guarantee that you didn't miss anything.
Remember that you should allways register a dll in the directory that it will be used by your application and this should happen only once. If you need to unregister a dll, then you should allways do it in the same directory that you used for the registration. In other words, once a dll is registered do not move it.
Note: if your dll is not on the same path as your C++ application it should be in a directory that is referenced in the PATH environment variable.
I got the same error message when I was calling a .Net4 C# COM object from Visual FoxPro.
The method returns object, type of which may be one of several. All the types are derived from an abstract class which implemented an interface with the common stuff for these types.
Eventually I decided to remove the abstract-modifier from the base class and just make it public and ComVisible. This solved the problem for me, even though I would like the base class to be abstract.
I have been working on implementing ImDisk into my C# project, where I can create RAMDisk on the fly. Unfortunately due to absolutely no examples, I am at a bit lost as to how to resolve this issue.
I am receiving the error Unable to find an entry point named '_ImDiskFindFreeDriveLetter#0' in DLL 'imdisk.cpl'. which, after Google searches, is apparently from not initiating an object. However, ImDiskAPI has no constructors, and cannot be initiated in that manner, so I am at a bit of a stand-still. When I attempt to initialize an instance, I get The type 'LTR.IO.ImDisk.ImDiskAPI' has no constructors defined
Does anyone have any idea what I can do to get this going?
The error indicates that there is a DLL missing.
You need to place the ImDisk.cpl file into your application's directory.
The managed wrapper library needs the ImDisk.cpl file to function properly.
Hope, this helps.
I am having a hard time figuring out what I'm doing wrong, so I thought I would ask this at SO. I am trying to automate a measurement task (Qualcomm QXDM), hence would like to access the COM interface exposed by a measurement tool. I wrote the following python code with works perfectly:
from comtypes.client import CreateObject
QXDM = CreateObject("QXDM.Application")
IQXDM2 = QXDM.GetIQXDM2
...
Now, I'm trying to rewrite this is C# because of some specific requirements I have. Here's what I tried:
using QXDM;
QXDM2Class IQXDM = new QXDM2Class();
But when I try to run this, I get:
Retrieving the COM class factory for component with CLSID {6777AAE0-D9D2-4EA7-996B-0EECC68F97D8} failed due to the following error: 80040154.
What am I doing wrong? I can see all the methods and interfaces provided by QXDM in the object browser in Visual Studio.
Edit: Seems like late binding is the only way to do this as Hans suggested. I modified the code to the following:
Type QXDM = Type.GetTypeFromProgID("QXDM.Application");
Object QXDMObject = Activator.CreateInstance(QXDM);
This works. The only trouble is that I need to know what methods and classes are exposed by QXDM, which I think I could figure out using the object browser. Thanks all!
Your code just isn't the same. In the Python code you are clearly using the common "Application" object. In many automation object models, that's the object from which you create other ones. Like IQXDM2 from the GetIQXDM2() method.
Your C# code seems to be trying to create the class that implements IQXDM2 directly. Cannot work, you have to go through the Application interface. It's just like the error message says, there's no "class factory" for that object, the Application interface creates it. Whatever it is called, it is almost always has "application" in the name. Use Object Browser on the interop reference to have a look-see. Look for the one that has the GetIQXDM2 method.
If you don't see anything resembling it then you may have added the wrong DLL. Look in the registry for the name of the right one. Start Regedit.exe and look at HKCR\QXDM.Application. You'll find a CLSID key with a guid. Then look at HKCR\Clsid\{guid} where {guid} is the guid you found. The InprocServer32 key has the DLL name. An out-of-process server uses the LocalServer32 key.
If that doesn't pan out then maybe the COM server was only meant to be used by scripting languages. Very unusual but it can happen. In which case you'll have to use it late-bound in your C# code. That's only easy to do with the C# 4.0 dynamic keyword or VB.NET
It could be the fact that the DLL are dependent on other DLL's.. Debug with ProcExp (http://www.sysinternals.com/) might give some light
I think the COM objects are registered OK, or your Python code would fail and you would not see them on the machine. If this is the this case, your problem is accessing the COM objects from C#. Try the approach specified here.
If the library is already registered,
you can perform the following steps to
have Visual Studio generate an interop
assembly for you
HRESULT 0x80040154 means that the COM class is not registered. Try running regsvr32 on the COM dll.
It could be that you are building for 64 bit. Check your platform target. Make sure it's 32 bit.
Say I've got a load of COM types and I'd like to check if a particular type has been registered. I can use Activator.CreateInstance to actually try and create the class, but I was wondering if there's a simpler way actually check in advance if the class is actually registered.
I'd prefer not to go to the registry directly - I'm looking for something easy to use like the Activator.CreateInstance call above.
Thanks
NB. Activator.CreateInstance doesn't directly create COM class instance, it requires an interop assembly to have been generated and installed (e.g. by tlbimp.exe)—but this makes no difference here.
The simplest way to check without reading the registry is to try creating an instance and catch the possible exceptions due to the type not being available. (E.g. COMException if the underlying component is not installed correctly, TypeLoadException (IIRC) if the interop assembly is missing.)
I came across the following error a few days ago, in one of our C# applications here at work. Here's how the error message looks like:
"Inherited interface '...ResourceManager.ResourcesManager' causes a cycle in the interface hierarchy of '...ResourceManager.IResourcesManagerView' in D:...\Common\ResourceManager\IResourcesManagerView.cs"
This always happens on my machine, but on the build machine there's a 50-50 chance the build will succeed. My class 'ResourceManager' implements an interface 'IResourcesManagerView', which also implements several interfaces, one of which is a generic interface named IInitializable. I have found the following workaround: declare a dummy interface IDummy implementing IInitializable.
But that doesn't make any sense to me. Has anyone come across this issue?
I use Windows XP, Visual Studio 2005.
1) Add a Class Diagram to visualize the problem. Something tells me you aren't using one now.
2) Minimize the problem to something you can post. But you will probably find it yourself along the way.
Best Guess: Smells like there are 2 versions of IInitializable or maybe IResourcesManagerView around.
You are probably referencing the same, but different version assembly containing the interface. Make sure you reference common assemblies from the same location.
I get the same compilation error, fixed it (sort of) and formalized it here.
But it might be a different problem than yours.