gpt4 book ai didi

delphi - 以可执行的免注册方式使用 COM 对象

转载 作者:行者123 更新时间:2023-12-03 15:14:27 24 4
gpt4 key购买 nike

我正在努力尝试修改一组使用 COM 对象实例进行通信的现有程序。

COM 服务器实际上是主应用程序的(可选)扩展。两者都通过简单复制的方式部署到目标系统。

目前,这两个应用程序仅部署在我们的办公室本地(尽管主应用程序(COM 客户端)在我们的客户处部署得更广泛),并且我们手动注册服务器。我们需要重新设计它以在云服务上进行部署,因此,我正在研究免注册 COM。

到目前为止,我已经尝试过:

  • 为客户端和服务器编写 list 。不幸的是,我们无法部署此解决方案,因为客户端与服务器应用程序强链接,无法单独部署(我们的客户就是这种情况)。
  • 创建新的激活上下文并从资源中读取服务器的 list 。这可行,但尝试实例化对象会导致“Dll 中的错误”OLE 异常。一些谷歌搜索告诉我这是因为 DllgetClassObject 导出丢失。
  • 从可执行文件中导出DllGetClassObject(只需使用System.Win.ComServ中的内置实现将导出子句添加到项目源代码中即可。这会导致调用时发生访问冲突(直接调用或通过激活上下文调用)。我无法确定 AV 发生的位置。

这是我使用的 list (我以注释的形式在代码中留下了各种尝试):

服务器应用程序 list

<?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;

最佳答案

您可以创建 COM 扩展的“虚拟”版本,它具有与真实扩展相同的公共(public)接口(interface),但没有真正的功能。向该接口(interface)添加一个属性,您可以检查它是否是真实的。始终部署假人。在需要时用真实扩展替换虚拟扩展。

这似乎将您的部署策略与运行时建立激活上下文的方式分离。即,单个固定 list 文件(或嵌入式资源,以两者为准)始终有效。

关于delphi - 以可执行的免注册方式使用 COM 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38585509/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com