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.
Related
I’m working with a .NET 4 application written mostly in C#. The application has a user interface, but it also has an automation interface that allows the features of the application to be exploited directly from a .NET client. It also supports automation via COM, and for this there are “COM adapter” DLLs that present the classes/methods in the “real” DLLs in a COM-friendly way.
For example, let’s say the API for the bulk of the functionality is in a DLL called “Alpha.DLL”: a .NET client can simply reference that DLL directly, but a separate DLL called “Alpha.Com.DLL” is provided for use by COM clients (e.g. VBA).
There are 3 such COM adapter DLLs, and while two work fine, I simply cannot get the last one to work correctly.
The problem DLL only has two classes defined within it, and while I can instantiate one of them from a COM client such as VBScript, I get an error when I try to instantiate the other. The error I get is:
-2146234304 (0x80131040) Automation Error
I can instantiate the same class from .NET code, just not from a COM client.
I’ve tried using FUSLOGVW.EXE to look for assembly-loading errors, but there don’t seem to be any (and in any case, the fact that I can instantiate the other class from the same DLL suggests that it’s not the DLL itself that can’t be found/loaded?).
I’ve tried attaching a debugger and putting a breakpoint inside the constructor for the offending class, but it doesn’t get hit when I try to instantiate the class from VBScript. (A breakpoint in the constructor of the class that works does get hit).
I’ve checked the registry entries for the class I’m trying to instantiate, and I can’t see any problem. The GUIDs and version numbers all seem to match up.
I’m all out of ideas, and at the end of my tether, and I’d be extremely grateful for some help…
-2146234304 (0x80131040) Automation Error
The common problem with using .NET code from a COM client like VBA is that .NET exceptions get rather difficult to diagnose. You have to make do with an often cryptic HRESULT error code, you don't get the Holy Stack trace to see how code blew up. This exception is a doozy like that, it is FUSION_E_REF_DEF_MISMATCH, you can find these HRESULT codes in the CorError.h SDK include file.
You'd normally get the easier to interpret exception message "The located assembly's manifest definition does not match the assembly reference". And the stack trace to tell you what type caused this exception so you'll know what assembly is the problem. Nothing like that when this failed when called from VBA.
It is otherwise an every-day .NET mishap, the CLR found your assembly but its [AssemblyVersion] does not match the reference assembly's version that your code was compiled with. COM certainly increases the odds that this can go wrong, the version is recorded in the registry when you register the assembly with Regasm.exe. Forgetting to re-register if you do it by hand instead of letting the build system take care of it is a very easy oversight. Also very easy to copy dependent DLLs in the client EXE's directory, so the CLR can find them, and forgetting to update them.
Fuslogvw.exe does show this kind of mishap, hard to guess why you don't see anything. The backup plan is to use SysInternals' Process Monitor. It also shows you how the client is reading the registry, another thing that often goes wrong in COM. And you'll see it locating the DLL from the registry key so you'll have a shot at guessing why it found an old one.
Stay out of trouble by using the GAC, often necessary anyway to help the CLR to find dependent assemblies and to solve COM's rather severe DLL Hell problem. And strongly consider using the .NET 4 AppDomain.FirstChanceException event. Good to log exceptions before they turn undiagnosable in the COM client.
please check first
your com dll is placed into GAC
you dont't forget about regasm
http://www.jagjot.com/2014/01/register-c-vb-net-dll-regasm-gacutil/
check cpu architecture
does your com dll depends on anything outside GAC?
Aaargh. I found the problem. I said in my question:
I’ve checked the registry entries for the class I’m trying to instantiate, and I can’t see any problem. The GUIDs and version numbers all seem to match up.
...which was true. However, what I had not noticed was that in the registry definition of one of my classes, the public key token was wrong.
This explains why one class could be instantiated while the other could not, and possibly why there was nothing in the FUSLOGVW log (because the assembly was loaded OK when an instance of the "good" class was created).
Thanks for your help, Hans and Dimzon.
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 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.
I am writing a plugin dll for an application. The application loads plugin assemblies via:
assembly = Assembly.Load(System.IO.File.ReadAllBytes(filename));
The problem manifests itself when I attempt to serialize/deserialize a plublic class. I narrowed it down to the serialization of:
public BindingList<MyClass> MyClasses
{ get; set; }
If I comment this out, no problems. If I attempt to serialize with:
public static void SaveSettingsFile()
{
try
{
XmlSerializer ser = new XmlSerializer(typeof(GameTimeSettings));
TextWriter writer = new StreamWriter(SettingPath);
ser.Serialize(writer, Settings.Instance);
writer.Close();
}
catch (Exception e)
{
Logger.ReportException("SaveSettingsFile", e);
Logger.ReportException("SaveSettingsFile->InnerException", e.InnerException);
}
}
An exception is thrown on ser.Serialize(writer, Settings.Instance) :
System.InvalidOperationException Msg=There is an error in XML document (0,, 0). ->
InnerException: Object reference not set to an instance of an object.
My class has a default, empty constructor. I have tried using sgen. In a simple testbed application I wrote, serialization works fine... it's only when the Assembly is dynamically loaded does it fault.
Furthermore, from these two threads,
http://forums.gbpvr.com/showthread.php?30384-XMLSerializer-Problems-with-Plugins , http://forums.gbpvr.com/showthread.php?32197-System.XML-Deserialization
I know I can change the type from BindingList to ArrayList and have it work; however, I would like to keep databinding working as there are quite a bit of settings to manage.
Any input would be appreciated.
John Saunders' comment appears correct for this so far, you likely are not initializing MyClasses.
Since you say it works fine with SGen, you might also want to check if it has something to do with the compile flags, like maybe try setting it to release and see if that changes things.
Sorry to pull this up from the grave, but I ran into a similar issue again today and this was the first google result, so I thought I'd share.
This appears to be a generic case of an issue I had ran into awhile back when attempting to write an MSBuild Custom task (basically a plugin). I posted about it on the MSDN Forums.
Here is the most relevant part of the comment, simply substitute MSBuild for any application that has a plugin architecture, and the CruiseControl.NET library for any library that uses the XmlSerializer:
The Library in question is the Remoting Library for ThoughtWork's CruiseControl.NET, this library uses .NET Remoting with some Client Activated Objects. When you go to attempt to activate the object, .NET's Binary Serializer goes to work trying to figure out where to load the ThoughtWorks.CruiseControl assembly from so it can read the object (ThoughtWorks.CruiseControl.Remote.dll in 1.4.4SP1 which we're using) the problem is the Binary Serializer's GetAssembly Logic doesn't realize that MSBuild has performed some voodoo to load the custom assembly from an arbitrary location.
Therefore it defaults to attempting to look in the same directory that the program is located in as per http://msdn.microsoft.com/en-us/library/yx7xezcf%28v=VS.100%29.aspx which means if it didn't find it in the GAC its going to start probing from where the program was launched, and because MSBuild was launched from the %FrameworkDir%/%FrameworkVersion% folder it is unlikely to find the assembly it's looking for.
This explains why you wouldn't see this issue in a console application (the assembly most likely sat right next to the console app)
The solution offered in the MSDN Forum post is also applicable here, basically they added an additional event handler to attempt to probe from a known location, again I have quoted the relevant portions:
For anyone who cares, the workaround is to register a handler for the AppDomain.AssemblyResolve event, and to the Assembly.LoadFrom() there.
Personally this scares me, but it is the only solution I have found that works, a bit more googling hasn't shown me a Microsoft Connect issue for this, but it is most likely not going to be fixed or is by design.
I made a COM object with c# and let VS register it for me. I can see it in registry and if I make a test app I can add a reference to it and it works as expected with all the methods available and functional.
Now If I try and use it in a MSMQ rule nothing happens. It will not be invoked. Is this because it is a .NET assembly? Is it because I do not have VS Pro? Do you have any idea at all?
You haven't by any chance registered your component on a mapped network drive have you? MSMQ runs in a different WinStation to the interactive WinStation. Network drives that are mapped in the interactive WinStation are not visible in other WinStations which could result in the symptom you described (component not found).
You need to check the system event log for error messages (eventvwr.exe). If your component is registered and MSMQ is properly configured to activate your component but it fails, most likely the problem is with permissions. The event log should contain the details of the prolem.
Update!!!
I was messing around with this again. I created a simple EXE to fire when a message is received. It accepts 2 string parameters.
I forgot to pass the parameters the first time and I get the SAME error as I was discribing before. About the COM object not being found. I passed the parameters and it worked fine.
I thought I was passing the parameters to my COM object just fine, but maybe not. Maybe I'm doing something wrong. I will create a COM with no parameters and see if I can force the COM to invoke.
If anyone as examples of creating objects to accept parameters, please let me know.