Unable to instantiate COM+ objects installed via exported application - com

I have a COM+ application that has been exported to an MSI using Component Services and then installed on a test server. The web application (ASP) is unable to instantiate any of the objects it uses from the COM+ application.
The COM+ application consists of three DLLs built in VB6. There is one DLL each for data, application and presentation layers. The web application only uses objects from the presentation layer. The COM+ DLLs call into a couple of .NET DLLs exposed via COM.
When the web application runs, an HTTP 500 - Internal Server Error is returned. No errors appear in the application or system log.
I've tried instantiating the objects from VBScript using WSH.CreateObject and it works only for objects in the data layer. When trying to create object in the application or presentation layer I get the following error:
Error: Could not create object named "My.ProgId"
Code: 800A801D
Source: WScript.CreateObject
Because it fails from VBScript, I suspect that the ASP app is fine and that it is the COM+ application that has issues.
Extra Info
If I uninstall the COM+ application and try to run my VBScript to test instantiation, I get a different error.
Error: Could not locate automation class named "My.ProgId"
Code: 80020009
Source: WScript.CreateObject
Since the errors are different, it seems that COM is at least finding the COM+ objects when they're installed, it's just not able to instantiate them.
I've also tried monitoring the script with ProcessMon. I can see WScript.exe (via COM) querying the registry for the ProgID, and then the CLSID. Eventually the path to the DLL is pulled back and then svchost.exe and dllhost.exe query the registry for the same information using the CLSID and also getting back the path to the DLL. Eventually the DLL has a Load Image operation against it followed by the same for msvbvm60.dll. I don't see anything that points to a failure accessing the COM+ DLL.
I've now tried installing the COM+ application to another Win2k3 server and a Windows XP desktop. I'm getting the same result with being able to instantiate objects from the data layer DLL, but not from the application and presentation layer DLLs. I've also tried getting an old copy of the application layer DLL and I am able to successfully instantiate objects from it. However, when I compare the project files for the two different versions, nothing stands out as being a possible cause of this problem.

The application layer DLL was referencing a struct defined in a .NET assembly. The error was caused by the type library containing the struct not being registered on the deployment machine.
When building the .NET assembly in Visual Studio, it would create a type library for the assembly and register it. When the app was deployed, the .NET assemblies were registered using regasm /codebase <assemblyname.dll>. That would register the classes so that they could be instantiated, but it did not register any structs.
The solution was to use regtlib.exe to register the type library on the test server.
The error messages were of no help at all when trying to discover the cause of the problem. Come on Microsoft!!

Related

ASP - Server.CreateObject returns nothing, Classic ASP

Team,
The following code returns empty/null to myobj, in my classic ASP page while trying to invoke a dll component.
Set myobj = Server.CreateObject("MODULENAME.cCLASSNAME")
This is related to a DLL which is placed alongside this asp page under \Bin. The DLL is an Interop COM dll custom developed by a former colleague and currently there's no access to the code.
The DLL components are appearing in the regEdit under HKEY_LOCAL_MACHINE\SOFTWARE\Classes\ which makes me assume it is registered. However when I try to re-register using regsvr32, it shows that it was loaded but couldn't find DLLRegisterServer method. I use regAsm to register the component.
Any alternate approach that can be done here? Am I missing something?
If the file name starts with "Interop" or "AxInterop", it is likely a wrapper to a COM DLL, not the DLL it's self. The COM DLL must be registered on the system and then a dotNet application will use/create that wrapper so you can make calls to it.
What you need to do is find the DLL, not the Interop because you are not using dotNet in Classic ASP. Make sure it is registered on that computer (using regsvr32 without error) and then this should work.
Last note/hint, that dll created by ex-coworker was done in C or VB (not dotNet) right? If done in dotNet, it is not COM and you need to research "How to call a managed DLL from unmanaged code".

error "429" AcitveX Component Can't create object (in vb6)

I have one problem in vb6. I created a .tlb file in VB.net 2005 by adding Com class to project. I built the project, I got .tlb file and .dll files while building project, i selected "Register for Com interop" from project properties and built. It registered autometically and I can use created .tlb file in that PC in Vb6 working fine. if I deploy application to another PC and run I am getting "Error 429 ActiveX Component Can't create object" run time error. What I need to do? Please help me as soon as possible. I can't deploy the application to client due to above error.
one possible solution is to install .net frame work on client pc i never want to install .net framework any other solution will be most appreciatable.
If you've created a DLL in a .NET language (such as VB.NET), the target computer must have the .NET Framework installed in order to use the DLL.
This a hard and fast requirement, irrelevant of how you're utilizing the DLL, whether from a VB 6 application through COM interop or otherwise. It is also a hurdle you'll have to jump over first, before you worry about things like registering COM components, as Uday's answer suggests.
If you don't want a dependency on .NET, you need to use another environment to create the ActiveX DLL; either C++ or VB 6 are possible choices.
One option may be that, while deployment, you need to register that .tlb file in System Registry using regsvr32 command in command-prompt. Generally static libraries does not work until they are registered with System Registry.
You might have seen many programs register components during installation like 'Registering Type Components' or 'Registering COM Components' (for those who do networking especially). Those components are nothing but native COM dlls and tlbs.
so when creating deployment project, add some scripting login to register thode dlls and tlb to System registry using:
regsvr32 <path to tlb/dll>
you have to recursivey call this command for every dll/tlb you want to register with system. For example, if you have 4 dlls and 2 tlbs then you have to call it 6 times providing the path of dll and tlb one at a time.

