C# Interop - can't create object - c#

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)

Related

Why do I get 0x80070002 error calling a C# COM object from VB when launched from C#?

I have a C# COM object in a dll that I have registered using regasm.exe.
I do a createObject on the COM object and call methods on the object in a vbs script run with cscript.
If I run this on the command line it all works properly, creates the object calls the method via com.
cscript.exe c:\mypath\myvb.vbs argument
I now am trying to run this same command from C#. I use the System.Diagnostics.Process methods
ProcessStartInfo si = new ProcessStartInfo();
si.Filename = "cscript.exe";
si.Arguments = "c:\mypath\myvb.vbs argument";
Process exe = ProcessStart(si);
...
When I run this way I get the 0x80070002 error , which is basically a file not found error. I dont understand why it is different from C# to the command line.
Edit - More Info
I am running on a 64bit OS. The C# COM dll was built with "AnyCPU" .
I used the 64bit regasm.
The cscript I used was from c:\windows\system32 so it was the 64 bit version.
From the command line if I deliberately use the 32 bit version of cscript I also get the 0x80070002 error. This leads me to suspect the problem from c# is related, but I still don't get it.
"File not found" is not the first kind of error you'd expect in this scenario. But it is certainly possible, you have to register the assembly twice. Once with the 64-bit version of Regasm.exe so that the 64-bit registry keys are written. And again with the 32-bit version, it writes the keys to HKLM\Software\Wow6432Node, where 32-bit client programs search for keys.
Which is easy to overlook of course, you never mentioned doing this so that's a Big Red flag. You'd normally get "Class not registered", that didn't happen, maybe there was an earlier registration we don't know about. Like Visual Studio registering it, you'd normally always favor it doing that way because it prevents registry pollution. Simple changes to the project or file can then trigger "File not found". Forgetting the /codebase option when you ran the 32-bit version of Regasm is another way.
Best thing to do is just not guess at this. File not found errors are very easy to diagose with SysInternals' Process Monitor. You'll see cscript.exe searching for the file and not finding it. The name of the file gives you a very strong hint what the underlying cause can be. Look at the trace from the bottom up to avoid drowning in the data. And pre-emptively ensure you use both versions of Regasm.exe because you know that's necessary.

ActiveX DLL Error

