Using a COM object from an executable without registering

I am trying to modify an existing set of programs that uses an instance of a COM object for communication.

The COM server is actually and (optionally) an extension for the main application. Both are deployed to target systems with a simple copy.

Currently, both applications are deployed only locally in our offices (although the main application, the COM client, is more widely distributed among our clients), and we manually register the server. We need to reconfigure this for deployment in the cloud service, and so I look at COM without registering.

So far I have tried:

  • Writing manifests for the client and server. Unfortunately, we cannot deploy this solution, since the client is then strongly connected with the server application and cannot be deployed separately (which is the case with our clients).
  • Create a new activation context and read the server manifest from the resource. This works, but trying to instantiate an object throws an OLE " Error in the Dll" exception . Some search queries tell me this because there is DllgetClassObjectno export.
  • Export DllgetClassObjectfrom an executable file (just adding an export proposal to the project source using the built-in implementation from System.Win.ComServ). This leads to an access violation during a call (directly or through an activation context). I could not understand where the AV is.

, ( ):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
name="wgaticket.exe"
type="Win32"
version="1.0.0.0"
/>

<file name = "wgaticket.exe">

<comClass
    clsid="{E33A1F59-CEA2-463E-97B2-1CCDA66DA984}"
    />
<!-- comClass
    clsid="{E33A1F59-CEA2-463E-97B2-1CCDA66DA984}"
    threadingModel = "Apartment"
    /-->

<typelib tlbid="{414AE7FB-3025-40D8-B14C-2A29B6E42C29}"
       version="1.0" helpdir=""/>

</file>

<!--comInterfaceExternalProxyStub
    name="INewTicket"
    iid="{740BF585-3246-483E-9146-B6A8E49400B5}"
    proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
    baseInterface="{00000000-0000-0000-C000-000000000046}"
    tlbid = "{414AE7FB-3025-40D8-B14C-2A29B6E42C29}" /-->

  <dependency>
    <dependentAssembly>
      <assemblyIdentity
        type="win32"
        name="Microsoft.Windows.Common-Controls"
        version="6.0.0.0"
        publicKeyToken="6595b64144ccf1df"
        language="*"
        processorArchitecture="*"/>
    </dependentAssembly>
  </dependency>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="asInvoker"
          uiAccess="false"/>
        </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

, Spring4D, :

function getActivationContext: IActivationContext;
var
  actCtx: TActCtx;
begin
  result := TActivationContext.Create;
  zeroMemory(@actCtx, SizeOf(actCtx));
  actCtx.cbSize := SizeOf(actCtx);
  actCtx.lpSource := 'wgaticket.exe';

  actCtx.lpResourceName := MakeIntResource(1);
  actCtx.lpAssemblyDirectory := PChar(ModulePath);
  actCtx.dwFlags := ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID or ACTCTX_FLAG_RESOURCE_NAME_VALID;
  result.Handle := CreateActCtx(actCtx);
  if result.Handle = INVALID_HANDLE_VALUE then
  begin
    RaiseLastOSError;
  end;
  result.Cookie := 0;
end;

procedure TActivationContext.Activate;
begin
  CriticalSection.Enter;
  try
    if (FHandle <> INVALID_HANDLE_VALUE) and (Cookie = 0) then
    begin
      if not ActivateActCtx(FHandle, FCookie) then
        RaiseLastOSError;
    end;
  finally
    CriticalSection.Leave;
  end;

end;

class function CoNewTicket.CreateAsClient: INewTicket;
begin
  // GActContext is a global, lazy interface variable. It will be auto-created the first time GActContext.Value is referenced
  GActContext.Value.Activate;
  result := CreateComObject(CLASS_NewTicket) as INewTicket;
end;
+4
1

COM- "dummy", , , . , , , . . , .

, -, , . ( , ) .

0

Source: https://habr.com/ru/post/1649136/


All Articles