将应用程序清单嵌入到 VB6 exe 中 [英] Embedding an application manifest into a VB6 exe

查看:40
本文介绍了将应用程序清单嵌入到 VB6 exe 中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近浏览了一堆用 VB6 编写的独立实用程序,以确保为 Windows Vista 及更高版本关闭注册表虚拟化.我为每个 exe 创建了一个独立的清单文件,适当地设置了 requestedExecutionLevel(其中一些需要修改 HKEY_LOCAL_MACHINE 注册表项,其他不需要),并对其进行了测试.它们似乎都可以正常工作.

我只剩下一个小问题了.由于它们是独立的实用程序,人们习惯于在网络上复制它们并手动运行它们.如果有人忘记复制清单文件和 exe,那么 exe 将默默地写入虚拟化注册表项而不是真实注册表项,并导致难以调试的问题.

显而易见的解决方案是将清单作为资源嵌入到 exe 中.我在网上看到的所有文章都告诉你嵌入资源是这样的:

#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1#define RT_MANIFEST 24CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "app.manifest"

这应该工作得很好,除了 VB 编译器总是创建资源 ID = 1 的应用程序图标.当我尝试上面的代码时,Windows 拒绝运行 exe,抱怨资源错误(我会更新这个稍后发布详细信息).我尝试将资源 ID 更改为另一个数字,之后 Windows 成功运行程序但无法识别清单内容.

有谁知道让嵌入式清单在 VB6 exe 中工作的方法,还是我应该坚持使用外部文件?

更新 1

上面给出的文本是.rc 文件的全部内容.我将它编译成这样的 .res 文件:

"%ProgramFiles%Microsoft Visual StudioVB98Wizards c.exe"/r/fo "Resources.res" "Resources.rc"

并将其嵌入到 VB6 项目文件中,如下所示:

Type=Exe参考=*G{00020430-0000-0000-C000-000000000046}#2.0#0#................WINDOWSsystem32stdole2.tlb#OLE 自动化形式=Main.frmResFile32="资源.res"IconForm="FMain"启动="FMain"帮助文件=""Title="Windows Vista 注册表测试 - VB6"ExeName32="RegistryTestVB6.exe"路径 32=""命令 32=""名称="RegistryTestVB6"帮助上下文ID="0"兼容模式=0"主要版本=1次要版本=0修订版本=0自动增量版本=0服务器支持文件=0VersionComments="Windows Vista 注册表测试 - VB6"版本公司名称=""VersionFileDescription="Windows Vista 注册表测试 - VB6"版本法律版权=""VersionProductName="Windows Vista 注册表测试 - VB6"康德康="编译类型=0优化类型=0FavorPentiumPro(tm)=0CodeViewDebugInfo=0无锯齿=0边界检查=0溢出检查=0FlPointCheck=0FDIVCheck=0未圆整FP=0启动模式=0无人值守=0保留=0ThreadPerObject=0MaxNumberOfThreads=1

当我将编译好的exe读入VS2008资源编辑器时,是这样的:

RegistryTestVB6.exe图标1 [中性]RT_MANIFEST1 [英语(美国)]版本1 [英语(美国)]

当我在 VS2008 中构建一个完全等效的 VB.NET 测试应用程序,然后将其加载到资源编辑器中时,它看起来像这样:

RegistryTestNET.exe图标32512 [中性]RT_MANIFEST1 [中性]版本1 [中性]

更新 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 为我指明了正确的方向.可惜我不能把你们俩都标记为答案!

解决方案

有趣的是,我最近不得不做同样的事情.按照 Christian 描述的步骤,我第一次完成了它.为了繁荣,这是我遵循的整个工作流程:

  1. 按照原始问题中的描述创建了一个 RC 文件
  2. 创建了一个 app.manifest,保留了空白字符,这对于它的工作非常重要.如之前的答案所述,文件大小必须是 4 的倍数.

  3. 按照原始问题中所述针对 rc 运行 RC.EXE 以生成 .res 文件

  4. 编辑了我的 Project.VBP 文件,在顶部附近添加了以下行:

<块引用>

