向.NET-Application添加多个图标(Win32-Resource)

时间:2012-01-18 15:46:11

标签: c# .net icons .net-assembly

可以在Project Properties中设置Application-Icon。如果你这样做,exe将有这个图标而不是默认的图标。此图标是win32资源,也可以像这样访问:

change icon

我希望我的程序使用的文件类型有特殊图标。关联filetype-icon我可以在注册表中指定它(“DefaultIcon”键中的“MyProg.exe,1”)。

所以如何添加更多图标到我可以用它来进行文件类型关联的程序集?

非常感谢

ps:它是一个WPF应用程序(.NET 4.0)

5 个答案:

答案 0 :(得分:16)

Windows对托管资源一无所知,您需要将非托管资源添加到可执行文件中。在parapura的屏幕截图中,您需要选择Resource file单选按钮。这需要一个.res文件,这是一个通过在.rc文件上运行Windows SDK rc.exe工具创建的二进制文件。 .rc文件是一个包含资源语句的简单文本文件,类似于:

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

请确保将此文件保存到项目文件夹中,而不使用utf-8编码,最好使用记事本。使用Project + Add New Item,Application Manifest File创建所需的app.manifest文件。使用Project + Add Existing Item将此.rc文件添加到项目中。双击它并验证您是否可以看到图标和清单。右键单击顶部节点,添加资源,然后单击版本+新建。编辑版本信息,请注意它将不再自动匹配AssemblyInfo.cs中的属性

您可以使用Visual Studio命令提示符将.rc文件编译为.res文件:

rc /r something.rc

生成可在项目属性选项卡中使用的.res文件。这样做是预建事件是可取的,但有点难以正确。这可能出错的方式很多,祝你好运。

答案 1 :(得分:10)

我刚刚创建了一个简单的工具来完成这一操作,而不必弄乱.res文件。它是一个很小的实用程序,您可以将其用作Post-Build事件的一部分,并允许您将特定文件夹中的所有图标文件添加到程序集中。如果我们假设您在主项目文件夹下有一个icons文件夹,则可以添加以下构建后事件:

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

可以在http://einaregilsson.com/add-multiple-icons-to-a-dotnet-application/

找到进一步的说明和下载

答案 2 :(得分:1)

基于我看到的答案 - 这似乎很微不足道,但遗憾的是它不是那么简单。

让我们从.rc文件开始 - 您可以快速编写如下文件: myown.rc:

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

但接下来的问题 - 在哪里获取应用程序所需的清单文件。

可以使用如下命令行提取当前使用的清单文件:

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

然后您可以将该清单与.net可执行文件一起使用。

但这不是全部。 从项目本身,您无法指定.res文件的相对路径,您只能使用绝对路径。保存.csproj,并使用记事本手动编辑 - 以使路径相对。之后项目编译得很好。

但是进入svn / git - 你可能不会放置.res文件 - 只有源代码。 需要将.rc编译为.res。

最好在项目/预建步骤中完成。

但是当然rc.exe无法启动,因为它的C ++项目,我们有C#项目,它不关心C ++项目的路径。

这可以使用这样的预构建步骤来解决:

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

您需要使用您正在编译的Visual Studio更改VS100COMNTOOLS(我使用Visual Studio 2010)。

这仍然不是一切。如果你想在飞行中更改你的应用程序的图标 - 你可能会对这样的代码snipet感兴趣:

[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;
}

在form_load中你可以像这样拨打电话:

SetIcon(this, N);

第一个图标的N = 0,N = 1 - 第二个图标等等。

18.5.2016更新我的方法正常 - 但是 - 在此程序集文件属性之后 - 版本信息消失。可以使用典型的C ++ .rc文件将其恢复,但不幸的是,它确实会以某种方式破坏程序集属性 - 任务管理器会将你的exe显示为&#34;应用程序&#34;。如果有可能以某种方式改变清单/应用程序标题 - 我没有任何结果,我试图更深入地收获。之后,我最终使用了此处提出的InsertIcons.exe解决方案。

因此,如果您对文件版本信息不感兴趣 - 您可以使用我的解决方案,如果您需要文件版本并且任务管理器应该正确显示您的应用程序 - 请使用InsertIcons.exe。 C#code snipet(SetIcon)在任何解决方案中都适合您。

答案 3 :(得分:0)

如果您转到项目设置,您将看到设置应用程序图标的方法。

enter image description here

添加其他图标......

  • 解决方案资源管理器中项目上的鼠标右键,选择新项,然后选择资源文件
  • 双击解决方案资源管理器中的资源文件,然后选择添加资源 - &gt;新图标

答案 4 :(得分:0)

我成功使用了InsertIcons方法,直到赛门铁克反病毒开始将我的exe标记为可疑。我的猜测是,赛门铁克并不喜欢签名的变化,这些变化伴随着exe作为后期构建步骤而变得混乱。

最后,我使用了csproj文件中使用以下代码编译的单独的.NET dll类库:

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

您不需要安装c ++构建工具,但您需要资源编译器,如上面接受的答案所述。

我的icons.rc文件如下所示:

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

预构建命令是:

"C:\Program Files (x86)\Windows Kits\8.1\bin\x86\rc.exe" $(ProjectDir)icons.rc