Пример как заменить иконку другого приложения программным способом!
Создаём новый класс: NativeMethods.cs
Создаём новый класс: Structures.cs
Создаём последний класс: IconChanger.cs
Вызывается так:
Создаём новый класс: NativeMethods.cs
C#:
namespace IconExUpdate
{
using System;
using System.Runtime.InteropServices;
using System.Security;
[SuppressUnmanagedCodeSecurity()]
internal static class NativeMethods
{
[DllImport("kernel32")]
internal static extern IntPtr BeginUpdateResource(string fileName, [MarshalAs(UnmanagedType.Bool)] bool deleteExistingResources);
[DllImport("kernel32")]
public static extern bool UpdateResource(IntPtr hUpdate, IntPtr type, IntPtr name, short language, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)] byte[] data, int dataSize);
[DllImport("kernel32")]
public static extern bool EndUpdateResource(IntPtr hUpdate, [MarshalAs(UnmanagedType.Bool)] bool discard);
}
}
C#:
namespace IconExUpdate
{
using System.Runtime.InteropServices;
public static class Structures
{
#region For Icon Change
[StructLayout(LayoutKind.Sequential)]
public partial struct ICONDIR
{
public ushort Reserved;
public ushort Type;
public ushort Count;
}
[StructLayout(LayoutKind.Sequential)]
public partial struct ICONDIRENTRY
{
public byte Width;
public byte Height;
public byte ColorCount;
public byte Reserved;
public ushort Planes;
public ushort BitCount;
public int BytesInRes;
public int ImageOffset;
}
[StructLayout(LayoutKind.Sequential)]
public partial struct BITMAPINFOHEADER
{
public uint Size;
public int Width;
public int Height;
public ushort Planes;
public ushort BitCount;
public uint Compression;
public uint SizeImage;
public int XPelsPerMeter;
public int YPelsPerMeter;
public uint ClrUsed;
public uint ClrImportant;
}
[StructLayout(LayoutKind.Sequential, Pack = 2)]
public partial struct GRPICONDIRENTRY
{
public byte Width;
public byte Height;
public byte ColorCount;
public byte Reserved;
public ushort Planes;
public ushort BitCount;
public int BytesInRes;
public ushort ID;
}
#endregion
}
}
Создаём последний класс: IconChanger.cs
C#:
namespace IconExUpdate
{
using System;
using System.IO;
using System.Runtime.InteropServices;
public class IconChanger
{
public void InjectIcon(string exeFileName, string iconFileName)
{
InjectIcon(exeFileName, iconFileName, 1, 1);
}
public void InjectIcon(string exeFileName, string iconFileName, uint iconGroupID, uint iconBaseID)
{
const uint RT_ICON = 3, RT_GROUP_ICON = 14;
var iconFile = FromFile(iconFileName);
var hUpdate = NativeMethods.BeginUpdateResource(exeFileName, false);
var data = iconFile.CreateIconGroupData(iconBaseID);
NativeMethods.UpdateResource(hUpdate, new IntPtr(RT_GROUP_ICON), new IntPtr(iconGroupID), 0, data, data.Length);
for (int i = 0, loopTo = iconFile.ImageCount - 1; i <= loopTo; i++)
{
var image = iconFile.Get_ImageData(i);
NativeMethods.UpdateResource(hUpdate, new IntPtr(RT_ICON), new IntPtr(iconBaseID + i), 0, image, image.Length);
}
NativeMethods.EndUpdateResource(hUpdate, false);
}
private Structures.ICONDIR iconDir = new Structures.ICONDIR();
private Structures.ICONDIRENTRY[] iconEntry;
private byte[][] iconImage;
public int ImageCount => iconDir.Count;
public byte[] Get_ImageData(int index) => iconImage[index];
public static IconChanger FromFile(string filename)
{
var instance = new IconChanger();
try
{
byte[] fileBytes = File.ReadAllBytes(filename);
var pinnedBytes = GCHandle.Alloc(fileBytes, GCHandleType.Pinned);
instance.iconDir = (Structures.ICONDIR)Marshal.PtrToStructure(pinnedBytes.AddrOfPinnedObject(), typeof(Structures.ICONDIR));
instance.iconEntry = new Structures.ICONDIRENTRY[instance.iconDir.Count];
instance.iconImage = new byte[instance.iconDir.Count][];
int offset = Marshal.SizeOf(instance.iconDir);
Type iconDirEntryType = typeof(Structures.ICONDIRENTRY);
int size = Marshal.SizeOf(iconDirEntryType);
for (int i = 0, loopTo = instance.iconDir.Count - 1; i <= loopTo; i++)
{
Structures.ICONDIRENTRY entry = (Structures.ICONDIRENTRY)Marshal.PtrToStructure(new IntPtr(pinnedBytes.AddrOfPinnedObject().ToInt64() + offset), iconDirEntryType);
instance.iconEntry[i] = entry;
instance.iconImage[i] = new byte[entry.BytesInRes];
Buffer.BlockCopy(fileBytes, entry.ImageOffset, instance.iconImage[i], 0, entry.BytesInRes);
offset += size;
}
pinnedBytes.Free();
}
catch { }
return instance;
}
public byte[] CreateIconGroupData(uint iconBaseID)
{
try
{
int sizeOfIconGroupData = Marshal.SizeOf(typeof(Structures.ICONDIR)) + (Marshal.SizeOf(typeof(Structures.GRPICONDIRENTRY)) * ImageCount);
var data = new byte[sizeOfIconGroupData];
var pinnedData = GCHandle.Alloc(data, GCHandleType.Pinned);
Marshal.StructureToPtr(iconDir, pinnedData.AddrOfPinnedObject(), false);
int offset = Marshal.SizeOf(iconDir);
for (int i = 0, loopTo = ImageCount - 1; i <= loopTo; i++)
{
var grpEntry = new Structures.GRPICONDIRENTRY();
var bitmapheader = new Structures.BITMAPINFOHEADER();
var pinnedBitmapInfoHeader = GCHandle.Alloc(bitmapheader, GCHandleType.Pinned);
Marshal.Copy(Get_ImageData(i), 0, pinnedBitmapInfoHeader.AddrOfPinnedObject(), Marshal.SizeOf(typeof(Structures.BITMAPINFOHEADER)));
pinnedBitmapInfoHeader.Free();
grpEntry.Width = iconEntry[i].Width;
grpEntry.Height = iconEntry[i].Height;
grpEntry.ColorCount = iconEntry[i].ColorCount;
grpEntry.Reserved = iconEntry[i].Reserved;
grpEntry.Planes = bitmapheader.Planes;
grpEntry.BitCount = bitmapheader.BitCount;
grpEntry.BytesInRes = iconEntry[i].BytesInRes;
ushort result = unchecked((ushort)(iconBaseID + i));
grpEntry.ID = result;
Marshal.StructureToPtr(grpEntry, new IntPtr(pinnedData.AddrOfPinnedObject().ToInt64() + offset), false);
offset += Marshal.SizeOf(typeof(Structures.GRPICONDIRENTRY));
}
pinnedData.Free();
return data;
}
catch
{
return null;
}
}
}
}
Вызывается так:
C#:
string IconPath = string.Empty; // Переменная где будет путь к иконки
// Добавляем иконку
using var OpenFileDialog = new OpenFileDialog
{
Filter = "Icon Files (*.ico)|*.ico",
FilterIndex = 1,
InitialDirectory = Environment.CurrentDirectory,
RestoreDirectory = true
};
if (OpenFileDialog.ShowDialog() == DialogResult.OK)
{
IconPath = OpenFileDialog.FileName; // Присваиваем переменную к нашему пути до иконки
}
if (!string.IsNullOrEmpty(IconPath)) // Если путь к иконке не пустой
{
var ico = new IconChanger(); // Создаём экземпляр класса.
ico.InjectIcon(outfilePath, IconPath); // Заменяем иконку.
}