【发布时间】:2010-02-02 08:57:20
【问题描述】:
我最近浏览了一堆用 VB6 编写的独立实用程序,以确保为 Windows Vista 及更高版本关闭注册表虚拟化。我为每个exe创建了一个独立的清单文件,适当地设置了requestedExecutionLevel(其中一些需要修改HKEY_LOCAL_MACHINE注册表项,其他不需要),并对其进行了测试。它们似乎都可以正常工作。
我只剩下一个小问题了。由于它们是独立的实用程序,人们习惯于在网络上复制它们并手动运行它们。如果有人忘记复制清单文件和 exe,那么 exe 将默默地写入虚拟化注册表项而不是真实注册表项,并导致难以调试的问题。
显而易见的解决方案是将清单作为资源嵌入到 exe 中。我在网上看到的所有文章都告诉你嵌入资源是这样的:
#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#define RT_MANIFEST 24
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "app.manifest"
这应该可以正常工作,除了 VB 编译器总是创建资源 ID = 1 的应用程序图标。当我尝试上面的代码时,Windows 拒绝运行 exe,抱怨资源错误(我会更新这个稍后发布详细信息)。我尝试将资源 ID 更改为另一个数字,之后 Windows 成功运行程序但无法识别清单内容。
有谁知道让嵌入式清单在 VB6 exe 中工作的方法,还是我应该坚持使用外部文件?
更新 1
上面给出的文本是.rc 文件的全部内容。我将它编译成.res 文件,如下所示:
"%ProgramFiles%\Microsoft Visual Studio\VB98\Wizards\rc.exe" /r /fo "Resources.res" "Resources.rc"
并将其嵌入到 VB6 项目文件中,如下所示:
Type=Exe
Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\..\..\..\..\WINDOWS\system32\stdole2.tlb#OLE Automation
Form=Main.frm
ResFile32="Resources.res"
IconForm="FMain"
Startup="FMain"
HelpFile=""
Title="Windows Vista Registry Test - VB6"
ExeName32="RegistryTestVB6.exe"
Path32=""
Command32=""
Name="RegistryTestVB6"
HelpContextID="0"
CompatibleMode="0"
MajorVer=1
MinorVer=0
RevisionVer=0
AutoIncrementVer=0
ServerSupportFiles=0
VersionComments="Windows Vista Registry Test - VB6"
VersionCompanyName=""
VersionFileDescription="Windows Vista Registry Test - VB6"
VersionLegalCopyright=""
VersionProductName="Windows Vista Registry Test - VB6"
CondComp=""
CompilationType=0
OptimizationType=0
FavorPentiumPro(tm)=0
CodeViewDebugInfo=0
NoAliasing=0
BoundsCheck=0
OverflowCheck=0
FlPointCheck=0
FDIVCheck=0
UnroundedFP=0
StartMode=0
Unattended=0
Retained=0
ThreadPerObject=0
MaxNumberOfThreads=1
当我将编译好的exe读入VS2008资源编辑器时,是这样的:
RegistryTestVB6.exe
Icon
1 [Neutral]
RT_MANIFEST
1 [English (United States)]
Version
1 [English (United States)]
当我在 VS2008 中构建一个完全等效的 VB.NET 测试应用程序,然后将其加载到资源编辑器中时,它看起来像这样:
RegistryTestNET.exe
Icon
32512 [Neutral]
RT_MANIFEST
1 [Neutral]
Version
1 [Neutral]
更新 2
测试 - .NET exe 在 Windows XP 和 Windows 7 上都可以正常运行。但是,VB6 exe 在 XP 上会产生以下错误:
此应用程序无法启动,因为应用程序配置不正确。重新安装应用程序可能会解决此问题。
7 出现以下错误:
应用程序无法启动,因为它的并排配置不正确。请查看应用程序事件日志或使用命令行 sxstrace.exe 工具了解更多详细信息。
查看事件日志,我看到以下条目:
“RegistryTestVB6.exe”的激活上下文生成失败。第 10 行的清单或策略文件“RegistryTestVB6.exe”出错。无效的 Xml 语法。
不用说 XML 不是无效的,它与我用于 .NET exe 的具有相同编码的文件完全相同,并且该文件有效。
分辨率
VB6 编译器确实要求资源中包含的任意文本文件必须是 4 字节的精确倍数。我只是在 XML 中添加了空格,直到 Notepad++ 告诉我包括 BOM 在内的总文件大小是 4 的倍数。
感谢 Michael 和 Jim 为我指明了正确的方向。可惜我不能把你们俩都标记为答案!
【问题讨论】:
-
不确定您的问题是什么,但不是图标。每类资源(RT_MANIFEST、RT_ICON)都有自己的 id 命名空间。你能给我们更多的 .rc 文件的文本吗?
-
我隐约记得 XP 和 Vista 希望清单具有不同的资源 ID。尝试使用 RESOURCE_ID 2,或者可能将相同的清单放在 ID 1 和 ID 2 中。
-
@JohnKnoeller 资源ID实际上是有含义的,可以产生不同的结果,详见here。
标签: vb6 resources uac manifest