如何在.NET PE可执行文件中嵌入资源?

时间:2011-11-08 21:07:55

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

如何在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机制是什么?

另见


这些必须是标准资源;你知道每个人都可以读作资源的那种:

  • 资源黑客会显示为资源
  • PEView 会显示为资源
  • Internet Explorer 可以使用res protocol阅读(例如res://c:\foo\MyProgram.exe/PNG/SplashLogo

我尝试过的东西不起作用:

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

    enter image description here

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

    enter image description here

    (也尝试过构建操作:嵌入式资源,为was suggested to me in 2008


  3. 更新:什么行不通

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

    wumpa.rc

    SplashPNG   PNG   "Splash.png"
    

    默认情况下它不起作用。我尝试更改wumpa.rc构建操作

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

    我得到的(没有):

    enter image description here

    我的期望(某事):

    enter image description here

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

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

    IE可以找到它:

    enter image description here

2 个答案:

答案 0 :(得分:5)

托管资源以与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 ++时才能使用。

答案 1 :(得分:1)

以下是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在Application&gt;下的Project Properties对话框中使用相应的.RES文件。资源(用于C#)。