I need to reference a Com DLL from within a Silverlight program. Since this is not allowed, I created a wcf service and put my reference to the Com in it.
This idea seems to work fine when I ran my wcf service from my local machine but when I publish the service to my server it failed to work. The error was “Object reference not set to an instance of an object” where I tried to instance the DLL.
Here problem line is
m_cloVB6Encryption = New VB6Encryption.cEncryption
VB6Encryption is a complicated one. It called another DLL which calls several others.
To try to isolate the problem I created a very simple VB6 component, this time I got the error
"Retrieving the COM class factory for component with CLSID {74FE605A-5861-41A0-BA13-27DDD9C2EBB8} failed due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))."
This is despite the fact that I manually registered the component and it was successful.
The problem line was cloSimple = New Simple.cSimple.
My computer runs Windows 7; the server runs Windows Server 2012 R2 Standard.
Presumably your COM component was build as 32bit...so when you register it is registered as a (InProc) 32bit COM component....(and can only be loaded by a 32bit application).
Your ASP.NET Website is most likely running in an AppPool that is set to be 64bit...thus it can't use the 32bit COM class.
There are 2 options (the clearest and easiest is option 1):
1) Get your IIS WebSite/Application to run as 32bit, so it can access your already registered 32bit COM component.
To make sure your website is running as 32bit too (instead of as 64bit)...change the DefaultAppPool to enable 32bit applications (or you can create a new AppPool which is 32bit specifically for that webservice/site and make it use it...if you don't want to affect other sites).
https://help.webcontrolcenter.com/kb/a1114/how-to-enable-32-bit-application-pool-iis-7-dedicatedvps.aspx
OR
2) Do some additional registration so that your COM class is available to 64bit clients too (you register it so it is run OUT OF PROCESS...so it can be consumed by either 32bit or 64bit clients....but you might not want that for perf reasons...and it might not always be possible)
http://www.gfi.com/blog/32bit-object-64bit-environment/
Related
I have a c# Framework 4.7.2 Com visible library that calls a web api.
Unit tests in the VS2017 C# IDE library work fine.
However if I try to call via VB6 I get
System.IO.IOException unable to read data from the transport connection: An existing connection was forcibly closed by the rempte
host.
System.Net.Sockets.SocketException
I am running Windows 10
I call as administrator
C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm /codebase /verbose /tlb:SBD.ComBridge.tlb C:\dev\SBD.ComBridge.dll
to create the .dll and .tlb
I also tried running regasm from the VS2017 command prompt as administrator
RegAsm reports that the libraries register successfully.
In Vb6 the (simplified) code is
Dim o As SBD_ComBridge.BridgeImplementation
Set o = New dBridgeImplementation
o.SetOrderDates id
set o = nothing
In BridgeImplementation the (simplified) code is
[DispId(25)]
[ComVisible(true)]
public void SetOrderDates(int Id)
{
PackAndSend.SetReadByInfo(Id) // calls freight service
}
I know that the code calling the service from within SetReadyByInfo works because my unit test passes when I run it in VS2017
Unfortunately I have been asked not to post the code. However I know that the vb6 code calls Com correctly because there are other methods I call without errors.
I had a similar issue with MYOB api and TLS the solution was to upgrade the Framework. However I can't upgrade the VB6 framework ( the large re-write is not an option) Probably I will just make a .Exe and shell out to it.
[Update]
The link Simon Mourier gave me solves it.
If I add
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
then my com call works on VB6
As the link points out,
This isn't a good solution since it hard codes what TLS version to
use, so it wouldn't use TLS 1.3 in future
As per the update section at the bottom of my question, a work around is to include
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
I need to investigate further for a more complete solution
We have been trying to install a COM DLL on a new server. The interface is Classic ASP. The Map Connector DLL seems to be the problem but that is as far as I am able to get.
We are unable to get the pages served by IIS to give anything other than a 500 error.
When tracing the ASP:
127. -ASP_SCRIPT_TRACE_COM_CALL_END
FilePath
C:\INETPUB\WWWROOT\MILER\GLOBAL.ASA
LineNumber
6
CurrentStatement
set g_pcmsrv=Server.CreateObject("PCMServer.PCMServer")
SizeOfStatement
55
0 ms
128. -ASP_LOG_ERROR
LineNumber
6
ErrorCode
ASP 0177 : 8007007e
Description
Server.CreateObject Failed
The DLL is PCMSRV32.DLL in c:\windows
GLOBAL.ASA:
Sub Application_OnStart
set g_pcmsrv=Server.CreateObject("PCMServer.PCMServer")
set application("g_pcmsrv") = g_pcmsrv
set g_pcmmapmgr=Server.CreateObject("Pcmgole.PCMMapMgr")
set application("g_pcmmapmgr") = g_pcmmapmgr
End Sub
Sub Session_OnStart
set Session("currentTrip") = application("g_pcmsrv").NewTrip("NA")
set Session("map") = application("g_pcmmapmgr").createMap()
End Sub
Sub Session_OnEnd
set Session("currentTrip") = Nothing
set Session("map") = Nothing
End Sub
Sub Application_Onend
Set application("g_pcmsrv")=Nothing
Set application("g_pcmmapmgr")=Nothing
End Sub
The advice below relates to both Server.CreateObject and CreateObject use in
vbscript jscript vba
The Web Server sections are specific to asp-classic but still worth reading.
What Causes This error?
Server.CreateObject Failed
is caused most commonly when Web Applications are moved from one Web Server to another without an understanding of external COM components that are in use and registered with the Web server.
From PRB: Server.CreateObject Returns HTTP 500.100 or ASP 0177 Error (0x8007007E)
This error occurs when you attempt to use the Server.CreateObject method to instantiate an object that is not registered on the local system.
Identifying the Source of the Error
If you are using COM components inside a ASP Web application you will see a line like this
set g_pcmsrv=Server.CreateObject("PCMServer.PCMServer")
Usually the error will point to the Set line which makes identifying the cause easier (luckily you have some nice trace code in place so it's even better).
What If You Don't Know Where the DLL Is Located?
Note: Please be careful when accessing the Windows Registry as it is very easier to inadvertently make changes that have serious consequences for the Operating System and in extreme cases will require a system restore or re-install / repair.
The string inside the CreateObject method is known as a ProgId and is used as an identifier to a key inside the Windows Registry that can be found inside the
Note: Windows Registry can be browsed in most versions of Windows using the regedit.exe also known as the Registry Editor. Be very careful when using this tool to browse the Windows Registry.
HKEY_CLASSES_ROOT
and by extension
HKEY_LOCAL_MACHINE\Classes
Whenever the ASP processor encounters a ProgId it attempts to talk to the Windows Registry and find a corresponding key that denotes the location of the registered COM accessible DLL.
HKEY_CLASSES_ROOT\PCMServer.PCMServer
A common approach to this is the key contains a subkey called CLSID which points to the Class GUID for the associated registered DLL. Once the GUID key is located in the
HKEY_CLASSES_ROOT\CLSID
hive it can be used to find the location by looking in the subkey
HKEY_CLASSES_ROOT\CLSID\{GUID from CLSID}\InprocServer32
where the location will be stored in the (default) value.
Example Using the ProgId - Scripting.FileSystemObject
Locate Scripting.FileSystemObject subkey in HKEY_CLASSES_ROOT
HKEY_CLASSES_ROOT\Scripting.FilesystemObject
Identify GUID from subkey CLSID
HKEY_CLASSES_ROOT\Scripting.FilesystemObject\CLSID
(default) - "{0D43FE01-F093-11CF-8940-00A0C9054228}"
Use GUID to find registered DLL subkey in HKEY_CLASSES_ROOT\CLSID
HKEY_CLASSES_ROOT\CLSID\{0D43FE01-F093-11CF-8940-00A0C9054228}
Check subkey InprocServer32 (default) value for the DLL location
HKEY_CLASSES_ROOT\CLSID\{0D43FE01-F093-11CF-8940-00A0C9054228}\InprocServer32
(default) - "C:\Windows\System32\scrrun.dll"
No ProgId for PCMServer.PCMServer in the Registry?
If you cannot find the corresponding ProgId in the registry it is likely due to one of two reasons we will elaborate on here.
The DLL is not registered.
The DLL is registered in the wrong area.
How to register COM DLL with Windows
COM DLLs can be registered and have the corresponding Registry entries created by running the regsvr32.exe tool from the Windows Command Prompt using elevated permissions (this varies from version to version of Windows).
Before we continue though the architecture of both the Operating System and the mode used by the ASP Web application are very important.
Most newer hardware is 64 Bit this creates a conundrum in Windows as it now has to support newer 64 bit architecture and still maintain support for 32 bit architecture. The solution Microsoft came up with was to split the OS in two, so we have 64 bit elements and 32 bit elements. The main OS programs are broken down into two folders (only on 64 bit OS because a 32 Bit OS doesn't have to contend with 64 Bit, even if the hardware is capable of it).
Note: On 32 Bit only systems just use the 64 Bit locations for both System Files and the Windows Registry.
On a 64 Bit OS the System Programs are located in
For 64 Bit programs
%SystemRoot%\System32\
For 32 Bit programs
%SystemRoot%\SysWOW64\
This is also applies to the Windows Registry
64 Bit
HKEY_CLASSES_ROOT
32 Bit
HKEY_CLASSES_ROOT\Wow6432Node
So for example on a 64 Bit version of Windows, the following command will register the PCMSRV32.DLL in the 32 Bit Registry and create the associated COM DLL registry keys.
C:\Windows\SysWOW64>regsvr32 "C:\Windows\PCMSRV32.DLL"
IIS Application Pool
As everything begins to support 64 Bit including IIS you still need to be able to support legacy applications that only support 32 Bit COM, so IIS introduced in IIS 6.0 (starting with Windows Server 2003, Service Pack 1) under the Application Pool settings the configurable property Enabled32BitAppOnWin64 which allows the Application Pool to run in 32 Bit mode on 64 Bit versions of Windows.
With this in mind before you register the COM DLL to know where you should be registering it you need to know whether the Application Pool is running in 32 Bit Mode. In IIS 7.0 and above you can just check this from the Application Pool properties inside the IIS Manager application. The setting is in the Advanced Settings under the General section and is called Enable 32-Bit Applications (can also be configured in the applicationHost.config using enable32BitAppOnWin64 under the <ApplicationPools> section).
If Enable 32-Bit Applications is set to False
The IIS Application Pool is running in native 64 Bit mode and any COM DLLs that need to be used by the ASP Web Application will need to support 64 Bit and be registered using the 64 Bit version of regsvr32.exe to be added into the 64 Bit registry.
C:\Windows\System32>regsvr32 "C:\Windows\PCMSRV32.DLL"
If Enable 32-Bit Applications is set to True
The IIS Application Pool is running in 32 Bit Mode and any COM DLLs that need to be used by the ASP Web Application will need to be 32 Bit COM DLLs and be registered using the 32 Bit version of regsvr32.exe to be added into the 32 Bit registry.
C:\Windows\SysWOW64>regsvr32 "C:\Windows\PCMSRV32.DLL"
Registering the COM DLL Using the Wrong Version of regsvr32.exe
For example, using
C:\Windows\SysWOW64>regsvr32 "C:\Windows\PCMSRV32.DLL"
to register the COM DLL with the 32 Bit registry on a 64 Bit version of Windows when the IIS Application Pool is not in 32 Bit Mode will cause the ASP 500.100 Internal Server error
Server object error 'ASP 0177: 8007007e'
Server.CreateObject Failed
COM DLL Checklist
What is the IIS Application Pool Advanced Setting Enable 32-Bit Applications set to, as it impacts on how you register the COM DLL?
Is the DLL registered using the architecture-specific version of regsvr32.exe (if Windows version isn't 64 Bit use the default) that reflects the setting of Enable 32-Bit Applications?
Does the Windows Registry contain a ProgId for the DLL in the architecture-specific location of
HKEY_CLASSES_ROOT
that reflects the setting of Enable 32-Bit Applications?
Does the InprocServer32 key contain the correct location for the DLL?
In the context of the account I'm using to access the COM DLL (ApplicationIdentity, LocalSystem, NetworkService etc), do I have permission to access both the physical DLL file and the registry entries?
Useful Links
PRB: Server Object Error 'ASP 0177:80040154' Server.CreateObject.
I have a .net 2 COM+ class library. It is installed on my machine running as the host server.
The COM+ object builds and registers, and I am able to call if via VB (open Excel and using dev mode added the reference, and then can call the object without any problems).
Now attempting to deploy to our test machine. Tried the following:
Export the COM+ object as Application Proxy
Export the COM+ object as Application Proxy with "Save application in COM+ 1.0 format."
After taking the msi and cab files to the client machine, ran the MSI. There were no errors on installation.
The object does show up in the registry (searched for it by GUID). The object does NOT however show up in the DCOM Config tree (also checked the COM+ tree as well just to make sure it is not there).
Looking at the win32 file in registry for the object, it shows it pointing to c:\Program Files\COMPlus Applications\ {GUID} \class.tlb This is valid as that is where the tlb is sitting, and the GUIDs match as well.
Does anyone know how to get this to work correctly?
Additional information:
The COM+ object is built via ClassInterfaceType.AutoDual as AutoDispose and None I could not get to work correctly.
Hi All,
I have created a Dotnet Application using Dotnet 4.0 Programming language as VB.Net4.0. I have a Windows Service which sends out Fax Document using FaxComexLib Com Component, i have its Inetrop.FaxComexLib.dll, it works great in Windows 7 and Window 2008 Server, i can send out Faxes without any problems.
I have a Legacy Client which Windows XP home with ServicePack3 , i installed my WindowsService there and the Service Works fine other than communicationg with the FaxComexLib Com Component. I tried Several Possible solutions, i copied the the Registry entry({571CED0F-5609-4F40-9176-547E3A72CA7C}) from windows 7 to windows XP, Still no luck
Here is my exception:
System.InvalidCastException: Unable to cast COM object of type 'FAXCOMEXLib.FaxServerClass'
to interface type 'FAXCOMEXLib.IFaxServer2'.
This operation failed because the QueryInterface call on the COM component for the interface with IID '{571CED0F-5609-4F40-9176-547E3A72CA7C}' failed due to the following error:
No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
at System.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc, IntPtr pCPCMD, Boolean& pfNeedsRelease)
at FAXCOMEXLib.FaxServerClass.Connect(String bstrServerName)
Any Solutions for this would be greatly appeciated.
Thanks In advance
Suresh
It's been a looong time since I used FaxComExLib, but if memory serves, you need to install the Fax printer or something for XP, it is not installed by default.
I'm calling a UpdateUser on AuthenticationBase class in the System.ServiceModel.DomainServices.Server assembly installed by the WCF RIA Services installer. This works on my Win 7 desktop but on my Win 7 laptop, I get the following exception.
Any ideas on what I ought to be looking for or how I can determine what is different between the two systems? Thanks.
System.MethodAccessException was unhandled
Message=Attempt by method 'System.ServiceModel.DomainServices.Server.ApplicationServices.AuthenticationBase`1<T>.IsReadOnly(System.Reflection.PropertyInfo)' to access method 'System.Linq.Enumerable.Cast<System.ComponentModel.DataAnnotations.EditableAttribute>(System.Collections.IEnumerable)' failed.
Source=System.ServiceModel.DomainServices.Server
StackTrace:
at System.ServiceModel.DomainServices.Server.ApplicationServices.AuthenticationBase`1.IsReadOnly(PropertyInfo propertyInfo)
at System.ServiceModel.DomainServices.Server.ApplicationServices.AuthenticationBase`1.UpdateProfile(T user)
at System.ServiceModel.DomainServices.Server.ApplicationServices.AuthenticationBase`1.UpdateUserCore(T user)
at System.ServiceModel.DomainServices.Server.ApplicationServices.AuthenticationBase`1.UpdateUser(T user)
It sounds like you do not have Reflection permission on the laptop instance.
Are you perhaps running it under another user account?
Have a look at the MethodAccessException docs.
Also, make sure both are running the same version of .NET as there are security changes introduced in .NET 4.