The code below executes without problems in a 32bit c#-application.
object obj = system.Runtime.InteropServices.Marshal.GetActiveObject("Due.Application");
var due = (Due.IDueApplication2)obj;
Now, I try to get the same code working in a 64bit c#-application and therefore I followed the instructions at
http://www.gfi.com/blog/32bit-object-64bit-environment/ or http://www.codeproject.com/Tips/267554/Using-bit-COM-Object-from-bit-Application
Two cases when running the 64bit application
Due is not running and the first code-line fails with HRESULT: 0x800401E3 (MK_E_UNAVAILABLE). That's fine and happens in the 32bit version as well.
Due is running and in the first code-line obj receives a COM-object. But then, the second code-line throws an InvalidCastException because QueryInterface fails with HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG). (Obviously, this works in the 32bit version.)
Q What must I do, to make the cast in the 2nd code-line to succeed?
Edit As suggested by #HansPassant, I fired up the ProcessMonitor and monitored both the 32bit and 64bit application. I observed that the 64bit application when executing GetActiveObject (1st code-line) omitted accessing a COM-object specific dll (CreateFile, QueryBasicInformationFile, QueryNameInformationFile, ...) which in contrast the 32bit application did, even though I've added the according registry entries beforehand, i.e. AppID, DllSurrogate.
Edit1 I removed all the registry-entries I added and double-checked the results including the log-files of the ProcessMonitor. I didn't notice any difference - same symptoms as before.
Update In the directory of the 3rd party software I found a Due.tlb and I tried to create a runtime-callable-wrapper as hinted in 64 to 32 bit Interop - how?.
I created an Interop.due.dll with tlbimp.exe Due.tlb /out:Interop.due.dll. Unfortunately, when I replaced the original 32-bit Interop.deu.dll with the newly created platform-agnostic one my solution failed to compile (missing references).
The only thing which worked was an out-of-process solution. I implemented a 32-bit WCF-service which provides the access to the COM-objects for the 64-bit process. (Hence, I implemented the proxy myself.)
ad Update
good news
By utilizing the information in this post I was able to regenerate a platform agnostic version of the Interop.due.dll. Even though, TlbImp.exe warned me with warning TI3002 : Importing a type library into a platform agnostic assembly. This can cause errors if the type library is not truly platform agnostic.
bad news
The promised glue code was not provided and therefore the bridging of 64bit and 32bit did not work out. (The 32bit only version worked as before.)
Related
There is a third-party COM server DLL I need to include in my ASP.NET Core project. Adding via the Add > COM Reference worked fine and I end up with a COM > Interop.ThirdPartyServer under the Dependencies.
In my code I want to create an instance of one of the classes but it keeps failing with "Class not registered" even though it is.
I used
using ThirdPartyServer;
Type widgetType = Type.GetTypeFromProgID("ThirdPartyServer.Widget");
IWidget myWidget = (IWidget)Activator.CreateInstance(widgetType);
But I am seeing a "80040154 Class not registered" error.
I am sure it is registered, as I had to find the ProgID from the registry as it's not shown anywhere in the disassembled type library. In any case, I re-ran regsvr32 ThirdPartyServer.dll and that seemed to work with no errors, as it is a 32-bit DLL.
The 0x80040154 aka REGDB_E_CLASSNOTREG or "Class not registered" error usually means ... well, that the class is ... not registered. But the exact reason can be a bit complex.
COM clients and COM servers that run both in-process need to run with the same bitness, so both in x86 or both in x64. So:
If a COM client runs as x86, it talks to the x86 side of the
registry, so the COM server must registered in the x86 side of the
registry (regsvr32, regasm, custom reg code, etc. must run as x86).
If a COM client runs as x64, it talks to the x64 side of the
registry, so the COM server must registered in the x64 side of the
registry (regsvr32, regasm, custom reg code, etc. must run as x64).
Note 1: for out-of-process communications x86 clients or servers can talk to x64 servers or clients. That's one benefit of COM.
Note 2: the .NET "Any CPU" compilation feature allows to use the exact same binary for x86 and x64 but this binary still needs to be registered in the needed registry side, or in both registry sides if x86 clients and x64 clients support is needed.
I'm trying to instantiate a COM object, defined in a x86 dll written in Borland C++, in a testing program i write in C# (.net 4.7.2). The COM dll (server) is working, I have a windows service also written in C++ Borland that can use it and instantiate a COM object from the class (using CoCreateInstance). The dll is registered and the InprocServer32 entry has the correct path to the dll. There is no coclass existing in a typelib, only interfaces (those exist in the typelib). I have used the TlbImp to create dll:s which i reference in the c# project. In the project the target platform is set to x86. The way i try to instantiate an object is:
var comType = Type.GetTypeFromProgID("ins.MyComType");
object comObj = Activator.CreateInstance(comType);
however the second line gives me
"Exception thrown: 'System.IO.FileNotFoundException' in mscorlib.dll"
with the message 'Retrieving the COM class factory for component with
CLSID {C4363C5E-3831-46DF-8701-60C8D1B612BA} failed due to the
following error: 8007007e The specified module could not be found.
(Exception from HRESULT: 0x8007007E).".
It does not matter if i try to run the app as administrator. I have a vague memory of trying out a similar thing a couple of years ago and that it at that time worked. It was probably on a Win 7 machine (might even have been a 32-bit system). I have tried to open the project in DependencyWalker but i'm not sure what i'm looking at. I get a couple of errors:
*Error: At least one required implicit or forwarded dependency was not found.
*Error: Modules with different CPU types were found.
*Error: A circular dependency was detected.
*Warning: At least one delay-load dependency module was not found.
*Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module.
Does any one have any idea on what it could be causing the exception? Or if i could get some hints as of how to dig deeper into dependencywalker? I get a gigantic tree of systemassembly stuff but i cannot see any obvious assembly standing out, though DW refers to many of them as being 64 bit. My guess is some dependent dll(s) somewhere should be x86 but which one(s). Is there a redist similar thingi i should have installed for this to work?
best regards
/Erik
You should write a simple VBScript that contains these lines:
set obj = CreateObject("ins.MyComType")
MsgBox TypeName(obj)
Name the file test.vbs
Execute the command:
c:\windows\syswow64\wscript.exe test.vbs
Using the version from syswow64 ensures that it uses the 32-bit version of wscript.exe which can instantiate 32-bit COM objects. The version in c:\windows\system32 can only instantiate 64-bit In-process COM objects in DLLs...you said your object is a 32-bit COM DLL server.
If the vbscript fails, it could be that the object is not automation compatible--implements IDispatch. Otherwise you will get an error message why it fails.
If it succeeds, you will know there is probably nothing on the C++ side causing problems. You THINK this is the case...but where is the runtime for Borland C++? Is everything statically linked, or is some of it dynamically linked? If it is dynamically linked, where is it in the path? It could be that the C++ service you have has the library in its path so that when it loads your COM object, the library is available. But, when you try to load from a 3rd party, like .NET or VBScript then the path to the library manifests itself. Who knows? I'm just making suggestions.
If you use ProcMon, it can see where the problems are. It will show you what registry entries are being read and which files are trying to be loaded.
I'm hitting a wall that I understand. I have a simple COM server that I want to instantiate. I can do so with simple VBS or PS commands outside of my EXE:
$sms_client = New-Object -COM 'CPApplet.CPAppletMgr'
Set controlPanelAppletManager = CreateObject("CPApplet.CPAppletMgr")
In my C# code I tried early binding, late binding, a PS runspace/pipeline and lastly Process.Start( cscript myVBS ). In all of those scenarios it comes back with class not registered and fails.
//throws exception
CPAPPLETLib.CPAppletMgr cpAppletMgr= new CPAPPLETLib.CPAppletMgr();
// myType does not come back null
Type myType = Type.GetTypeFromProgID("CPApplet.CPAppletMgr");
// throws exception
object myObject = Activator.CreateInstance(myType);
Update: I can create the Scripting.FileSystemObject without issue. I don't need that... it was just a test.
I've tried compiling 32bit, 64bit. Running as standard user and elevated. I've tried registering the DLL again but something about my C# .NET EXE is doing something that it just can't see the COM. I even tried creating a brand new console app project and it does it there also.
Am I missing something that is a .NET 101 COM-Interop fundamental?
Retrieving the COM class factory for component with CLSID {096C5BA8-044B-4BAC-9914-144723BA4F2A} failed due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).
Update:
Setting the platform to x64 made the error go away. AnyCPU and x86 fail. Does this mean I have to create 2 versions of the EXE for my 32bit and 64bit workstations?
It doesn't necessarily mean you have to create two instances. You should be able to create just one as long as you make it AnyCPU. The thing is, you have to register it with the correct runtime. By default, Visual Studio registers AnyCPU with the 32-bit runtime on a 64-bit machine. If you make sure to run the regasm.exe with the 64-bit runtime and correct version of the runtime, then you should be able to call it from a 64-bit process.
However, in my shop we've generally compiled one for x86 and one for x64 and deploy the right one for the right platform.
I have third party DLL which I am using it in my application. when I run my application, I get Com Exception, Class not registered error.
Retrieving the COM class factory for component with CLSID
{6A587E64-35FE-47EA-99F2-BDE40978D81D} failed due to the following
error: 80040154 Class not registered (Exception from HRESULT:
0x80040154 (REGDB_E_CLASSNOTREG)).
I know there are lot of duplicate question on this exception but none of the answers have helped me so far.
I have verified Class Id (Guid) is present in Registry entry.
I have tried to re register DLL by using Regsvr32.exe but it did not fix the issue. I have Win 7 machine and have tried re register from both type of regSvr32.exe. One located in Sytem32 and other one in SystemWow64.
I am running my application by targeting platform to Any CPU. Anyway, I have tried it by running as X86 and x64. X86 is will not work in my case as I have someother DLL which are 64 bit dll. My third party DLL is also 64 Bit dll.
Additional info:
This is existing application which works fine in XP. I am moving it to Win 7 and that is when I am facing the issue...Third Party DLL which I am talking about comes with installer...I just install it and refer the DLL...I have got 64 Bit version from third Party and have installed that in Win 7 Machine and only have changed reference to point to 64 Bit version DLL. I am sure that path I am referring to is correct..Not single line of code is changed apart from reference.
Any ideas on what next I could do to solve this problem
I'm working with National Instruments Measurement Studio in C#, and I've come across a bit of a problem in deploying my application to a particular computer (running Windows 7). I've tried asking on the National Instruments forums, but haven't got any solutions yet - could anyone here give me some tips?
Essentially, I have deployed this application several times on a number of computers, but in this particular case I receive an error when running the program -
"System.DllNotFoundException: Unable to load DLL 'nianlys.dll': The specified module could not be found. (Exception from HRESULT: 0x80070007E)
I have ensured that nianlys.dll is present in C:\Program Files
(x86)\National Instruments\Shared\Analysis.
I have ensured that libiomp5md.dll and LV110000_BLASLAPACK.dll, the files from mkl.msm (nianlys.dll has a dependency on mkl.msm), are present. nianlys.dll also has a dependency on nimetautils.msm, but I'm not sure which dlls are included in this.
I have ensured the program is installed by running the setup.exe as an administrator (as opposed to running the .msi that is generated, see here).
I have ensured the computer in question is up to date with updates to the .net framework via windows update.
I have tried reinstalling the program several times, sometimes with a freshly-recompiled installer.
I have tried adding in the 64 bit nianlys.msm into the setup project manually - this throws an error because the TargetPlatform property of the setup project is set to x86. The 32 bit version is, of course, already present in the detected dependencies.
Interestingly, taking a copy of nianlys.dll from C:\Program Files (x86)\National Instruments\Shared\Analysis and inserting it into the directory the program is installed in throws up a different error - in this case, the error is:
"An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)"
Taking a copy of the 64 bit version of nianlys.dll from another computer (default location C:\Program Files\National Instruments\Shared\Analysis) and inserting it into the directory the program is installed in throws up a third type of error - "System.DllNotFoundException: Unable to load DLL 'nianlys.dll': A dynamic link library (DLL) initialization routine failed. (Exception from HRESULT: 0x8007045A)". It should be noted that this .dll was present before installing the program on the machines that the program works on, but is not present on the target computer that is throwing up problems.
Taking the same 64 bit nianlys.dll and inserting it into the location it was found on on another computer, C:\Program Files\National Instruments\Shared\Analysis, does not solve the original error.
Even more interestingly, I have tried to reproduce the error on a computer on which the program works - removing the x64 version of nianlys.dll throws up the original HRESULT: 0x80070007E error, whereas removing the x86 version causes a windows installer to appear when running the program.
On a computer upon which the program works with no problems, the windows task manager does not seem to indicate that the program is 32 bit (with the *32 suffix on the program name), despite the target platform being set to x86. It seems from all this that there is some issue with the nianlys.dll being used in both its x64 and x86 versions, despite the target platform only being x86.
I'm running out of ideas about what kind of thing I could try to solve this problem.
I suspect that even though the setup is for X86, the project itself is AnyCPU and thus runs as a 64bit process on 64bit systems and as a 32bit process on 32bit systems. As you said your DLL is in the Program Files (x86) folder I assume it is 32bit only, so you should compile your application explicitly as x86, too. It is your bullet #7 that leads me to this conclusion.
Just copying the nianlys.dll 64bit DLL doesn't seem to work as it seems to rely on other DLLs it then can't find. (bullet #8).
It may caused by the dependents of nianlys.dll are not found. You can diagnose this problem with the process monitor , one of the system internal tools. It can capture the loading/unloading DLL activities, so if something wrong, you can find it in the log.
Be sure to use the filter when use this tool, otherwise the log file will be huge.