19

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)

Stefan Paul Noack
  • 3,654
  • 1
  • 27
  • 38
0xDEADBEEF
  • 3,401
  • 8
  • 37
  • 66

5 Answers5

17

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.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • problem solved. but i´ve used [ResEdit](http://www.resedit.net/) to create the rc/res-file. it works perfectly – 0xDEADBEEF Jan 18 '12 at 22:37
  • Or just deploy a native DLL that contains such resources with the application, so you don't have to run custom tools or lose versioning information. – David Anderson Feb 10 '12 at 07:30
  • This approach loses file version information, and if you restore it back (e.g. using C++ version style .rc file) - you will still have problem with task manager / application title incorrect. (See my own solution & update to it at the end.) So use InsertIcons.exe ! Do not use official Microsoft tools ! :-) – TarmoPikaro May 18 '16 at 15:43
  • I managed to add the icons I needed and the version information in the .rc file. While I used ResEdit to initially create it, I had to trim the resulting file a bit in order for the rc command to build it but, in the end, it worked like a charm, and I could see no issues with the task manager. Perhaps you'd have to try and provide as much of the info it creates there. – Leonardo Pessoa Apr 25 '19 at 15:36
13

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/

Einar Egilsson
  • 3,438
  • 9
  • 36
  • 47
1

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.

TarmoPikaro
  • 4,723
  • 2
  • 50
  • 62
0

I used the InsertIcons approach successfully until Symantec anti virus started flagging up my exe as suspicious. My guess is Symantec didn't like the change in signature that comes with messing about with the exe as a post build step.

In the end I went with a separate .NET dll class library compiled using the following code in the csproj file:

<PropertyGroup>
   <Win32Resource>icons.res</Win32Resource>
</PropertyGroup>

You don't need to have c++ build tools installed, but you do need resource compiler as described in the accepted answer above.

My icons.rc file looks like this:

1  ICON  "IconA.ico"
2  ICON  "IconB.ico"
3  ICON  "IconC.ico"

And the pre-build command is:

"C:\Program Files (x86)\Windows Kits\8.1\bin\x86\rc.exe" $(ProjectDir)icons.rc
Tom Makin
  • 3,203
  • 23
  • 23
  • Were you code signing before the post-build InsertIcons.exe event, or did you code sign your .exe after InsertIcons.exe modified it? We're looking to use InsertIcons.exe because it's a simpler solution. We code sign the .exe with our cert after the build (and post-build) are finished. – spurgeon Jul 31 '18 at 13:55
  • @spurgeon I wasn't signing my exe so can't help here I'm afraid – Tom Makin Aug 02 '18 at 08:43
-1

If you go to your project settings you will see a way to set the icon for the application.

enter image description here

To add additional icons ...

  • Right Mouse Button on Project in Solution Explorer and pick New Item and then Resources File
  • Double click the resources file in solution explorer and pick Add Resource -> New Icon
parapura rajkumar
  • 24,045
  • 1
  • 55
  • 85
  • i know. i did this already. if i compile this, the exe has the selected icon. but how to add some more icons? – 0xDEADBEEF Jan 18 '12 at 15:56
  • 2
    does not work (added Resource1.resx, loaded the ico-file and clean+build solution). hm, i forgot to mention (explicitly) that my program is a WPF/.NET4-Application – 0xDEADBEEF Jan 18 '12 at 16:28