2010-02-02 223 views
15

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

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

显而易见的解决方案是将manifest作为资源嵌入到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,或者我应该坚持使用外部文件?

UPDATE 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测试应用程序,然后加载到资源edito R,它看起来像这个:

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直到记事本+ +告诉我,文件总大小,包括BOM是4.

感谢两个迈克尔和吉姆·多指着我在正确的方向。只是可惜我不能将你们都标记为答案!

+0

不知道你的问题是什么,但它不是图标。每类资源(RT_MANIFEST,RT_ICON)都有它自己的id名称空间。你能给我们更多的.rc文件的文本吗? – 2010-02-02 09:14:25

+0

我依稀记得有关XP和Vista希望在不同的资源ID的清单的东西。尝试使用RESOURCE_ID 2,或者可能在ID 1和ID 2中放入相同的清单。 – 2010-02-02 09:25:45

+0

@JohnKnoeller资源ID实际上有一个含义并可以产生不同的结果,请参见[here](http://blogs.msdn.com/b /junfeng/archive/2007/06/26/rt-manifest-resource-and-isolation-aware-enabled.aspx)以获取详细信息。 – takrl 2013-01-21 10:34:56

回答

8

有趣的是,我必须做同样的事情最近。按照克里斯蒂安所描述的步骤,我第一次通过了。对于propsperity,这里是整个工作流程我跟着:

  1. 创建一个RC文件作为原单问题
  2. 创建一个app.manifest具有以下内容描述:用于

ManifestImage http://img638.imageshack.us/img638/3364/manifesta.png 图片保留空白字符,这对于此工作非常重要。如在先前的答案指出,文件大小必须是4

  • 然RC.EXE如在原来的问题对抗RC来产生res文件
  • 描述
  • 编辑我Project.VBP文件以包括靠近顶部以下行:
  • ResFile32 = “Resources.res”

  • 内置标准EXE vb6 e nvironment。当Vista或win7的机器上部署,屏蔽显示出来,并会提示用户以管理员身份运行。当打开工作室的EXE文件,我看到了以下资源:
  • alt text http://img688.imageshack.us/img688/4879/finalresources.png

    如果您还是有问题,让我知道,我会尽我所能与大家分享。除此之外,我不知道要告诉你什么,除了Works on my Machine!

    +0

    谢谢迈克。我还没有机会测试这个,所以我问你:你的清单在文件的开头是否包含UTF-8字节顺序标记? – 2010-02-11 08:36:34

    +0

    基督徒 - 不,它不。事实上,Notepad ++告诉我,我的app.manifest文件的编码是ANSI。 – 2010-02-11 20:23:40

    8

    VB6具有任何资源元素中的异常行为必须是4的长度的整数倍。尝试用空格填充.RC文件,并查看是否改变了行为。

    此外,您可以使用VB6的IDE,而不是编辑VBP添加资源。效果可能相同,但资源编辑器是执行此操作的标准方法。

    +0

    对不起,我的意思是说,将MANIFEST填充到4的倍数。 – 2010-02-02 13:22:35

    +0

    谢谢吉姆,不知道。根据纯粹的巧合,根据VS2008十六进制查看器,我的清单资源条目已经是16个字节的确切倍数。我怀疑这可能是一个编码问题。我正在尝试不同的组合以查看哪些方法有效,稍后我会更新我的帖子。 – 2010-02-02 13:53:28

    +0

    @JimMack我知道这从我自己的经验来看是真实的,但是你有没有在任何地方看到过它的权威记录(例如,微软)? – 2012-10-19 17:16:20

    6

    使用Resource Compiler (rc.exe)是漫长的。在可执行文件中嵌入应用程序清单是一种非常简单的选项,无论是C++还是VB6还是其他任何语言。 The Manifest Tool (mt.exe)是专门为嵌入在二进制文件中的清单编写的,并且免费提供给Windows SDK。使用mt.exe的附加好处是它会自动处理任何必要的填充。

    在编译二进制文件后,只需运行以下命令行即可。我已经使用了Visual C++ 2005编译器内部使用的命名约定,其中清单文件名包含完整的程序名称并附有“.intermediate.manifest”。

    mt.exe -nologo -manifest "program.exe.intermediate.manifest" -outputresource:"program.exe;#1

    更新:我本人曾在自动生成过程,现在使用这种与VB6的可执行文件超过两年。它非常成功,我们已经从我们的回归测试中消除了特定于体现的操作系统兼容性测试。

    +0

    谢谢约翰,了解这样的工具总是有用的。 – 2011-07-13 07:13:15