ResFile32="Resources.res"

  1. 在标准vb6环境下构建EXE.当部署在 vista 或 win7 机器上时,会显示盾牌并提示用户以管理员身份运行.在 Studio 中打开 EXE 文件时,我验证了资源.

  2. Notepad++ 告诉我 app.manifest 文件的编码是 ANSI.它在文件开头没有包含字节顺序标记.

如果您仍有问题,请告诉我,我会尽我所能与您分享.除此之外,除了 在我的机器上工作,我不知道该告诉你什么!

I have recently gone through a bunch of standalone utility apps written in VB6 to make sure that registry virtualization is turned off for Windows Vista and above. I created a standalone manifest file for each exe, set the requestedExecutionLevel appropriately (some of them need to modify HKEY_LOCAL_MACHINE registry keys, others do not), and tested them. They all appear to work correctly.

I have only one small problem remaining. Since they are standalone utilities, people are used to just copying them around the network and running them manually. If anyone forgets to copy the manifest file as well as the exe, then the exe will silently write to the virtualized registry key instead of the real one and cause hard-to-debug problems.

The obvious solution is to embed the manifest into the exe as a resource. All the articles I have read on the net tell you to embed the resource like this:

#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1
#define RT_MANIFEST 24
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "app.manifest"

This should work just fine, except that the VB compiler always creates the application icon with resource ID = 1. When I tried the above code, Windows refused to run the exe, complaining about a resource error (I'll update this post with the details later). I tried changing the resource ID to another number, after which Windows ran the program successfully but did not recognise the manifest contents.

Does anyone know of a way to get an embedded manifest to work in a VB6 exe, or should I just stick with an external file?

UPDATE 1

The text given above is the whole content of the .rc file. I compile it to a .res file like this:

"%ProgramFiles%Microsoft Visual StudioVB98Wizards c.exe" /r /fo "Resources.res" "Resources.rc"

And embed it in the VB6 project file like this:

Type=Exe
Reference=*G{00020430-0000-0000-C000-000000000046}#2.0#0#................WINDOWSsystem32stdole2.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

When I read the compiled exe into the VS2008 resource editor, it looks like this:

RegistryTestVB6.exe
    Icon
        1 [Neutral]
    RT_MANIFEST
        1 [English (United States)]
    Version
        1 [English (United States)]

When I construct an exact equivalent VB.NET test app in VS2008, then load that into the resource editor, it looks like this instead:

RegistryTestNET.exe
    Icon
        32512 [Neutral]
    RT_MANIFEST
        1 [Neutral]
    Version
        1 [Neutral]

UPDATE 2

Testing - the .NET exe runs fine on both Windows XP and Windows 7. However, the VB6 exe produces the following error on XP:

This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem.

and the following error on 7:

The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.

Looking in the event log I see the following entry:

Activation context generation failed for "RegistryTestVB6.exe". Error in manifest or policy file "RegistryTestVB6.exe" on line 10. Invalid Xml syntax.

Needless to say the XML isn't invalid, it's exactly the same file with the same encoding that I used for the .NET exe, and that one works.

RESOLUTION

The VB6 compiler does indeed require that an arbitrary text file included in a resource must be an exact multiple of 4 bytes. I simply added spaces to the XML until Notepad++ told me that the total file size including BOM was a multiple of 4.

Thanks to both Michael and Jim for pointing me in the correct direction. Just a pity I can't mark you both as the answer!

解决方案

Interestingly enough, I had to do the exact same thing recently. Following the steps Christian described, I got it to work the first time through. For prosperity, here is the entire workflow I followed:

  1. Created a RC file as described in the orginal question
  2. Created a app.manifest, preserving whitespace characters, which are VERY IMPORTANT for this to work. As stated in previous answers, the file size must be a multiple of 4.

  3. Ran RC.EXE as described in the original question against the rc to generate the .res file

  4. Edited my Project.VBP file to include the following line near the top:

ResFile32="Resources.res"

  1. Built EXE in standard vb6 environment. When deployed on a vista or win7 machine, the shield shows up and the user is prompted to run as administrator. When opening the EXE file in studio, I verified the resources.

  2. Notepad++ tells me that the encoding on my app.manifest file is ANSI. It did not include an byte order mark at the start of the file.

If you are still having troubles, let me know and I'll share whatever I can with you. Other than that, I'm not sure what to tell you other than Works on my Machine!

这篇关于将应用程序清单嵌入到 VB6 exe 中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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