tags:

views:

462

answers:

5

Is there a way to change a WPF assembly icon from code? I'm not referring to the window icon, but to the icon that appears on the .exe file.

EDIT:

I'm trying to achieve interactivity in the application icon's representation - different user-initiated actions combined with a current state should lead to a different application icon. I rely on the visual representation of the application as it has no visible window and the interaction is based on hot-keys and general system usage patterns.

A: 

Ummm, you are not meant to change an exe file while it is running!

The assembly icon is defined in the project file. You can change that as part of the build process but not once the application is running

What are you trying to achieve?

TFD
I've edited the question to reflect the final goal of such an approach and on a side note I'd rather focus on the final result rather than the things I'm not meant to do - I didn't specify I want the .exe itself changed, only it's icon - I'm pretty sure that when you're manually changing an app's icon in Windows explorer it doesn't involve changing the exe.
luvieere
+3  A: 

The icon that you see when looking at the exe in a folder window is set inside the exe, it is possible to change that icon from code but it's more trouble than you think.

The icons you see on the start menu, desktop and quick launch toolbar are set in shortcut files (a different file on each location), editing those files isn't that difficult.

You can do it with Com and IShellLink http://msdn.microsoft.com/en-us/library/bb776891%28VS.85%29.aspx

Here's a wrapper class that simplifies things: http://vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects/Creating_and_Modifying_Shortcuts/article.asp

You can also do it with windows scripting host: http://www.codeproject.com/KB/dotnet/shelllink.aspx

Nir
+2  A: 

Nir's suggestion to use shortcuts is really your best approach if you want to make the actual desktop icon change.

Probably a better approach for a windowless application is install an icon in the notification area. You can read up on the details of adding / changing an icon in win32 in the notification area here. .NET supports this functionality through System.Windows.Forms.NotifyIcon. Either of these APIs will let you change/animate the icon as desired; give you an approved place to notify the user of events; and give you a central place to let the user interact with your application using menus. This also has the benefit that even when windows are maximized, your icon is still visible (providing that the user hasn't hidden it, in which case you probably want to let them do so).

See also, Windows 7 guidelines for polite usage of the notification area. It's always easier to work with the operating system than against it.

Eclipse
Well, if it would have been easy, I would not have found a reason to ask it here, don't you think? I write the app for my use, so I'm not following best usability practices, nor do I care about them in this instance - I care that I want it to behave and to look as I've specified and the notification area icon is a common and good, but in this case, undesired solution.
luvieere
+3  A: 

Overview

Changing the icon in your .exe file is straightforward though a bit cumbersome. You'll potentially need to do three things:

  1. Prevent your running process from holding a lock on the .exe file which would prevent it from being modified
  2. Possibly modify file permissions to make it writable
  3. Actually edit the .exe file to replace the icon

Details

Step 3 - actually editing the .exe file - is the most interesting, so I'll start there. You will use the BeginUpdateResource(), UpdateResource() and EndUpdateResource() calls in kernel32.dll. Basically you do this:

byte[] data = File.ReadAllBytes(newIconFilePath);
       // Or otherwise load icon data

IntPtr hUpdate = BeginUpdateResource(exePath, false);
UpdateResource(hUpdate, RT_ICON, MAKEINTRESOURCE(1), LANG_SYSTEM_DEFAULT,
               data, data.Length);
EndUpdateResource(hUpdate, false);

You'll need to add DllImport declarations for the functions and implement the constants. See the documentation on MSDN for details on how BeginUpdateResource, UpdateResource, and EndUpdateResource work.

For step 1 - preventing your .exe from being locked - the easy solution is to add code to your application startup that checks to see if the current .exe is running from the temporary directory (Path.GetTempPath()). If not, it copies the .exe to the temporary directory using File.Copy() along with any additional files needed, then executes it with one additional command line argument that gives the location of the original .exe. The original process then exits, removing the lock on the .exe file.

For step 2 - correcting permissions - this simply a matter of modifying the ACLs and possibly triggering a UAC dialog. There are plenty of examples out there and you probably don't need to do this, so I'll skip further explanation

Final note

The above steps will actually allow you to edit the actual icon of your real .exe file. However if you just need a visual icon change I would recommend you use a shortcut and edit its icon instead.

Ray Burns
A: 
Onots