COM DLL registration failed with TFS 2010

I have a C++ DLL project which is created in VS 2010. It is exposed as COM(ATL). I used this dll to another .NET Project as reference. C++ Project linker settings are set as follows:
­"Register Output" = Yes
"Per-user Redirection = Yes
I created a build definition to build these two projects in tfs 2010. C++ Project builds fine, but .NET project fails because the output dll of C++ project is not registered. Setting to "Per-User redirection" = false does not work. I also tried using WF activity 'InvokeProecss' to register the c++ dll using Regsrv32/batch file/my own exe etc, but I get exit code of 5. My TFS 2010 is in Windows 2008 Server R2. And I think, it's not running the process as admin.
If I generate a interop dll using tlbimp, and then I refer that interop in my .NET proejct, it works fine(oviously in tfs build, I need to add InvokeProecss to call tlb). But this is not acceptable as our general practice is to refer a COM dll directly from .NET proejct.
Can anybody please help about this?
Is there a way to run the tfs automated build activity 'InvokeProcess' as Administrator without prompting for user name/password?
By default, the TFS Build Service runs as the "Network Service" account which is a relatively low-privilege account. Alternatively, you can configure it to run as any domain account you like. I wouldn't recommend that as a solution to the problem you described, however. I would agree with Hans that, in this case, it would be better to use the type library importer (TlbImp.exe) to "reference" your COM server from your managed assembly.
If the COM object isn't changing, you can just use the type library importer to generate an interop assembly, check that in and reference it from your .NET project. If it is changing, you can add a post-build step to generate the interop assembly rather than using the InvokeProcess activity. As Hans pointed out, you can't actually reference a COM object directly from a managed assembly. Your reference is actually causing an interop assembly to get generated at build time after resolving the reference to the registered COM server.

Do I need to register the COM dll to be able to reference it on the .NET project?

I'm trying to reference a COM dll in visual studio by using the Browse tab and selecting the DLL. I noticed that if the DLL is registered on the system with regsvr32 I can reference it, but if it's not registered I receive an error selecting the dll file "A reference to 'file.DLL' could not be added. Please make sure that the file is accessible, and that it is a valid assembly or COM component."
We would like to keep the DLL not registered, so that we have less configuration needed on other development machines and on the development environments.
Is it too much to ask?
Thanks!
you need to register dll. you can set registration in your setup project or create a batch file for all these type of processes.
Note: Don't forget to unregister dll on uninstallation.
You'll need to register the dll because otherwise it would not be able to find the type library.
Adding the dll afterwards as a reference to you project will create the interop.XXXXmethod.dll assembly.
You need to have the COM server registered, period. You could take some measures to automate the process though and to unregister the COM server when it is not needed.
The same applies to daily builds. If you build a COM server and a .NET based client during the build you have to register the server prior to building the client. And you better unregister it as soon as the client is built. Adding these steps to the build sequence is not a problem at all.
You might be able to use Registration Free Com

XBAP uses unmanaged c++ COM server, Side by side deployment issue

I'm facing a the following situation:
I created a simple full trust XBAP application that refers to unmanaged c++ COM server (isolated).
After deployment I expect that XBAP application will discover the COM server dll that is placed in the same directory, but it is not.
I'm getting the following error:
Exception has been thrown by the target of an invocation. ---> System.Runtime.InteropServices.COMException (0x80040154): Retrieving the COM class factory for component with CLSID {970599E0-2673-11D3-A8A8-00105AA943DF} failed due to the following error: 80040154.
at Generation888.Generation888.Simple(Int32 num1, Int32 num2)
I verified that the folder where the XBAP was deployed contains the DLL and XBAP manifest that contains proper CLSID
If I created a simple C# Windows Form application and refers to the same COM dll, it works fine.
My question is does XBAP support Side-by-Side mechanism.
Thanks
I'm not terribly familiar with XBAPs so these are some general suggestions.
If your XBAP is in fact being launched as a separate executable since it's fulltrust (what does taskmgr say?), try using the "sxstrace.exe" tool from an elevated command line on Windows Vista or later to determine whether the XBAP manifest is actually being interpreted by the system. It's possible that if you first tried your application without a manifest or changed the manifest, the system cached this old information and you'll need to clear this manifest-state cache by touching the timestamp of both the manifest and the executable.
It's also possible that your executable has an embedded manifest, which would mean that the external manifest is being ignored. To check this open the executable up in Visual Studio and see if it has an RT_MANIFEST resource of ID 1.