使用代理 Windows 运行时组件的 64 位侧加载应用程序

Posted

技术标签:

【中文标题】使用代理 Windows 运行时组件的 64 位侧加载应用程序【英文标题】:64 bit side-loaded app to use Brokered Windows Runtime Components 【发布时间】:2017-12-11 06:22:52 【问题描述】:

我有一个 32 位 (x86) 侧载 Windows Store app,它与代理的 Windows 运行时组件一起工作,它运行流畅,可以启动桌面 exe、使用反射加载桌面 dll 等。

我想让这个侧面加载的应用程序 64 位。并且在将应用程序重建为 x64 后,它再也无法使用代理的 Windows 运行时组件。错误是

附加信息:

无法将“StoreAppBrokeredWindowsRuntimeComponent.DirectInvoker”类型的 COM 对象转换为接口类型“StoreAppBrokeredWindowsRuntimeComponent.IDirectInvokerClass”。此操作失败,因为 IID 为“50EA3FD3-2383-5445-4002-8CBCBED5DB0F”的接口的 COM 组件上的 QueryInterface 调用由于以下错误而失败:未注册类(来自 HRESULT 的异常:0x80040154 (REGDB_E_CLASSNOTREG))。

来自文档Brokered Windows Runtime Components for a side-loaded Windows Store app,

侧载应用程序可以是 64 位的(前提是同时注册了 64 位和 32 位代理),但这不是典型的。

问题:

如何构建 64 位代理?

VS template 只能构建 32 位 (Win32) 代理。如果把WindowsRuntimeProxyStub改成x64,它甚至不能编译——有一堆LINK错误。

所以到目前为止,32 位侧载应用程序、32 位代理 Windows 运行时组件和 32 位代理是唯一工作方法。

【问题讨论】:

【参考方案1】:

在 Microsoft 支持的帮助下,我成功构建了一个 64 位代理运行时组件,并在 64 位侧载应用程序中使用它。

为了更容易理解,只需使用以下 MS 示例项目。您根本不需要修改任何代码文件。但是,您需要先修复模板中的两个错误,请参阅此答案末尾的重要说明

Brokered Windows Runtime Components for side-loaded Windows Store apps - Server

Brokered Windows Runtime Components for side-loaded Windows Store apps - Client

构建 64 位代理组件和代理的步骤

    解压缩代码包(用于侧载 Windows 应用商店应用的代理 Windows 运行时组件 - Server.zip)并使用 Visual Studio 2013 打开解决方案(以管理员身份运行);

    SampleProxy项目的平台从Win32改为x64;

    打开SampleProxy Property->Configuration Properties->Preprocessor->Preprocessor Definitions,修改两个定义

WIN32->X64; REGISTER_PROXY_DLLWIN32->REGISTER_PROXY_DLL

    EnterpriseIPCServer项目的平台改为x64。

    编辑EnterpriseIPCServer的构建后事件命令行,将每次出现的x86Win32替换为x64,命令应该是这样的:

call "$(DevEnvDir)..\..\vc\vcvarsall.bat" x64

md "$(TargetDir)"\impl
md "$(TargetDir)"\reference

erase "$(TargetDir)\impl\*.winmd"
erase "$(TargetDir)\impl\*.pdb"
rem erase "$(TargetDir)\reference\*.winmd"

xcopy /y "$(TargetPath)" "$(TargetDir)impl"
xcopy /y "$(TargetDir)*.pdb" "$(TargetDir)impl"

winmdidl /nosystemdeclares /metadata_dir:C:\Windows\System32\Winmetadata "$(TargetPath)"

midl /metadata_dir "%WindowsSdkDir%References\CommonConfiguration\Neutral" /iid "$(SolutionDir)SampleProxy\$(TargetName)_i.c" /env x64 /x64 /h "$(SolutionDir)SampleProxy\$(TargetName).h" /winmd "$(TargetName).winmd" /W1 /char signed /nologo /winrt /dlldata "$(SolutionDir)SampleProxy\dlldata.c" /proxy "$(SolutionDir)SampleProxy\$(TargetName)_p.c"  "$(TargetName).idl"

mdmerge -n 1 -i "$(ProjectDir)bin\$(PlatformName)\$(ConfigurationName)" -o "$(TargetDir)reference" -metadata_dir "%WindowsSdkDir%References\CommonConfiguration\Neutral" -partial

rem erase "$(TargetPath)"

    首先构建EnterpriseIPCServer项目。

    然后构建SampleProxy 项目。

检查输出文件(Fabrikam.winmd 和 SampleProxy.dll)。

使用 64 位代理组件和代理的步骤

够棘手的是,64 位代理运行时组件根本不会使用。我们只需要 32 位代理运行时组件,但我们需要注册 both 32 位和 64 位代理。

将 3 个文件(32 位代理运行时组件 + 2 个代理)放在同一文件夹下,例如 C:\test。然后执行以下命令。

regsvr32.exe C:\test\SampleProxy_64.dll(我已经重命名了64位代理)

regsvr32.exe C:\test\SampleProxy.dll(这是 32 位代理)

icacls C:\test /T /grant "所有应用程序包":RX

然后在 64 位旁加载应用程序中,引用 32 位代理运行时组件。但要小心选择“reference”文件夹中的那个,不要引用“impl”文件夹中的那个。

我已将代码上传至this GitHub repository,供您参考。

重要提示

此示例项目中存在一些错误,这使得为 x86/win32 配置构建它成为一场噩梦。

EnterpriseIPCServer的x86配置中,post build事件中的以下命令包含无法识别的开关/x86,应该是/win32.

midl /metadata_dir "%25WindowsSdkDir%25References\CommonConfiguration\Neutral" /iid "$(SolutionDir)SampleProxy\$(TargetName)_i.c" /env win32 /x86 /h "$(SolutionDir)SampleProxy\$(TargetName ).h" /winmd "$(TargetName).winmd" /W1 /char signed /nologo /winrt /dlldata "$(SolutionDir)SampleProxy\dlldata.c" /proxy "$(SolutionDir)SampleProxy\$(TargetName)_p .c" "$(TargetName).idl"

SampleProxy 项目的 Win32 配置中,预处理器定义之一 REGISTER_PROXY_DLLWIN32 应该是 REGISTER_PROXY_DLL

【讨论】:

以上是关于使用代理 Windows 运行时组件的 64 位侧加载应用程序的主要内容,如果未能解决你的问题,请参考以下文章

从用户代理或 Javascript 检测 64 位或 32 位 Windows?

weixin dll 注释

Nginx 反向代理重定向到帐户/登录

报错:尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。

Windows64 系统下PythonNumPy与matplotlib 安装方法

Oracle 11g - 找不到客户端和网络组件 Windows Server 2008 x64