通过准隔离COM消耗EXE服务器 [英] Consuming EXE server through quasi Isolated COM

查看:56
本文介绍了通过准隔离COM消耗EXE服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经能够使用清单,尤其是MSBuild任务GenerateApplicationManifest,以便我们的主应用程序使用隔离COM.我可以创建在所需DLL中实现的所有COM对象,而不必在客户端计算机上注册DLL.但是,我很贪心...

I have been able to use manifests and especially the MSBuild task GenerateApplicationManifest so that our main application uses Isolated COM. I can create all the COM objects implemented in DLLs that I need without having to register the DLLs on my client machine. But, I'm greedy...

通常,我们的应用程序套件还具有一些通过COM调用的独立应用程序.对于这些,据说您不能对EXE隔离的COM执行EXE.严格来说,这是对的,但是我已经掌握了90%的方法,在其他论坛上,我看到其他人提供了线索,以帮助人们实现其余的目的.

Our application suite also has some separate applications that are invoked through COM, generally. For these, it is said that you can't do EXE to EXE isolated COM. Strictly speaking, that is true, but I have gotten 90% of the way and on other forums I have seen others giving clues to get the rest of the way there.

对于我的EXE服务器,清单中有一个带有EXE服务器名称的条目,该条目中有一个子条目,以便当ATL服务器调用 LoadRegTypeLib()时,该调用将成功.那行得通.

For my EXE server, I have a entry in the manifest with the name of the EXE server and a sub entry in that entry so that when the ATL server calls LoadRegTypeLib(), the call will succeed. That works.

当然,棘手的部分是您不能在客户端应用程序清单中放置EXE服务器的条目,并期望 CoCreateInstance()成功(通过启动服务器EXE并执行所有其他操作)COM做的.)

Of course, the tricky part is that you cannot put a entry for the EXE server in the client application manifest and expect CoCreateInstance() to succeed (by launching the server EXE and doing all the other stuff COM does.)

我能够伪造很多东西,因为我知道要启动的EXE服务器.我可以先在客户端应用程序中调用 CreateProcess(),然后再调用 WaitForInputidle(),以便为客户端应用程序中的CoCreateInstance()准备好服务器.

I am able to fake quite a bit because I know what EXE server to launch. I can call CreateProcess() and then call WaitForInputidle() in the client app to get my server ready for CoCreateInstance() in the client app.

如果我调用 CoCreateInstance()并要求客户端应用程序中的 IDispatch 接口,则调用成功,并且我可以调用 Invoke()一切正常.

If I call CoCreateInstance() and ask for the IDispatch interface in the client app, the call succeeds and I can call Invoke() and everything works.

现在是贪婪的部分...

Now here comes the greedy part...

IDispatch可以正常工作,但我希望能够通过从IDispatch派生的双重接口进行调用.之所以要这样做,是因为我编写了很多代码,语法更简单,并且异常处理已经存在.

It's all well and good that IDispatch works, but I want to be able to call through my dual interfaces derived from IDispatch. I want to do that because I have lots of code written that way and the syntax is simpler and the exception handling is already there.

但是,当我为我的 IDispatch 接口上的双接口调用 QueryInterface()时,我得到了E_NOINTERFACE返回.我已经在服务器EXE的ATL服务器对象中设置了断点,并且可以确认在服务器端找到了接口并返回S_OK.因此,似乎无法以某种方式将接口编组回客户端.

However, when I call QueryInterface()for the dual interface on my IDispatch interface, I get an E_NOINTERFACE return. I have set breakpoints in my ATL server object in the server EXE and can confirm that on the server side, it finds the interface and returns S_OK. So, it seems like somehow the interface is not able to be marshalled back to the client.

所以,问题是,如何获得自定义/双重界面的 QueryInterface()才能成功?我已经尝试在客户端清单(和服务器清单)中使用< comInterfaceProxyStub> < comInterfaceExternalProxyStub> 的各种组合来尝试编组接口,但我是仍然在我的客户端中看到 E_NOINTERFACE 返回.

So, the question is, How can I get the QueryInterface() for my custom/dual interface to succeed? I've tried various combinations of using <comInterfaceProxyStub> and <comInterfaceExternalProxyStub> in my client manifest (and server manifest) to try and marshal the interface, but I am still seeing the E_NOINTERFACE return in my client.

