Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 向.NET应用程序添加多个图标(Win32资源)_C#_.net_Icons_.net Assembly - Fatal编程技术网

C# 向.NET应用程序添加多个图标(Win32资源)

C# 向.NET应用程序添加多个图标(Win32资源),c#,.net,icons,.net-assembly,C#,.net,Icons,.net Assembly,可以在项目属性中设置应用程序图标。如果执行此操作,exe将具有此图标,而不是默认图标。此图标是win32资源,也可以按如下方式访问: mt -inputresource:myOwnNetExe.exe;#1 -out:myown.manifest cd $(ProjectDir) call "%VS100COMNTOOLS%\vsvars32.bat" >nul rc /c 1252 /nologo myown.rc [DllImport("shell32.dll")] public

可以在项目属性中设置应用程序图标。如果执行此操作,exe将具有此图标,而不是默认图标。此图标是win32资源,也可以按如下方式访问:

mt -inputresource:myOwnNetExe.exe;#1 -out:myown.manifest
cd $(ProjectDir)
call "%VS100COMNTOOLS%\vsvars32.bat" >nul
rc /c 1252 /nologo myown.rc
[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;
}
SetIcon(this, N);
1  ICON  "IconA.ico"
2  ICON  "IconB.ico"
3  ICON  "IconC.ico"

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

那么如何向程序集添加更多图标,以便我可以将其用于文件类型关联

多谢各位


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

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

要添加其他图标

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

Windows对托管资源一无所知,您需要将非托管资源添加到可执行文件中。在parapura的屏幕截图中,您需要选择
资源文件
单选按钮。这需要一个.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+添加新项、应用程序清单文件创建所需的app.manifest文件。使用project+添加现有项将此.rc文件添加到项目中。双击它并确认您可以看到图标和清单。右键单击顶部节点,添加资源,然后单击版本+新建。编辑版本信息,注意它将不再自动匹配AssemblyInfo.cs中的属性

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

rc /r something.rc

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

我刚刚创建了一个简单的工具,可以准确地执行此操作,而不必处理.res文件。它是一个很小的实用程序,您可以将其用作生成后事件的一部分,并允许您将特定文件夹中的所有图标文件添加到程序集中。如果我们假设主项目文件夹下有一个图标文件夹,则可以添加以下生成后事件:

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

根据我所看到的答案,可以在

上找到进一步的描述和下载-这似乎很琐碎,但不幸的是,它不是那么简单

让我们从.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
cd $(ProjectDir)
call "%VS100COMNTOOLS%\vsvars32.bat" >nul
rc /c 1252 /nologo myown.rc
[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;
}
SetIcon(this, N);
1  ICON  "IconA.ico"
2  ICON  "IconB.ico"
3  ICON  "IconC.ico"
然后可以将该清单与.net可执行文件一起使用

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

但是在svn/git中,您可能不会只放入.res文件源代码。 需要将.rc编译为.res

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

当然,R.EXE不能启动,因为它是C++项目,我们有C++项目,不关心C++项目路径。 这可以通过以下预构建步骤实现:

mt -inputresource:myOwnNetExe.exe;#1 -out:myown.manifest
cd $(ProjectDir)
call "%VS100COMNTOOLS%\vsvars32.bat" >nul
rc /c 1252 /nologo myown.rc
[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;
}
SetIcon(this, N);
1  ICON  "IconA.ico"
2  ICON  "IconB.ico"
3  ICON  "IconC.ico"
您需要使用正在编译的visual studio更改VS100COMNTOOLS(我使用的是visual studio 2010)

这还不是全部。如果您想在运行时动态更改应用程序的图标,您可能会对以下代码感兴趣:

mt -inputresource:myOwnNetExe.exe;#1 -out:myown.manifest
cd $(ProjectDir)
call "%VS100COMNTOOLS%\vsvars32.bat" >nul
rc /c 1252 /nologo myown.rc
[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;
}
SetIcon(this, N);
1  ICON  "IconA.ico"
2  ICON  "IconB.ico"
3  ICON  "IconC.ico"
其中N=0表示第一个图标,N=1表示第二个图标,依此类推

18.5.2016更新我的方法正常-但是-在此程序集文件属性之后-版本信息消失。有可能使用典型的C++ .RC文件恢复它,但不幸的是,它确实会破坏组件属性——任务管理器会将你的EXE显示为“应用程序”。如果有可能以某种方式更改清单/应用程序标题,我试图获得更深一层的收获——但没有任何结果。之后,我也使用了这里提出的InsertIcons.exe解决方案


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

我成功地使用了插入器方法,直到赛门铁克反病毒软件开始将我的exe标记为可疑。我的猜测是赛门铁克不喜欢签名的改变,这是因为在构建后的步骤中需要处理exe

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

<PropertyGroup>
   <Win32Resource>icons.res</Win32Resource>
</PropertyGroup>
预构建命令是:

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

我知道。我已经这么做了。如果我编译此文件,exe将具有选定的图标。但是如何添加更多图标?不起作用(添加Resource1.resx、加载ico文件和clean+build解决方案)。嗯,我忘了(明确地)提到我的程序是一个WPF/.NET4应用程序问题解决了。但是我曾经创建过rc/res文件。它的工作原理是完美的,或者只是部署一个包含应用程序的资源的本地DLL,这样就不必运行自定义工具或丢失版本信息。这种方法丢失文件版本信息,如果你恢复它(例如使用C++版本风格。RC文件)-任务管理器/应用程序标题不正确仍然会有问题。(见