【问题标题】:How to embed a resource in a .NET PE executable?如何在 .NET PE 可执行文件中嵌入资源?
【发布时间】:2011-11-08 21:07:55
【问题描述】:

如何在 Visual Studio 2010 的 .NET PE(便携式可执行文件)中包含资源?

olden days 中,我们将创建一个资源脚本文件:

wumpa.rc

 jqueryjs      RCDATA    "jquery.js"
 SplashLogo    PNG          "Hello world.png"
 ReportLogo    RCDATA    "ReportLogo.png"
 Users         ICON         "User XP.ico"
 Toolbar       BITMAP       "StandardToolbar24_32bpp.bmp"

将该文件添加到项目中,编译器将编译.rc 文件;包括最终可执行映像中的资源。

什么是托管/.NET/Visual Studio 包含资源的机制?

另见


这些必须是标准资源;您知道每个人都可以将其视为资源的那种:

  • Resource Hacker 将显示为资源
  • PEView 将显示为资源
  • Internet Explorer 可以使用res protocol 读取(例如res://c:\foo\MyProgram.exe/PNG/SplashLogo

我尝试过但不起作用的方法:

  1. 将资源添加到Resources.resx 文件:

  2. Resources.resx文件添加资源,并指定Resource的构建动作:

    (也尝试过构建操作:Embedded Resource,如was suggested to me in 2008


更新:什么不起作用

我尝试将文件 (wumpa.rc) 添加到项目中:

wumpa.rc

SplashPNG   PNG   "Splash.png"

默认情况下它不起作用。我尝试改变wumpa.rcBuild Action

  • 内容(默认):无效
  • 编译:“命名空间不能直接包含字段或方法等成员
  • 嵌入式资源:不起作用
  • 资源:无效

我得到什么(什么都没有):

我的期望(某事):

然后当您将 Internet Explorer 指向资源时(使用其 res 协议):

res://C:\Develop\Avatar\LocaleInfo\LocaleInfo.exe\PNG\SplashPNG

IE 可以找到它:

【问题讨论】:

  • 相当大的阻抗不匹配,托管资源的工作方式非常不同。您仍然可以使用 Project + Properties、Application 选项卡、Resource 文件将 .res 文件添加到项目中。阅读它们你将得不到任何帮助。需要 Pinvoke。
  • 所以我无法将.rc 文件添加到我的解决方案中并让Visual Studio 的资源编译器对其进行编译?
  • 好吧,当然,您可以添加一个 C++ 项目。您似乎对阅读资源的困难感到不知所措。
  • @HansPassant 幸运的是,它们并不适合我。有些适用于需要资源图像的 Internet Explorer 等程序(即,您不能将图像提供给 WebBrowser 控件或其本机 IWebBrowser COM 对象)。但我没有兴趣添加res 文件,因为这需要编译器。我使用了一种开发工具,您可以在其中向解决方案添加 .rc 文件,就像添加 .cs 文件一样容易 - 编译器/链接器会处理它 - 完成它的工作。
  • 是的,你有一个,Visual Studio。还没有尝试过那个 C++ 项目?

标签: .net visual-studio visual-studio-2010 resources


【解决方案1】:

托管资源以不同于 Win32 资源的方式嵌入到程序集中 - “嵌入资源”选项将您的资源嵌入到输出程序集中,但 不是以使用“res”协议之类的东西可以访问的方式。

您可以使用工具将 Win32 嵌入到现有资源中,如下所述:Embed Win32 resources in C# programs (CodeProject)

或者,您可以使用/win32res csc.exe 编译器选项嵌入已编译的.res 资源。此选项当前未在 Visual Studio 2010 中作为选项公开,但有一系列说明 here 解释了如何执行此操作。您只需使用rc.exe 正常编译您的资源(例如,作为预构建步骤):

<Target Name="BeforeBuild" Inputs="my_resource_file.rc" Outputs="my_resource_file.res">
    <Exec Command="&quot;C:\Program Files\Microsoft Visual Studio 8\VC\bin\rc.exe&quot; /r my_resource_file.rc" />
</Target>

然后提供Win32Resource 属性来指定输出.res 文件:

<Win32Resource>my_resource_file.res</Win32Resource>

更新: 作为替代方案,您可以使用 RC MSBuild task,只要您不介意编辑 MSBuild .csproj 文件。一个简单的例子:

<UsingTask TaskName="RC" AssemblyName="Microsoft.Build.CppTasks.Common, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
<PropertyGroup>
    <Win32Resource Condition="'$(Win32Resource)' != ''">@(ResourceCompile->'%(RelativeDir)%(filename).res')</Win32Resource>
</PropertyGroup>
<ItemGroup>
    <ResourceCompile Include="test.rc" />
</ItemGroup>
<Target Name="ResourceCompile" BeforeTargets="BeforeCompile" Condition="'@(ResourceCompile)' != ''">
    <RC Source="@(ResourceCompile)" />
</Target>

这只有在安装了 Visual C++ 时才有效。

【讨论】:

  • 他正在使用 Resource Hacker 在构建后手动将资源添加到 exe。当您有几十个资源并且在添加它们之前无法运行可执行文件时,这并不是一个真正的解决方案。
  • @IanBoyd 我已经更新了我的答案,包括一些关于如何使用 csc /win32res 选项来执行此操作的提示 - 恐怕我以前从未这样做过,所以我不这样做知道这样做的最佳方法,但希望这个答案能给你一些提示。
  • 以“虽然 Visual Studio 的未来版本可能支持它,但 Visual Studio 2010 不支持在 .NET 可移植可执行文件中编译资源”作为回答的前言。我会接受的。这似乎是正确的答案(即你不能
  • @IanBoyd 找到了一篇更好的文章,解释了如何使用预构建步骤来做到这一点。
  • 问题是我与其他开发人员一起工作。我不能将解决方案修改为在其他开发人员机器上会失败的硬编码路径。
【解决方案2】:

以下是 Visual Studio 2010 的替代预构建事件,它较少依赖特定目录位置:

@echo.
set RCDIR=
IF EXIST "$(FrameworkSDKDir)Bin\rc.exe" (set RCDIR="$(FrameworkSDKDir)Bin\rc.exe")
IF EXIST "$(DevEnvDir)..\..\VC\Bin\rc.exe" (set RCDIR="$(DevEnvDir)..\..\VC\Bin\rc.exe")
IF EXIST "$(DevEnvDir)..\..\SDK\v2.0\Bin\rc.exe" (set RCDIR="$(DevEnvDir)..\..\SDK\v2.0\Bin\rc.exe")
IF EXIST "$(DevEnvDir)..\..\SDK\v3.5\Bin\rc.exe" (set RCDIR="$(DevEnvDir)..\..\SDK\v3.5\Bin\rc.exe")
IF EXIST "$(DevEnvDir)..\..\..\Microsoft SDKs\Windows\v6.0a\bin\rc.exe" (set RCDIR="$(DevEnvDir)..\..\..\Microsoft SDKs\Windows\v6.0a\bin\rc.exe")
IF EXIST "$(DevEnvDir)..\..\..\Microsoft SDKs\Windows\v7.0a\bin\rc.exe" (set RCDIR="$(DevEnvDir)..\..\..\Microsoft SDKs\Windows\v7.0a\bin\rc.exe")
if not defined RCDIR (echo "Error!  Unable to find rc.exe.") ELSE (%RCDIR% /r "$(ProjectDir)MyResources.rc")
if not defined RCDIR (Exit 1)
@echo.

当然,将 MyResources.rc 更改为适当的文件名。

如果您使用此预构建事件,您可以告诉 Visual Studio 在“应用程序”>“资源”下的“项目属性”对话框中使用相应的 .RES 文件(对于 C#)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-08
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多