Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding multiple Icons (Win32-Resource) to .NET-Application

it is possible to set the Application-Icon in the Project Properties. If you do this the exe will have this icon instead of the default one. this icon is a win32-resource and can also be accessed like this:

change icon

i want to have special icons for filetypes which are used by my program. to associate an filetype-icon i can specify it in the registry ("MyProg.exe,1" in the "DefaultIcon" Key).

so how to ADD MORE icons to the assembly that i can use it for the filetype-association?

thank you very much

ps: it is a WPF-Application (.NET 4.0)

like image 453
0xDEADBEEF Avatar asked Jan 18 '12 15:01

0xDEADBEEF


People also ask

How do I add an Icon to a resource file?

At the top of the window select the arrow next to "Add Resource" and then select "Add Existing File...". Once selected, the icon is added to the resource file (and created, if necessary). The icon can be selected with the project properties Icon-Browse, and the project can then be published without any errors.

How do I add icons to Visual Studio?

On the menu bar, choose Project > Properties. When the Project Designer appears, choose the Application tab. (Visual Basic)—In the Icon list, choose an icon (.

How do I add an Icon in Winforms?

Go to Project Menu -> Add New Item -> Icon File Save this answer.


3 Answers

Windows doesn't know anything about managed resources, you need to add unmanaged resources to your executable. In parapura's screenshot, you need to select the Resource file radio button. That requires a .res file, a binary file that's created by running the Windows SDK rc.exe tool on a .rc file. The .rc file is a simple text file that contains resource statements, similar to this:

1 ICON "mainicon.ico"
2 ICON "alternative1.ico"
3 ICON "alternative2.ico"
1 24 "app.manifest"

Be sure to save this file into your project folder without utf-8 encoding, using Notepad is best. Create the required app.manifest file with Project + Add New Item, Application Manifest File. Add this .rc file to your project with Project + Add Existing Item. Double-click it and verify that you can see the icons and the manifest. Right-click the top node, Add Resource and click Version + New. Edit the version info, beware that it will no longer automatically match the attributes in AssemblyInfo.cs

You can compile the .rc file into a .res file with the Visual Studio Command prompt:

rc /r something.rc

Which produces the .res file you can use in the project property tab. Doing this is a pre-build event is advisable but a bit hard to get right. The number of ways this can go wrong are numerous, good luck.

like image 109
Hans Passant Avatar answered Nov 07 '22 07:11

Hans Passant


I've just created a simple tool to do exactly this without having to mess with .res files. It is a tiny utility which you can use as part of your Post-Build event and lets you add all icon files in a particular folder to your assembly. If we assume that you have a icons folder under your main project folder you can add the following post-build event:

C:\path\to\InsertIcons.exe $(TargetPath) $(ProjectDir)icons

A further description and a download can be found at http://einaregilsson.com/add-multiple-icons-to-a-dotnet-application/

like image 41
Einar Egilsson Avatar answered Nov 07 '22 07:11

Einar Egilsson


Based on answers which I see - it seems to be quite trivial, but unfortunately it's not so simple.

Let's start from .rc file - you can quickly write file like this: myown.rc:

1 ICON "..\\Folder1\\icon1.ico"
2 ICON "..\\folder2\\icon2.ico"
1 24 "myown.manifest"

But next question - where to get manifest file which you need for your application.

It's possible to extract currently used manifest file, using command line like this:

mt -inputresource:myOwnNetExe.exe;#1 -out:myown.manifest

And then you can use that manifest with your .net executable.

But this is not all. From project itself you cannot specify relative path to your .res file, you can use only absolute path. Save .csproj, and edit it manually with notepad - to make path relative. Project compiles just fine after that.

But into svn / git - you probably won't put .res file - only source code. Need to compile .rc to .res.

Best to do it in project / pre-build step.

But of course rc.exe cannot be launched, since it's C++ project, and we have C# project which does not care about C++ project pathes.

This can be walkarounded using pre-build step like this:

cd $(ProjectDir)
call "%VS100COMNTOOLS%\vsvars32.bat" >nul
rc /c 1252 /nologo myown.rc

Where you need to change VS100COMNTOOLS with visual studio with which you're compiling (I'm using Visual studio 2010).

And this is still not everything. If you want to change icon of your application on fly - in run-time - you might be interested in code snipet like this:

[DllImport("shell32.dll")]
public static extern IntPtr ExtractIcon(IntPtr hInst, string file, int nIconIndex);

[DllImport("user32.dll", SetLastError = true)]
static extern bool DestroyIcon(IntPtr hIcon);

/// <summary>
/// Sets icon from .exe or .dll into form object
/// </summary>
/// <param name="iIconIndex">Icon index to use.</param>
/// <param name="form">Form to assign to given icon</param>
/// <returns>true if ok, false if failed.</returns>
bool SetIcon( object form, int iIconIndex, String dllOrExe = null )
{
    if( dllOrExe == null )
        dllOrExe = System.Reflection.Assembly.GetExecutingAssembly().Location;

    IntPtr hIcon = ExtractIcon(IntPtr.Zero, dllOrExe, iIconIndex);

    if( hIcon == IntPtr.Zero )
        return false;

    Icon icon = (Icon) Icon.FromHandle(hIcon).Clone();
    DestroyIcon(hIcon);

    form.GetType().GetProperty("Icon").SetValue(form, icon);
    return true;
}

Where in form_load you can place call like this:

SetIcon(this, N);

Where N = 0 for first icon, N = 1 - for second and so on.

18.5.2016 Update My approach works ok - however - after this assembly file properties - version information disappears. It's possible to restore it back using typical C++ .rc file, but unfortunately for me it does then break assembly attributes somehow - task manager will display your exe as "Application". I've tried to harvest bit deeper if it's possible to somehow alter manifest / application title - but without any result. After that I've ended up using InsertIcons.exe solution proposed here as well.

So if you're not interested in file version information - you can use my solution, if you need file version and task manager should show your application correctly - use InsertIcons.exe. C# code snipet (SetIcon) here will work for you in any solution whatsoever.

like image 35
TarmoPikaro Avatar answered Nov 07 '22 08:11

TarmoPikaro