Это решение, которое сработало для меня. Я не смог написать это в .NET, но мне удалось написать C ++ DLL, на которую я ссылаюсь в моем приложении C #.
C ++ DLL
Содержимое решения C ++, из которого я собираю DLL:
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <windows.h>
extern "C"
{
#pragma pack(push, 2)
typedef struct {
WORD Reserved1; // reserved, must be 0
WORD ResourceType; // type is 1 for icons
WORD ImageCount; // number of icons in structure (1)
BYTE Width; // icon width (32)
BYTE Height; // icon height (32)
BYTE Colors; // colors (0 means more than 8 bits per pixel)
BYTE Reserved2; // reserved, must be 0
WORD Planes; // color planes
WORD BitsPerPixel; // bit depth
DWORD ImageSize; // size of structure
WORD ResourceID; // resource ID
} GROUPICON;
#pragma pack(pop)
__declspec(dllexport) void __stdcall ChangeIcon(char *executableFile, char *iconFile, INT16 imageCount)
{
int len = strlen(executableFile) + 1;
wchar_t *executableFileEx = new wchar_t[len];
memset(executableFileEx, 0, len);
::MultiByteToWideChar(CP_ACP, NULL, executableFile, -1, executableFileEx, len);
len = strlen("MAINICON") + 1;
wchar_t *mainIconEx = new wchar_t[len];
memset(mainIconEx, 0, len);
::MultiByteToWideChar(CP_ACP, NULL, "MAINICON", -1, mainIconEx, len);
HANDLE hWhere = BeginUpdateResource(executableFileEx, FALSE);
char *buffer; // Buffer to store raw icon data
long buffersize; // Length of buffer
int hFile; // File handle
hFile = open(iconFile, O_RDONLY | O_BINARY);
if (hFile == -1)
return; // If file doesn't exist, can't be opened etc.
// Calculate buffer length and load file into buffer
buffersize = filelength(hFile);
buffer = (char *)malloc(buffersize);
read(hFile, buffer, buffersize);
close(hFile);
// Calculate header size
int headerSize = 6 + imageCount * 16;
UpdateResource(
hWhere, // Handle to executable
RT_ICON, // Resource type - icon
MAKEINTRESOURCE(1), // Make the id 1
MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), // Default language
buffer + headerSize, // Skip the header bytes
buffersize - headerSize // Length of buffer
);
GROUPICON grData;
grData.Reserved1 = 0; // reserved, must be 0
grData.ResourceType = 1; // type is 1 for icons
grData.ImageCount = 1; // number of icons in structure (1)
grData.Width = 32; // icon width (32)
grData.Height = 32; // icon height (32)
grData.Colors = 0; // colors (256)
grData.Reserved2 = 0; // reserved, must be 0
grData.Planes = 2; // color planes
grData.BitsPerPixel = 32; // bit depth
grData.ImageSize = buffersize - 22; // size of image
grData.ResourceID = 1; // resource ID is 1
UpdateResource(
hWhere,
RT_GROUP_ICON,
// RT_GROUP_ICON resources contain information
// about stored icons
mainIconEx,
// MAINICON contains information about the
// application's displayed icon
MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
&grData,
// Pointer to this structure
sizeof(GROUPICON)
);
delete buffer; // free memory
// Perform the update, don't discard changes
EndUpdateResource(hWhere, FALSE);
}
}
код C #
Это код C #, который я использую для импорта функции ChangeIcon
из ранее написанной DLL:
[DllImport("IconChanger.dll")]
static extern void ChangeIcon(String executableFile, String iconFile, short imageCount);
/// <summary>
/// Changes the executable's icon
/// </summary>
/// <param name="exeFilePath">Path to executable file</param>
/// <param name="iconFilePath">Path to icon file</param>
static public void ChangeIcon(string exeFilePath, string iconFilePath)
{
short imageCount = 0;
using (StreamReader sReader = new StreamReader(iconFilePath))
{
using (BinaryReader bReader = new BinaryReader(sReader.BaseStream))
{
// Retrieve icon count inside icon file
bReader.ReadInt16();
bReader.ReadInt16();
imageCount = bReader.ReadInt16();
}
}
// Change the executable's icon
ChangeIcon(exeFilePath, iconFilePath, imageCount);
}
Надеюсь, что кто-нибудь найдет это полезным.