OK while I never thought in 2012 I would be writing my first ActiveX control (and yes there is a good reason for it) I am struggling with getting it running under Windows 7 (x64).
The Solution Short Story: I was missing /codebase from some of my regasm calls and also mixing up 32 and 64 bit processes, but that wasn't being helped by the standard VS2010 command prompt mixing up 32 and 64 bit paths for regasm and cscript.
The long story follows:
I have been bouncing between
Creating an ActiveX control in .Net using C#
(Oops I had the wrong link .. although it looks like the link I initially supplied was someone copying the original blog page)
Creating an ActiveX control in .Net using C#
and
C# ActiveX control (CSActiveX)
And I appear to be building the projects successfully (for the latter one I had to change the resource compiler location to the correct location).
For the first project I am using the suggested installer, for the second project I am trying to use regasm directly.
But after this it all goes down hill. I try and register the all's but either:
I have no idea how I should be registering them, or:
I have no idea how I should be registering them.
My test case has been a simple JScript file containing
var x = new ActiveXObject( "name of object" );
Which fails with the error:
test.js(1,1) Microsoft JScript runtime error: Automation Server can't create object
I am not sure if this is a permissions issue, or a 32 vs 64 bit issue or a combination.
A lot of sites offering help on ActiveX are assuming you will be accessing it via a web page , so I have tried looking at IE permissions (even though I want to load the control into a 3rd part program).
I know if I use either the 'framework' or 'framework64' versions of regasm I can control where in the registry entries get put - and I have seen some references to running cscript as either 32 or 64 bit (which possible affects what part of the registry is searched) depending on the cmd shell invoked (and I have tried both ways, as well as trying an "administrator" shell).
So basically at this point I have no idea what I am doing or what I should be doing.
My goal is to register an ActiveX control on Windows 7 x64 and have it be able to be loaded by:
A test .js script running from the default Windows command prompt
Load the same control into something like Excel 2007 VBA (for testing only)
Load the control into a 3rd part application (RSView Studio from Rockwell) and have it hosted within a VBA application (and I need to check if this isa 32 or 64bit program .. I suspect the former)
Notes
For the project that users the installer (Creating an ActiveX control in .Net using C#), it installs the code into "c:\program Files (x86)\" and looking with regedit I find entries under "Computer\HKEY_CLASSES_ROOT\Wow6432Node\CLSID\" which I believe is telling me that the DLL was installed as a 32 bit process. I have tried running my cscript test from both a 32 and 64 bit cmd and they both fail. NOTE that the installer was creating the equivalent of "regasm /codebase" when it ran.
For the project where I tried using regasm to register it (C# ActiveX control (CSActiveX)), it has some additional code for registering an ActiveX COM control. This code mentions registering 32 bit in-process servers (see ActiveXCtrlHelpers.cs)
(BTW I'm also cursing auto correct in Safari/Lion at the moment, keeps changing lower case "DLL" into "all")
Edit 2012-08-07
Prompted by Art's answer I discovered:
From standard VS2010 command prompt
When running 'regasm /codebase' through the standard VS2010 command prompt (and as administrator to allow regasm to perform changes), the entries got dumped into the registry under HKEY_CLASSES_ROOT\Wow6432Node\CLSID and the test scripts failed from the same prompt.
However I can see the ActiveX control in Excel 2007 (32 bit)
From x64 Win64 VS2010 command prompt
When running under the VS2010 x64 Win64 command prompt (again as admin) the registry entries appeared under HKEY_CLASSES_ROOT\CLSID but this time the test scripts worked from the same prompt and also from a standard Windows cmd prompt (however they fail from a 32 bit prompt)
But!! I can't see the active X control from Excel 2007 (32 bit)
Now I just need to figure out what the windows equivalent of the *nix 'which' command to ensure which regasm I am using) the 'where' command
Looking at the VS2010 and Windows 7 command prompts:
VS2010 (standard prompt): cscript => c:\windows\system32\cscript.exe
regasm => c:\windows\Microsoft.net\framework\v4.0.30319\regasm.exe
VS2010 (x64 Win 64): cscript => c:\windows\system32\cscript
regasm => c:\windows\Microsoft.net\framework64\v4.0.30319\regasm.exe
Windows 7 std. prompt: cscript => c:\windows\system32\cscript.exe
Windows 7 32 bit prompt: cscript => c:\windows\SysWOW64\cscript.exe
This is all starting to make some of my confusion understandable. I have been unknowingly mixing and matching 32 and 64 bit systems, but the VS2010 standard prompt didn't help either!
(and my latest peeve - VS2010 saving files as UTF-8 with BOM)
I was able to make this work both via IE and vbscript by doing the following:
Create .NET class library named 'ActiveXTest'
Add a class named MyObject which is defined as follows:
namespace ActiveXTest
{
[System.Runtime.InteropServices.ComVisible(true)]
[System.Runtime.InteropServices.ProgId("ActiveXTest.MyObject")]
[System.Runtime.InteropServices.Guid("df2dac4d-ba8a-4ecc-b76e-958c1bc32f1f")]
public class MyObject
{
public string HelloWorld()
{
return "This is Hello World from the COM component!";
}
}
}
Compile the class. Go to the folder where you compiled the class and do the following from a Visual Studio command prompt: regasm /codebase ActiveXTest.dll
To test from a .vbs script, create a file in notepad call test.vbs. type the following into the file:
Dim myObject
set myObject = CreateObject("ActiveXTest.MyObject")
MsgBox(myObject.HelloWorld)
Open a command prompt and navigate to where where you created the Test.vbs and type: wscript test.vbs. A dialog should be displayed stating "This is Hellow World from the COM component"
To test this from IE, I created a TEST.HTML file with the following contents:
<HTML>
<HEAD>
<script language="JScript" language="JavaScript">
var obj = new ActiveXObject("ActiveXTest.MyObject");
alert(obj.HelloWorld());
</script>
</HEAD>
<body>
<span>nothing to see here!</span>
<body>
</HTML>
Open the TEST.HTML file in IE. You will get a warning about the ActiveX control; just say Yes to allow the interaction. You will get an alert dialog stating "This is Hello World from the COM Component".
Similar steps can be used to make it work from a .js file or from Excel VBA. Note that if you change the COM method signature of the ActiveX assembly I believe you will need to re-register it.

Class not registered error from PHP

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.

c# OPC Automation gives 80040154

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.

COM on 64 Bit Platform

I'm using a 3rd party COM Library with C#, all works fine on 32 bit XP. I use tlbimp to create the wrapper, add a reference all works. However, when porting to our Server environment which is 64 bit Windows Server 2008, I've run into a road block.
The code below only runs properly when I right click and test it, ie run within the VS environment. The code does not work when compiled to a Console App, nor does the code work in an Assembly whether in test or called from a console App. In an attempt to get it working I'm running as Administrator and in a 32bit command window - still nothing grouper is always null, and no exception is thrown, indicating that GrpSvr.GrpCall is a valid Com Library name.
string sMessage = "no grouper";
GrpSvr.GrpCall grouper = Activator.CreateInstance(
Type.GetTypeFromProgID("GrpSvr.GrpCall")) as GrpSvr.GrpCall;
if (grouper != null)
sMessage = grouper.GroupInit(#"C:\CmdGrp.txt", true, true);
Console.WriteLine(sMessage);
Try using COM+ as host, and keep your application compiled for 64 bits. For more info see this link
It sounds like the 3rd party COM DLL is 32 bits only. You have to configure your app to run as 32 bits only, instead of any cpu.

Categories