I've got two sample VFP9 OlePublic dlls that I'm calling from a .NET Core 2.1 project running full framework .NET 4.6.1. Everything is working fine locally but upon deployment to a Windows Server 2016 machine, I'm only able to instantiate an instance of a.dll or b.dll, not both. It seems the last one to be registered wins.
If I register a.dll then b.ll, I can instantiate an instance of b & vice versa.
Retrieving the COM class factory for component with CLSID {CF0998BA-54F1-40BD-BB92-4E938A77E1E5} failed due to the following error: 80004005 Unspecified error (Exception from HRESULT: 0x80004005 (E_FAIL)).
Define Class miked As Session OLEPUBLIC
FUNCTION HelloWorld as String
RETURN "Hello World"
ENDFUNC
FUNCTION Echo(thingToEcho as String) as String
RETURN thingToEcho
ENDFUNC
Enddefine
public void TestMikeDll()
{
new miked.miked();
}
I'm guessing I haven't configured/defined something correctly in my VPF9 projects? 🤔
publish profile:
update
So it's not the last one registered, it's the first one to get instantiated. If I successfully instantiate a.dll then b.dll fails but if I recyle the app pool & try b.dll first it succeeds & a.dll fails.
Give the AppPool identity write (maybe modify too) access to the location of the VFP COM Dlls. Apparently, it needs to dynamically create another DLL: [original name]r1.dll that has a file desc of "Microsoft Visual FoxPro 9.0 SP2 Runtime Library" (the purple box).
Go to properties on folder where COM DLLs live
Security Tab
Edit
Add
in enter the object names to select: IIS AppPool\[your AppPool name]
reference: MSFT doc page on giving AppPool identity file permissions
credit: this comment from Aloio Kraus lead me down the path:
the 5 of the error code is the Win32 error code which means access denied. I would run procmon and watch for registry/file accesses which fail. That should hint to the right direction what went wrong
Related
i m trying to build COM dll file using C# and VS2010 - framework 3.5-:
if i try building the project without performing Clean, it will build, however this works only before any cleaning operation, after cleaning the project i will get stuck with this error
Error 16 Cannot register assembly "C:\Users\User\Desktop\Demo[Demo]
SCPP T1\bin\Debug\PrinterPlugin.dll" - access denied. Please make sure
you're running the application as administrator. Access to the
registry key
'HKEY_CLASSES_ROOT\CLSID{B9162A23-45F9-47CC-80F5-FE0FE9B9E1A2}' is
denied. C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets 3912 5 PrinterPlugin
i have based the original files on FrameWork 4.0 then converted to 3.5 due to COM registration incompatibility. building with Framework 4.0 will build successfully but will produce "TYPELIB" file is missing while registering the library.
further elaboration, the old PrinterPlugin works like a charm based on framework 3.5, it would register correctly, and would function with no warnings or erros of what-so-ever, these errors started popping after adding some components from another SDK that have been distributed using framework 4.0 and uses other microsoft libraries, like bidispl.dll, ReachFramework... etc.
EDIT0
i already have tried starting the VS2010 as admin, from every location.
EDIT1
i have tried building a new project using Framework 3.5, and still facing the same error, even when executing the devenv.exe as admin from the Common7 > IDE folder.
Error 18 Cannot register assembly
"C:\Users\Ameer\Desktop\projects\PrinterPlugin without resize
17-05-2015\printerplugin without resize
10-05-2015\bin\Debug\PrinterPlugin.dll" - access denied.
Please make sure you're running the application as administrator.
Access to the registry key
'HKEY_CLASSES_ROOT\CLSID{B9162A23-45F9-47CC-80F5-FE0FE9B9E1A2}' is
denied. C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets 3912 5 PrinterPlugin
i m guessing this is something has to do with the compatibility between the two SDKs.
I have successfully got Reg-Free COM working using C++ and C# using manifest files i.e. early binding. I am now trying to get this working using late binding. The technique I have found, after much web searching, appears to be using "Microsoft.Windows.ActCtx".
An example I used to test this was MS's "Registration-Free Activation of COM-Based Components" found at http://msdn.microsoft.com/en-us/library/ms973913.aspx to generate the SideBySide example. I then attempted to use a scripting language; VBScript and Python however both have fail in the same way (also tried VBA). The VBScript example is given below:
Set actctx = CreateObject("Microsoft.Windows.ActCtx")
actctx.manifest = "C:\test\client.exe.manifest"
Set SBSObj = actctx.CreateObject("SideBySide.SideBySideClass")
wscript.echo SBSObj.Version
Using something like SysInternals' "Process Monitor" you can see that running the following command (Windows 7 x64):
C:\Windows\SysWOW64\cscript.exe //Nologo C:\test\VBRegFreeTest.vbs
appears to work by loading the manifests and attempt to start looking for the equivalent registry calls and fails to find them. So it appears to partially work. I've also copied wScript.exe to the local directory to rule out directory issues for running application and manifest files.
I've read Microsoft.Windows.ActCtx on Windows Xp and have included the "prodID" in the manifest but it still fails. The manifest files work correctly with C++ and C# examples.
I can't help feeling that the "Microsoft.Windows.ActCtx" has issues. Documentation on this is very limited. Any help on using manifest files with Python or VBScript would be very much appreciated. I would be interested to know if anyone has got "Microsoft.Windows.ActCtx" to work.
Your EXE must have manifest with dependency section describing name and version of COM server, e.g. SideBySide.dll.
If your EXE has internal manifest: Windows 7 will not read external manifest, if internal one exists (Windows XP looks firstly for external manifest).
On Windows 7 the internal manifest of EXE must be changed with dependency to COM server, or internal manifest must be removed from EXE. It is possible with mt.exe from Visual Studio.
SideBySide.dll and SideBySide.dll.manifest must be in the same folder as EXE.
SideBySide.dll.manifest must include progID of COM server in comClass section.
Example of VBS code, using DLL from: Registration-Free Activation of COM Components: A Walkthrough
Dim o
Set o = CreateObject("Microsoft.Windows.ActCtx")
//in example here is a manifest reference: o.manifest = "SideBySide.X.manifest"
//but it does not function by me. By me a dependency is described in manifest of EXE.
Dim obj
Set obj = o.CreateObject("SideBySideLib")
Call MsgBox(obj.Version())
Set obj = Nothing
Set o = Nothing
We've created a C# class library assembly and made it COM visible to be able to call its methods from PHP. This used to work fine, but now we wanted to install it on a Windows Server 2008 server and we keep walking into the error "Class not registered".
To rule out any dependency problems I made a tiny little test class library in C#. The class library is built for Any CPU and it is COM visible (also set COMVisible to true in AssemblyInfo.cs). The test class library only contains one class with one method. The class is called TestLib and the namespace is also called TestLib. The method is called Test and only returns a string.
What we have done is the following:
- built the TestLib.dll
- copied it to the Windows Server 2008 machine
- registered the dll with: regasm /codebase TestLib.dll
- the regasm tool returns a success message
- in PHP we simply try to create a new COM instance:
try
{
$test = new COM("TestLib.TestLib");
}
catch (Exception $e)
{
die($e->getMessage());
}
when we call this test script from either the browser or the commandline (php -f test.php) we get the error "Class not registered" in both cases
I also tried adding TestLib to the GAC by using gacutil -i, but to no avail; still the class not registered error.
Then I tried compiling the testlibrary with .NET 2.0 instead of 4.0 as the target framework, same result. The .NET framework 4.0 is installed on the server by the way.
Any ideas?
Okay, so after some more research I figured it out. The php.exe process is 32 bit. The COM visible assembly is compiled for Any CPU so it should be accessible to both 32 and 64 bit applications.
The problem is that on a 64 bit OS php.exe, and any 32 bit process for that matter, searches in HKEY_CLASSES_ROOT\Wow6432Node\CLSID instead of HKEY_CLASSES_ROOT\CLSID and in HKEY_LOCAL_MACHINE\Software\Classes\Wow6432Node\CLSID instead of HKEY_LOCAL_MACHINE\Software\Classes\CLSID. The registry entries in the Wow6432 keys aren't created by regasm that is shipped with .NET framework v4 on Windows Server 2008. On Windows 7 they are created, don't ask me why.
It also turned out that if I create a little test assembly for .NET v2.0 and register it with regasm that ships with .NET framework v2.0 that it does create the Wow6432Node entries on Windows 2008. Strange.
So my solution is to create a basic registry file on the server using:
regasm /regfile MyClassLib.dll
This creates a file MyClassLib.reg with only the 'normal' 64 bit entries. Then I exported the Wow6432Node keys from a Windows 7 machine and added it to that .reg file. Now when I import that reg file into the registry on Windows 2008 everything works fine.
For more info on the Wow6432Node entries check out: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724072%28v=vs.85%29.aspx
Hope this saves someone else some time and headaches.
If you are trying to call a 32-bit COM DLL on 64-bit Windows, you will need to register it.
Copy your 32-bit DLL to C:\Windows\sysWOW64
Run C:\Windows\sysWOW64\regsvr32.exe your_com_32.dll
A bit more info with screenshots.
I am a .Net developer. New to OPC. When I tried some samples of OPC Client all of them give this error. It seems the DLL is not registered it seems. But I don't know how and where to register this.
error: retrieving the COM class factory for component with CLSID failed due to the following error: 80040154
Even I tried this
regsvr32 Interop.OPCAutomation.dll",
but it also throws error like
The module "Interop.OPCAutomation.dll" was loaded but the entry-point DllRegisterServeer was not found.
Make sure that "Interop.OPCAutomation.dll" is a valid DLL or OCX file and then try again.
I have gone through so many existing forums. So many of them said to change the Platform Target to x86 and still I am having the same issue. FYI, I can see only see 'Active (Any CPU)' in the Platform option from the top of the Build tab of Project Properties.
Here are my environment details:
.Net 2005
OPCAutomation Weapper
Windows 7 64-bit OS
Dell Inspiron 1525 (I hope this is not a 64bit machine, but my engineer installed 64bit OS somehow).
Please help me.
Thanks in advance!
Just in case somebody is dealing with this problem (as I've recently been...) I get through it! After some time, I found out that it's something about the .NET framework running on 64-bit machines. As long as the.NET application works only with 32-bit CLR, we must set .NET framework to load CLR in WOW mode. To do so, type:
C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\Ldr64.exe SetWow
After this you should be able to run the applications.
You can go back and revert .NET Framework as it was before by typing:
C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\Ldr64.exe Set64
If the OPC Client Toolkit SDK (C++) is used, a problem with the remote registry service may cause this error as well.
On Windows 7, by default the Remote Registry service is set to manual and not started. Ensure that the Remote Registry service is started on all of the machines you want to deploy to. This can be done manually or using Group Policy.
The function GetCLSIDFromRemoteRegistry() uses the RemoteRegistryService in order to get the CLSID of an OPC Server. If this service is not started on the client machine, the OPC program may return the error 80040154.
The error you're getting is more than likely due to the OPC server not being properly registered. Make sure it is registered (usually by running it at the command line with a "/regserver" or "/service" parameter). There may also be security issues in which case you'd have to run 'dcomcnfg' (DCOM Config) to make sure the client has access to the server.
This question is a bit dated so I hope you figured it out by now, but I had the same exact issue and wanted to share my solution. In my case, I am using a Kepware server. If you compile and try to run a client application for this server using Interop.OPCAutomation on a machine that does not have the server installed, you will get a dll not registered error and "entry point not found" if you try to register the dll manually.
Solution: Make sure you've got the server installed and running.
Although this is an old post, I would like to share my solution.
My problem was that when I tried to install an application with the OPCAutomation.dll, it gave me 80040154 error because the class was not registered.
This is my solution, always with Administrator privileges:
Copy OPCDAAuto.dll into the "C:\Windows\System32" folder
On the cmd prompt type "C:\Windows\System32\regsvr32 opcdaauto.dll"
You should watch a message like this one:
image
Hope this helps!
The OPC dll only works in 32 Bits, my solution was to change the "Enable 32-Bit Applications" to True in the advanced settings of the relative app pool in IIS.
I've created a C# COM object, and am trying to instantiate it from VBscript (under Windows Scripting Host).
The assembly builds correctly, etc, and RegAsm claims that it is successfully registered. However, whenever I try to instantiate it in a .vbs script, I get:
Error: Could not creawte object named
"MyProgId.blah" Code: 80040154
I'm running Win7 x64 Ultimate, object built for .NET 3.5 with VS2010.
I also tried copying the compiled DLL over to a Win Server 2003 machine, and I get the same results there.
Help.
Also, of note: I can register, but not instantiate, any of our old VB6 COM DLLs. (Yes, I am running the script as administrator.)
Update
Just for grins, I created a test application that uses Type.GetFromProgID() to find and create the object:
Type t = Type.GetTypeFromProgID(progId);
if (t == null)
{
Console.WriteLine("Couldn't create object.");
}
else
{
var obj = Activator.CreateInstance(t);
Console.WriteLine("Successfully created Object: Type is [{0}]", obj);
Console.WriteLine("Calling method [{0}]\n\n", methodName);
var result = t.InvokeMember(methodName, BindingFlags.Default | BindingFlags.InvokeMethod, null, obj, null);
Console.WriteLine("Result: {0}", result);
}
This works correctly. Attempting to create the object from VBscript, however, still fails.
Argh.
Update, the 2nd
After running SysInternals ProcMon, I see quite a few registry queries looking for the progID and guid under HKCU\Software\Classes\..., where there is no mention of the object (when I look in RegEdit). There are quite a few NAME NOT FOUND errors.
I've tried registering with the %windir%\microsoft.net\framework\v4... and framework64 versions of regasm, with no effect.
I'm running Win7 x64 Ultimate
That's very relevant to COM issues like these. The error message means that the COM client could not find the registry information for the COM server. The 64-bit version of Windows has two VB-script interpreters, a 64-bit and a 32-bit version. Processes with different bitness have a different view of the registry, a 64-bit client cannot see 32-bit COM servers. And the other way around.
What matters is what version of Regasm.exe you used. There are two, one in C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe, another in Framework64. You by default run the 32-bit version which enters registration info in the 32-bit view of the registry. You should use the 64-bit version from Framework64 instead. Or use both, .NET creates COM servers that can run in both bitnesses.
If you still have trouble then use SysInternals' ProcMon tool to see where the script interpreter is looking for the CLSID key.
If you're running a 32-bit interface under a 64-bit OS, you can get around that VBScript error by using the wscript/cscript under \windows\syswow64 (instead of the default under \windows\system32) to run your script. That tripped me up for a day.
I think that it is possible you are looking at a security issue.
Check out this stackoverflow post and see if this solves your issue.
Cannot instanciate .Net COM object in classic ASP/VBScript page (Error ASP 0177)