2

Sorry, I'm very new to COM, and I'm trying to figure stuff out. So I created some test COM-object in C# based DLL:

using System.Runtime.InteropServices;
using System.Diagnostics;
using System;

[ComVisible(true)]
[Guid("<interface_guid>")]
public interface IMyTest {
    string Test();
}

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[Guid("<class_guid>")]
public class MyTest : IMyTest {
    public string Test() {
        var pro = Process.GetCurrentProcess();
        var mac = Environment.MachineName;

        return $"{mac} - {pro.Id} - {pro.ProcessName}";
    }
}

And I'm registering this COM C# based DLL using this code:

var asm = Assembly.LoadFrom("<path_to_the_dll>");
var reg = new RegistrationServices();

reg.RegisterAssembly(asm, AssemblyRegistrationFlags.SetCodeBase);

Now I can use this object from VBScript like that:

set obj = CreateObject("MyTest")
WScript.Echo(obj.Test)

This works fine, however I need to be able to access this COM object from other computers on the LAN. When I try doing it even on the same computer I get an error:

' Unable to create ActiveXObject
set obj = CreateObject("MyTest", "localhost")
WScript.Echo(obj.Test)

So the question is how do I register my COM DLL in the way that it will be accessable for calling from the other computers on the LAN? Can I make the COM DLL to always be hosted in the dllhost.exe process (COM Surrogate) instead of being loaded into the caller process?

user2102508
  • 1,009
  • 11
  • 23
  • 1
    It is not very obvious why you like to do this programmatically over using Regasm.exe /codebase. There is a obvious chicken-and-egg problem with that. But as long as you do, "path_to_the_dll" needs to be the path of the DLL as stored on the server. Like `\\servername\sharename\foo\bar.dll`. The code snippet is too brief to give any specific advice on how to ensure that path is correct. Do favor Regasm.exe – Hans Passant Feb 01 '18 at 10:50
  • @HansPassant I thought that doing RegisterAssembly call actually does the same as calling "regasm.exe /codebase". I tried registering my COM DLL with regasm.exe. The regasm said that types were registered, but the VBScript code above doen't work. The the HKCR\CLSID\ wasn't created. – user2102508 Feb 01 '18 at 11:05

1 Answers1

1

You can specify a DllSurrogate to accomplish this task. Use oleview to set the appropriate registry entries (see this answer for further details).

As an alternative, you could also create a new COM+ server application and add your DLL.

Note that you may have to adjust the DCOM / COM+ security settings to access your class remotely.

Aurora
  • 1,334
  • 8
  • 21
  • I added the DllSurrogate with oleview, and calling CreateObject("MyTest", "localhost") works well, MyTest class is hosted inside dllhost.exe process. However, when I try accessing this class from remote machine CreateObject fail with HRESULT 0x800A01AD. How can I fix it? Is there anything else that should be done in order to access the class from remote machine? – user2102508 Feb 07 '18 at 08:56
  • Probably an issue with your security settings. Check your DCOM & firewall settings on both the client and server machine. If in doubt, try to pass the IP address, instead of the server name, as the second parameter to `CreateObject`. Also note that you'll need to register the type library on the client. – Aurora Feb 14 '18 at 22:14
  • thanks, I registered the same type on the client and disabled Brandmauer on server. Now I'm getting the "Access denied CreateObject" error. On the server I checked that "Enable Distributed COM on this computer" is checked in Component Services. Is there anything else I need to check to make it work? – user2102508 Feb 15 '18 at 08:43
  • Yes, you'll need to setup the appropriate remote permissions via DCOM Config in Component Services. Take a look at [this](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683772(v=vs.85).aspx) link for details. – Aurora Feb 15 '18 at 18:56