几年前,我在另一个论坛上看到了汉斯·帕桑特(Hans Passant)的一则评论,内容是可能需要单独的代理/存根DLL来封送接口,但没有太多细节.

I saw a comment by Hans Passant from several years ago in a different forum about maybe needing a separate proxy/stub DLL to marshal the interface, but there wasn't much detail.

是否有可能在免注册的情况下解决此问题?是否需要创建代理/存根库?如果是这样,清单条目在我的客户端应用程序(和/或服务器应用程序和/或代理/存根DLL)中是什么样的?

Is it even possible to solve this in a registration free context? Is it necessary to create a proxy/stub library? If so, what would the manifest entries look like in my client application (and/or server app and/or proxy/stub DLL)?

推荐答案

如果您有代理/存根DLL,请将其作为 file 元素包含在其子 comInterfaceProxyStub 中它处理的每个接口的元素(不要忘记 threadingModel 属性).

If you have a proxy/stub DLL, include it as a file element with a child comInterfaceProxyStub element for each interface it handles (don't forget the threadingModel attribute).

如果您有类型库,请将其作为带有子子元素 typelib file 元素包括在内,并为每个元素添加 comInterfaceExternalProxyStub 元素接口在类型库中(不要忘记 tlbid 属性),其中 proxyStubClsid32 是自动化封送处理程序:"{00020424-0000-0000-C000-000000000046}".

If you have a type library, include it as a file element with a child typelib element, and add a comInterfaceExternalProxyStub element for each interface in the type library (don't forget the tlbid attribute), where proxyStubClsid32 is the automation marshaler: "{00020424-0000-0000-C000-000000000046}".

例如,如果您使用标准封送处理(代理/存根DLL):

For instance, if you use standard marshaling (proxy/stub DLL):

<assembly ...>
    <file name="myps.dll">
        <comInterfaceProxyStub iid="{iid1}"
                               name="IMyDualInterface1"
                               baseInterface="{00020400-0000-0000-C000-000000000046}"
                               numMethods="8"
                               proxyStubClsid32="{proxyStubClsid32}"
                               threadingModel="Free"
                               />
    </file>
</assembly>

如果使用类型库封送处理:

If you use type library marshaling:

<assembly ...>
    <file name="mylib.tlb">
        <typelib tlbid="{tlbid}"
                 version="1.0"
                 helpdir=""
                 />
    </file>
    <comInterfaceExternalProxyStub iid="{iid2}"
                                   baseInterface="{00020400-0000-0000-C000-000000000046}"
                                   numMethod="8"
                                   name="IMyDualInterface2"
                                   tlbid="{tlbid}"
                                   proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
                                   />
</assembly>

实际上, comInterfaceExternalProxyStub 适用于任何其他已注册(非隔离)的代理/存根.例如:

In fact, comInterfaceExternalProxyStub applies to any other registered (non-isolated) proxy/stub. For instance:

<assembly ...>
    <comInterfaceExternalProxyStub iid="{iid2}"
                                   baseInterface="{00000000-0000-0000-C000-000000000046}"
                                   numMethod="4"
                                   name="IMyInterface3"
                                   proxyStubClsid32="{proxyStubClsid32}"
                                   />
</assembly>

在这种情况下, {proxyStubClsid32} 是注册的代理/存根CLSID.

where, in this case, {proxyStubClsid32} is a registered proxy/stub CLSID.

如果我的记忆正确,可以支持Windows XP,那么我已经成功地尝试对代理/存根DLL中的接口使用 comInterfaceExternalProxyStub ,然后声明相应的 comClass 代理/存根 file 元素中的元素,实际上不需要 comInterfaceProxyStub 元素.

If my memory serves me right, back when Windows XP was still supported, I've successfully tried using comInterfaceExternalProxyStub for interfaces in a proxy/stub DLL and then declaring the respective comClass elements in the proxy/stub file element, effectively not needing the comInterfaceProxyStub element.

但是,这不是一个好习惯, comInterfaceExternalProxyStub 实际上应该仅用于外部代理/存根,因为它已被记录在案,听起来像允许COM基础结构不寻找激活所需的代理/存根时,使用隔离的CLSID.

However, this is not a good practice, comInterfaceExternalProxyStub should really be used only for external proxy/stubs, as the way it is documented, it sounds like the COM infrastructure is allowed to not look for in isolated CLSIDs when activating the required proxy/stub.

这篇关于通过准隔离COM消耗EXE服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