Sco*_*den 11 wpf resources embedded-resource
我试图在我的WPF应用程序中嵌入一个图标,以便我可以使用以下代码将其拉出来作为Windows 7 JumpList中的图标使用:
newScene.IconResourcePath = System.Reflection.Assembly.GetEntryAssembly().Location;
newScene.IconResourceIndex = 0;
Run Code Online (Sandbox Code Playgroud)
我已经使用以下方法使用它:http://dennisdel.com/?p = 38
但是,它似乎不是最好的方法,似乎应该有一种更简单的方法将图标资源嵌入到我的应用程序中,同时仍然在我的程序的应用程序属性中选中" Icon and Manifest "选项.
我尝试了很多方法,包括将图标构建操作设置为资源和嵌入式资源,但每次在资源编辑器中打开我的.exe时,都不会显示图标.
有什么建议?
Ray*_*rns 27
Visual Studio没有提供从MSBuild任务执行Win32资源编译器的方法,也没有用于创建资源的嵌入式功能创建原始资源.因此,您的选择是:
首先,我将解释.exe或.dll文件中可能存在的五种不同"资源"之间的差异,包括JumpList所需的"Win32资源".
然后,我将解释如何构建一个自定义构建任务,允许您在C#或VB.NET可执行文件中嵌入任意Win32资源.
.exe或.dll文件中可以存在五种不同的"资源":
Win32资源
原始资源类型是Win32"资源".这种资源在.rc文件中定义,并具有编号或命名资源,每个资源都有一个类型和一团数据.的
Win32资源编译器,RC.EXE,编译rc文件到可接着被添加到生成的可执行的二进制res文件.
使用Win32 FindResource和LoadResource函数访问Win32资源.
通过将它们添加到.rc文件中,将Win32资源嵌入到C++应用程序中,该文件被编译为.res文件并链接到可执行文件中.它们也可以在事后使用rc.exe程序添加.对于C#和VB.NET应用程序,MSBuild可以将预先构建的.res文件添加到它通过Csc或Vbc编译器创建的可执行文件中,或者它可以为您构建一个默认文件.C#和VB.NET都没有能力从.rc文件构建非默认.res文件,并且没有MSBuild任务可以为您执行此操作.
您可以使用文件 - >打开在Visual Studio中打开.exe或.dll文件本身来查看.exe或.dll中的Win32资源.
典型的C,C++或MFC应用程序将具有许多Win32资源,例如,每个对话框都将由资源指定.
典型的WPF应用程序将只具有由C#或VB.NET编译器构造的三个默认Win32资源:版本资源,RT_MANIFEST和应用程序图标.这些资源的内容由代码中的Assembly属性和<ApplicationIcon>.csproj或.vbproj文件中的元素构成.
这是JumpList正在寻找的那种资源.
嵌入式资源
"嵌入式资源"是.NET Framework资源.包含这些资源的数据结构由CLR以更有利于托管代码访问的方式进行管理.每个资源都由字符串名称标识,按照约定,该名称以与资源关联的类的名称空间开头.
嵌入式资源只是一个带有名称的二进制数据.实际数据类型可以是调用者已知的,也可以从名称中推断出来,类似于文件系统中的文件.例如,名称以".jpg"结尾的嵌入式资源可能是JPEG文件.
使用Assembly.GetManifestResourceStream及其兄弟姐妹GetManifestResourceInfo和访问嵌入式资源GetManifestResourceNames.
嵌入式资源通过将文件添加到项目并将构建操作设置为"嵌入式资源"而嵌入到.exe和.dll文件中.
您可以通过在.NET Reflector中打开它并查看"Resources"文件夹来查看.exe或.dll中的嵌入式资源.
嵌入式资源通常在WinForms中使用,但几乎从不使用WPF.
资源集(.resx/.resources)
多个.NET Framework对象(如字符串和图标)可以组合在一起形成一个"资源集"数据结构,该数据结构作为单个.NET Framework嵌入式资源存储在.exe中.例如,WinForms使用它来存储诸如图标和字符串之类的东西,这些东西不容易包含在生成的代码中.
可以使用CLR定义的ResourceManager和ResourceSet类单独检索资源集中的对象.
资源集中的对象由源代码中的.resx文件定义.数据可以直接在.resx文件中(如字符串的情况)或由.resx文件引用(如图标的情况).构建项目时,每个.resx文件指定的内容将序列化为二进制形式,并存储为单个嵌入式资源,扩展名为".resx",替换为".resources".
您可以通过打开.NET Reflector中的.exe或.dll,打开Resources文件夹,单击".resources"文件,然后查看右侧窗格中的项目来查看资源集中的对象.
许多WinForms时代的特性通常使用.resx文件和ResourceSets,其方式与旧的Win32 .rc文件类似,用于存储多个资源,如字符串.它们也被WinForms本身用于在不能进入代码的表单上存储设置.
WPF应用程序几乎从不在ResourceSets中使用任意对象,尽管WPF本身在内部使用ResourceSets来存储已编译的XAML.
XAML资源
WPF XAML资源是存储在ResourceSet中的已编译XAML文件.资源集内的名称是原始文件名,".xaml"替换为".g.baml".内容可以是任何有效的XAML,最常见的类型是Window,Page,UserControl,ResourceDictionary和
Application.
WPF资源可以使用Application.LoadComponent()或通过引用WPF上下文中的原始XAML文件名来加载.此外,任何具有代码隐藏(由指定x:Class)的WPF资源将自动加载并应用于在InitializeComponent调用期间由该类创建的每个对象.
通过将.xaml文件添加到项目并将其构建操作设置为"Resource","Page"或"ApplicationDefinition"来创建WPF资源.这会导致编译器将文件编译为BAML并将其添加到适当的ResourceSet.
您可以通过在安装了BamlViewer加载项的NET Reflector中打开它,从菜单中选择工具 - > BAML查看器,并使用BAML查看器浏览到特定的.g.baml,来查看.exe或.dll中的XAML资源. .resources中的文件.
ResourceDictionary中的WPF资源
在WPF中,几乎所有被称为"资源"的都是ResourceDictionary中的条目.ResourceDictionaries在XAML中描述,或者在其他对象(如Windows和UserControls)中,或者在仅包含ResourceDictionary的单独XAML文件中描述.每个都由"x:Key"标识,可以是任何对象类型.资源本身也可以是任何对象类型.
WPF资源可以使用{StaticResource}和{DynamicResource}标记扩展在XAML中引用,也可以使用代码加载到代码中FindResource.
通过将WPF资源添加到包含<ResourceDictionary>元素内的ResourceDictionary 并为其提供x:Key属性的XAML文件,将其添加到ResourceDictionary .
WPF资源在WPF中广泛使用,包括画笔,样式,数据,几何,模板等.
您可以通过浏览上面描述的XAML资源以及查看ResourceDictionary标记内的每个资源来查看.exe或.dll中的WPF资源,以查看资源本身.
如何轻松地将任意Win32资源嵌入到C#或VB.NET .exe中
您将从上面的讨论中注意到,除了 Win32资源之外,很容易将每种类型的资源添加到C#或VB.NET应用程序中.为了简化这一过程,您可以添加其他构建任务和目标.方法如下:
任务非常简单:
public class Win32ResourceCompiler : ToolTask
{
public ITaskItem Source { get; set; }
public ITaskItem Output { get; set; }
protected override string ToolName { get { return "rc.exe"; } }
protected override string GenerateCommandLineCommands()
{
return @"/r /fo """ + Output.ItemSpec + @""" """ + Source.ItemSpec + @"""";
}
protected override string GenerateFullPathToTool()
{
// TODO: Return path to rc.exe in your environment
}
}
Run Code Online (Sandbox Code Playgroud)
.targets文件也很简单.它将是这样的:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="SomeNamespace.Win32ResourceCompiler" AssemblyFile="Something.dll" />
<PropertyGroup>
<CoreCompileDependsOn>$(CoreCompileDependsOn);CompileWin32RCFile</CoreCompileDependsOn>
</PropertyGroup>
<Target Name="CompileWin32RCFile" Outputs="@(Win32RCFile->'%(filename).res')">
<Win32ResourceCompiler
Source="@(Win32RCFile)"
Output="@(Win32RCFile->'%(filename).res')" />
</Target>
</Project>
Run Code Online (Sandbox Code Playgroud)
现在在.csproj文件中,添加对.targets文件的引用:
<Import Project="Win32ResourceCompiler.targets" />
Run Code Online (Sandbox Code Playgroud)
当然,您需要为.rc文件提供Win32RCFile的文件类型:
<ItemGroup>
<Win32RCFile Include="MyWin32Resources.rc" />
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)
通过此设置,您可以创建传统的Win32 .rc文件来指定所有Win32资源,包括您的版本,清单,应用程序图标以及任意数量的其他图标.每次编译时,所有这些Win32资源都将添加到.exe文件中.
设置需要一些时间,但从长远来看比手动编辑.res文件更令人满意和简单.
您可以在.rc文件中指定多个图标,如下所示:
1 ICON ApplicationIcon.ico
2 ICON JumpListIcon.ico
3 ICON AnotherIcon.ico
Run Code Online (Sandbox Code Playgroud)
以下是您可以在.rc文件中使用的所有资源定义语句的文档.
另请注意,上面的.targets文件是在一时冲动时输入的,尚未经过测试.可以在此处和此处找到有关MSBuild(.csproj和.targets)文件语法的文档,并且可以在c:\ Windows\Microsoft.NET\Framework\v3.5目录中找到.targets文件的良好示例.