Я пытаюсь встроить значок в мое свое приложение WPF так, чтобы я мог вытащить его для использования в качестве значка в Windows 7 JumpList с помощью следующего кода:
newScene.IconResourcePath = System.Reflection.Assembly.GetEntryAssembly().Location;
newScene.IconResourceIndex = 0;
Я заставил это работать с помощью следующего метода: http://dennisdel.com/?p=38
Однако это не походит на лучший подход, и кажется, что должен быть более легкий способ встроить ресурс значка в мое приложение, все еще оставление опции "Icon and Manifest" зарегистрировалось в Свойствах приложения для моей программы.
Я попробовал многочисленные методы включая установку действия сборки значка как ресурс и встроенный ресурс, но каждый раз я открываю свой .exe в редакторе ресурса, значок не появляется.
Какие-либо предложения?
Visual Studio не поставляется со способом выполнения компилятора ресурсов Win32 из задачи MSBuild, и ни одна из ее встроенных функций для создания ресурсов не создает сырые ресурсы. Поэтому у вас есть следующие варианты:
Сначала я объясню разницу между пятью различными видами "ресурсов", которые могут существовать в файле .exe или .dll, включая "ресурсы Win32", которые требует JumpList.
Затем я объясню, как создать пользовательскую задачу сборки, которая позволит вам внедрить произвольные Win32 ресурсы в исполняемый файл C# или VB.NET.
Существует пять различных видов "ресурсов", которые могут существовать в файле .exe или .dll:
Ресурсы Win32
Первым видом ресурсов был "ресурс" Win32. Этот вид ресурсов определяется в файле .rc и имеет либо пронумерованные, либо именованные ресурсы, каждый из которых имеет тип и набор данных. The
Компилятор ресурсов Win32, rc.exe, компилирует файл .rc в двоичный файл .res, который затем может быть добавлен к исполняемому файлу.
Доступ к ресурсам Win32 осуществляется с помощью функций Win32 FindResource
и LoadResource
.
Ресурсы Win32 встраиваются в приложения C++ путем добавления их в файл .rc, который компилируется в файл .res и подключается к исполняемому файлу. Они также могут быть добавлены постфактум с помощью программы rc.exe. Для приложений C# и VB.NET MSBuild может добавить предварительно скомпилированный .res файл в исполняемый файл, который он создает с помощью компилятора Csc или Vbc, или создать его по умолчанию. Ни C#, ни VB.NET не имеют возможности создавать не стандартные .res файлы из .rc файлов, и не существует задачи MSBuild, чтобы сделать это за вас.
Вы можете просмотреть Win32 Resources в .exe или .dll, открыв сам .exe или .dll файл в Visual Studio, используя File -> Open.
Типичное приложение на C, C++ или MFC будет иметь много Win32 Resources, например, каждое диалоговое окно будет задано ресурсом.
Типичное WPF приложение будет иметь только три Win32 ресурса по умолчанию, созданных компилятором C# или VB.NET: Ресурс версии, RT_MANIFEST и значок приложения. Содержимое этих ресурсов конструируется из атрибутов Assembly в коде и элемента
в файле .csproj или .vbproj.
Это тип ресурса, который ищет JumpList.
Встроенные ресурсы
Встроенный ресурс - это ресурс NET Framework. Структура данных, содержащая эти ресурсы, управляется CLR в более удобной для доступа управляемого кода форме. Каждый ресурс идентифицируется строковым именем, которое по соглашению начинается с пространства имен класса, с которым связан ресурс.
Встроенный ресурс - это просто сгусток двоичных данных с именем. Фактический тип данных либо известен вызывающей стороне, либо выводится из имени, подобно файлам в файловой системе. Например, встроенный ресурс с именем, заканчивающимся на ".jpg", скорее всего, является файлом JPEG.
Доступ к встроенным ресурсам осуществляется с помощью Assembly.GetManifestResourceStream
и его родственников GetManifestResourceInfo
и GetManifestResourceNames
.
Встроенные ресурсы встраиваются в файлы .exe и .dll путем добавления файла в проект и установки действия сборки на "Embedded Resource".
Вы можете просмотреть встроенные ресурсы в файле .exe или .dll, открыв его в NET Reflector и заглянув в папку "Resources".
Встроенные ресурсы широко используются в WinForms, но почти никогда в WPF.
Наборы ресурсов (.resx/.resources)
Несколько объектов NET Framework, таких как строки и иконки, могут быть объединены в одну строку данных "Resource Set", которая хранится в .exe как один встроенный ресурс NET Framework. Например, это используется в WinForms для хранения таких вещей, как значки и строки, которые нелегко включить в сгенерированный код.
Объекты в наборе ресурсов могут быть получены по отдельности с помощью классов ResourceManager
и ResourceSet
, определенных CLR.
Объекты в наборе ресурсов определяются в исходном коде файлом .resx. Данные могут находиться непосредственно в файле .resx (как в случае со строками) или ссылаться на файл .resx (как в случае со значками). Когда проект собран, содержимое, указанное в каждом .resx файле, сериализуется в двоичную форму и хранится как один Embedded Resource с расширением ".resx", замененным на ".resources".
Вы можете просмотреть объекты в наборе ресурсов, открыв .exe или .dll в NET Reflector, открыв папку Resources, щелкнув на файле ".resources" и просмотрев элементы в правой панели.
Многие функции WinForms использовали файлы .resx и ResourceSets подобно старым файлам Win32 .rc для хранения нескольких ресурсов, таких как строки, вместе. Они также используются самим WinForms для хранения настроек формы, которые не могут быть включены в код.
Приложения WPF почти никогда не используют произвольные объекты в ResourceSets, хотя сам WPF использует ResourceSets внутри для хранения скомпилированного XAML.
Ресурсы XAML
Ресурс WPF XAML - это скомпилированный файл XAML, который хранится внутри набора ресурсов (ResourceSet). Имя внутри набора ресурсов - это оригинальное имя файла с ".xaml", замененным на ".g.baml". Содержимое может быть любым допустимым XAML, наиболее распространенными типами являются Window, Page, UserControl, ResourceDictionary и
.
Application.
Ресурсы WPF могут быть загружены с помощью Application.LoadComponent()
или путем ссылки на исходное имя файла XAML в контексте WPF. Кроме того, любой Ресурс WPF, за которым стоит код (как указано в x:Class
), будет автоматически загружен и применен к каждому объекту, созданному из этого класса во время вызова InitializeComponent
.
Ресурсы WPF создаются путем добавления файла .xaml в ваш проект и установки его действия сборки на "Resource", "Page" или "ApplicationDefinition". Это заставляет компилятор скомпилировать файл в BAML и добавить его в соответствующий ResourceSet.
Вы можете просмотреть ресурсы XAML в .exe или .dll, открыв их в NET Reflector с установленным дополнением BamlViewer, выбрав в меню Tools -> BAML Viewer и используя BAML Viewer для просмотра конкретного файла .g.baml внутри .resources.
Ресурсы WPF в словаре ресурсов
В WPF почти все так называемые "ресурсы" являются записями в словаре ресурсов. Словари ресурсов описываются в XAML либо внутри других объектов, таких как Windows и UserControls, либо в отдельных файлах XAML, содержащих только словарь ресурсов. Каждый ресурс идентифицируется "x:Key", который может быть объектом любого типа. Сами ресурсы также могут быть объектами любого типа.
На ресурсы WPF можно ссылаться в XAML с помощью расширений разметки {StaticResource}
и {DynamicResource}
или загружать в код с помощью FindResource
.
Ресурсы WPF добавляются в ResourceDictionary путем добавления их в XAML-файл, содержащий ResourceDictionary, внутри элемента
и присвоения им атрибута x:Key
.
Ресурсы WPF широко используются в WPF, включая кисти, стили, данные, геометрию, шаблоны и т.д.
Вы можете просмотреть ресурсы WPF в .exe или .dll, просмотрев ресурсы XAML, как описано выше, и для каждого из них заглянув в теги ResourceDictionary, чтобы увидеть сами ресурсы.
Как легко встроить произвольные ресурсы Win32 в файл C# или VB.NET .exe
Из приведенного выше обсуждения вы заметите, что в приложение C# или VB.NET легко добавить любой тип ресурсов, кроме ресурсов Win32. Чтобы упростить эту задачу, вы можете добавить дополнительную задачу сборки и цель. Вот как это делается:
Задача очень проста:
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
}
}
Файл .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>
Теперь в вашем файле .csproj добавьте ссылку на ваш файл .targets file:
<Import Project="Win32ResourceCompiler.targets" />
И, конечно, вам нужно дать вашему .rc файлу тип файла Win32RCFile:
<ItemGroup>
<Win32RCFile Include="MyWin32Resources.rc" />
</ItemGroup>
С помощью этой установки вы можете создать традиционный Win32 .rc файл, чтобы указать все ваши Win32 ресурсы, включая вашу версию, манифест, значок приложения, и столько дополнительных значков, сколько вы захотите. Каждый раз при компиляции все эти ресурсы Win32 будут добавляться в ваш .exe файл.
Это занимает немного времени для настройки, но в конечном итоге гораздо приятнее и проще, чем вручную редактировать файл .res.
Вы можете указать несколько иконок в файле .rc следующим образом:
1 ICON ApplicationIcon.ico
2 ICON JumpListIcon.ico
3 ICON AnotherIcon.ico
Вот документация по всем утверждениям определения ресурсов, которые вы можете использовать в файле .rc.
Также обратите внимание, что приведенный выше файл .targets был набран на скорую руку и не был протестирован. Документацию по синтаксису файлов MSBuild (.csproj и .targets) можно найти здесь и здесь, а хорошие примеры файлов .targets можно найти в каталоге c:\Windows\Microsoft.NET\Framework\v3.5).