Jump to content
tdxev

Help ! C++ Add icon to exe

Recommended Posts

Posted

Încerc sa adaug o icoana la un executabil (cazul de fata este exe consola ).

Adaug? resursa dar nu ?tiu unde este problema, am cautat pe google dar nu am g?sit un r?spuns pentru problema asta.

Codul de mai jos as vrea sa adauge sau sa modifice icoana unei aplica?ii exe.

Nu am nevoie de exemplele de pe msdn ca le-am citit de zece ori.


/*
|
| Add icon to executables
|
*/
void addNewIcon()
{
std::cout << "Add new icon \n";

HANDLE hFile;
DWORD dwFileSize, dwBytesRead;
LPBYTE lpBuffer;

hFile = CreateFile("c:\\1.ico", GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);

if (INVALID_HANDLE_VALUE != hFile)
{
dwFileSize = GetFileSize(hFile, NULL);
lpBuffer = new BYTE[dwFileSize];
if (ReadFile(hFile, lpBuffer, dwFileSize, &dwBytesRead, NULL) != FALSE)
{
HANDLE hResource;
hResource = BeginUpdateResource("c:\\file.exe", FALSE);
if (NULL != hResource)
{
if (UpdateResource(hResource,
RT_ICON,
MAKEINTRESOURCE(3),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
lpBuffer,
dwFileSize) != FALSE)
{
EndUpdateResource(hResource, FALSE);
}
}
}
delete [] lpBuffer;
CloseHandle(hFile);
}

return;
}

Posted

am reu?it sa copiez o icoana de la alta aplica?ia la cea care doresc eu folosind exemplu de pe msdn dar tot nu reu?esc sa încarc o icoana (*.ico) pentru un executabil dorit

@wildchild o sa caut sa vad dac? o g?sesc

@cifratorul din p?cate nu este acolo problema

Posted

Option Explicit

Public Type ICONDIR
idReserved As Integer ' Reserved (must be 0)
idType As Integer ' Resource Type (1 for icons)
idCount As Integer ' How many images?
'ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em)
End Type

Public Type ICONDIRENTRY
bWidth As Byte ' Width, in pixels, of the image
bHeight As Byte ' Height, in pixels, of the image
bColorCount As Byte ' Number of colors in image (0 if >=8bpp)
bReserved As Byte ' Reserved ( must be 0)
wPlanes As Integer ' Color Planes
wBitCount As Integer ' Bits per pixel
dwBytesInRes As Long ' How many bytes in this resource?
dwImageOffset As Long ' Where in the file is this image?
End Type


Public Type GRPICONDIR
idReserved As Integer ' Reserved (must be 0)
idType As Integer ' Resource Type (1 for icons)
idCount As Integer ' How many images?
'ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em)
End Type

Public Type GRPICONDIRENTRY
bWidth As Byte ' Width, in pixels, of the image
bHeight As Byte ' Height, in pixels, of the image
bColorCount As Byte ' Number of colors in image (0 if >=8bpp)
bReserved As Byte ' Reserved ( must be 0)
wPlanes As Integer ' Color Planes
wBitCount As Integer ' Bits per pixel
dwBytesInRes As Long ' How many bytes in this resource?
dwIconID As Integer ' Where in the file is this image?
End Type

Public Type Dat
Data() As Byte
End Type

Public Type Ico
IcoDir As ICONDIR
Entries() As ICONDIRENTRY
IcoData() As Dat
End Type

Public Type IcoExe
IcoDir As GRPICONDIR
Entries() As GRPICONDIRENTRY
End Type

Private Declare Function BeginUpdateResource Lib "kernel32.dll" Alias "BeginUpdateResourceA" (ByVal pFileName As String, ByVal bDeleteExistingResources As Long) As Long
Private Declare Function UpdateResource Lib "kernel32.dll" Alias "UpdateResourceA" (ByVal hUpdate As Long, ByVal lpType As Long, ByVal lpName As Long, ByVal wLanguage As Long, lpData As Any, ByVal cbData As Long) As Long
Private Declare Function EndUpdateResource Lib "kernel32.dll" Alias "EndUpdateResourceA" (ByVal hUpdate As Long, ByVal fDiscard As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Private Const RT_ICON As Long = 3&
Private Const DIFFERENCE As Long = 11
Private Const RT_GROUP_ICON As Long = (RT_ICON + DIFFERENCE)

'// ReplaceIcoInExe "C:\EXEtoReplace.exe", OpenIconFile("C:\NewIcon.ico")

Public Function OpenIconFile(FileName As String) As Ico
Dim t As Ico 'structure temporaire
Dim X As Long 'compteur

'on ouvre le fichier
Open FileName For Binary As #1
'on récup?re l'entete du fichier
Get #1, , t.IcoDir

'redimensionne au nombre d'icones
ReDim t.Entries(0 To t.IcoDir.idCount - 1)
ReDim t.IcoData(0 To t.IcoDir.idCount - 1)

'pour chaque icones
For X = 0 To t.IcoDir.idCount - 1
'récup?re l'entete de l'icone
Get #1, 6 + 16 * X + 1, t.Entries(X)
'redimensionne ? la taille des données
ReDim t.IcoData(X).Data(t.Entries(X).dwBytesInRes - 1)
'récup?re les données
Get #1, t.Entries(X).dwImageOffset + 1, t.IcoData(X).Data
Next
'ferme le fichier
Close #1
'renvoie les données
OpenIconFile = t
End Function

Private Function MakeIcoExe(IconFile As Ico) As IcoExe
Dim t As IcoExe 'structure temporaire
Dim X As Long 'compteur

'nombre d'icones
t.IcoDir.idCount = IconFile.IcoDir.idCount
'type : Icone = 1
t.IcoDir.idType = 1
'chaque entrée
ReDim t.Entries(IconFile.IcoDir.idCount - 1)

'pour chaque entrée
For X = 0 To t.IcoDir.idCount - 1
'entete d'icones
t.Entries(X).bColorCount = IconFile.Entries(X).bColorCount
t.Entries(X).bHeight = IconFile.Entries(X).bHeight
t.Entries(X).bReserved = IconFile.Entries(X).bReserved
t.Entries(X).bWidth = IconFile.Entries(X).bWidth
t.Entries(X).dwBytesInRes = IconFile.Entries(X).dwBytesInRes
t.Entries(X).dwIconID = X + 1
t.Entries(X).wBitCount = IconFile.Entries(X).wBitCount
t.Entries(X).wPlanes = IconFile.Entries(X).wPlanes
Next
'renvoie la structure
MakeIcoExe = t
End Function

Public Function ReplaceIcoInExe(FileName As String, IcoFile As Ico) As Boolean
Dim hWrite As Long 'handle de modification
Dim Exe As IcoExe 'structure de ressource icone
Dim ret As Long 'valeur de retour
Dim X As Long 'compteur
Dim D() As Byte 'buffer

'obtient un handle de modification
hWrite = BeginUpdateResource(FileName, 0)

'si échec, on quitte
If hWrite = 0 Then ReplaceIcoInExe = False: Exit Function

'sinon, on lit l'icone
Exe = MakeIcoExe(IcoFile)

'on redimmensionne le buffer
ReDim D(6 + 14 * Exe.IcoDir.idCount)
'on copie les données dans le buffer
CopyMemory ByVal VarPtr(D(0)), ByVal VarPtr(Exe.IcoDir), 6

'pour chaque icone
For X = 0 To Exe.IcoDir.idCount - 1
'on copie les données
CopyMemory ByVal VarPtr(D(6 + 14 * X)), ByVal VarPtr(Exe.Entries(X).bWidth), 14&
Next

'on met ? jour la ressource groupe icone
ret = UpdateResource(hWrite, RT_GROUP_ICON, 1, 0, ByVal VarPtr(D(0)), UBound(D))

'si échec, on quitte
If ret = 0 Then ReplaceIcoInExe = False: EndUpdateResource hWrite, 1: Exit Function

'on met ? jour chaque ressource icone
For X = 0 To Exe.IcoDir.idCount - 1
ret = UpdateResource(hWrite, RT_ICON, Exe.Entries(X).dwIconID, 0, ByVal VarPtr(IcoFile.IcoData(X).Data(0)), Exe.Entries(X).dwBytesInRes)
Next

'on enregsitre dans le fichier executable
ret = EndUpdateResource(hWrite, 0)
'si échec, on quitte
If ret = 0 Then ReplaceIcoInExe = False: Exit Function

'sinon succ?s
ReplaceIcoInExe = True
End Function

Maine, daca stau pe acasa, il portez eu in C/C++. Adica azi, ca e aproape 4...

Sau asta:

Option Explicit

Type DIB_HEADER
Size As Long
Width As Long
Height As Long
Planes As Integer
Bitcount As Integer
Reserved As Long
ImageSize As Long
End Type

Type ICON_DIR_ENTRY
bWidth As Byte
bHeight As Byte
bColorCount As Byte
bReserved As Byte
wPlanes As Integer
wBitCount As Integer
dwBytesInRes As Long
dwImageOffset As Long
End Type

Type ICON_DIR
Reserved As Integer
Type As Integer
Count As Integer
End Type

Type DIB_BITS
Bits() As Byte
End Type

Public Enum Errors
FILE_CREATE_FAILED = 1000
FILE_READ_FAILED
INVALID_PE_SIGNATURE
INVALID_ICO
NO_RESOURCE_TREE
NO_ICON_BRANCH
CANT_HACK_HEADERS
End Enum
Public Function ReplaceIcons(Source As String, Dest As String, Error As String) As Long

Dim IcoDir As ICON_DIR
Dim IcoDirEntry As ICON_DIR_ENTRY
Dim tBits As DIB_BITS
Dim Icons() As IconDescriptor
Dim lngRet As Long
Dim BytesRead As Long
Dim hSource As Long
Dim hDest As Long
Dim ResTree As Long

hSource = CreateFile(Source, ByVal &H80000000, 0, ByVal 0&, 3, 0, ByVal 0)
If hSource >= 0 Then
If Valid_ICO(hSource) Then
SetFilePointer hSource, 0, 0, 0
ReadFile hSource, IcoDir, 6, BytesRead, ByVal 0&
ReadFile hSource, IcoDirEntry, 16, BytesRead, ByVal 0&
SetFilePointer hSource, IcoDirEntry.dwImageOffset, 0, 0
ReDim tBits.Bits(IcoDirEntry.dwBytesInRes) As Byte
ReadFile hSource, tBits.Bits(0), IcoDirEntry.dwBytesInRes, BytesRead, ByVal 0&
CloseHandle hSource
hDest = CreateFile(Dest, ByVal (&H80000000 Or &H40000000), 0, ByVal 0&, 3, 0, ByVal 0)
If hDest >= 0 Then
If Valid_PE(hDest) Then
ResTree = GetResTreeOffset(hDest)
If ResTree > 308 Then ' Sanity check
lngRet = GetIconOffsets(hDest, ResTree, Icons)
SetFilePointer hDest, Icons(1).Offset, 0, 0
WriteFile hDest, tBits.Bits(0), UBound(tBits.Bits), BytesRead, ByVal 0&
If Not HackDirectories(hDest, ResTree, Icons(1).Offset, IcoDirEntry) Then
Err.Raise CANT_HACK_HEADERS, App.EXEName, "Unable to modify directories in target executable. File may not contain any icon resources."
End If
Else
Err.Raise NO_RESOURCE_TREE, App.EXEName, Dest & " does not contain a valid resource tree. File may be corrupt."
CloseHandle hDest
End If
Else
Err.Raise INVALID_PE_SIGNATURE, App.EXEName, Dest & " is not a valid Win32 executable."
CloseHandle hDest
End If
CloseHandle hDest
Else
Err.Raise FILE_CREATE_FAILED, App.EXEName, "Failed to open " & Dest & ". Make sure file is not in use by another program."
End If
Else
Err.Raise INVALID_ICO, App.EXEName, Source & " is not a valid icon resource file."
CloseHandle hSource
End If
Else
Err.Raise FILE_CREATE_FAILED, App.EXEName, "Failed to open " & Source & ". Make sure file is not in use by another program."
End If
ReplaceIcons = 0
Exit Function
ErrHandler:
ReplaceIcons = Err.Number
Error = Err.Description
End Function
Public Function Valid_ICO(hFile As Long) As Boolean
Dim tDir As ICON_DIR
Dim BytesRead As Long
If (hFile > 0) Then
ReadFile hFile, tDir, Len(tDir), BytesRead, ByVal 0&
If (tDir.Reserved = 0) And (tDir.Type = 1) And (tDir.Count > 0) Then
Valid_ICO = True
Else
Valid_ICO = False
End If
Else
Valid_ICO = False
End If
End Function

Am niste probleme stupide, pe o structura din C. "Imi sare" peste un cam din structura, ca si cum nu ar fi. Sa vad daca reusesc sa scap de problema.

Posted

Nu stiu de ce nu merge. De fapt schimba iconita, dar STRICA executabilul.

Poate te ajuta cu ceva:


/*
Nume: Icon Changer portat din Visual Basic 6
Autor: Gheorghe Vasile
Status: Functionare partiala
*/

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

typedef struct ICONDIR
{
short idReserved;
short idType;
short idCount;
} ICONDIR;

typedef struct ICONDIRENTRY
{
unsigned char bWidth;
unsigned char bHeight;
unsigned char bColorCount;
unsigned char bReserved;
short wPlanes;
short wBitCount;
int dwBytesInRes;
int dwImageOffset;
} ICONDIRENTRY;

typedef struct GRPICONDIR
{
short idReserved;
short idType;
short idCount;
} GRPICONDIR;

typedef struct GRPICONDIRENTRY
{
unsigned char bWidth;
unsigned char bHeight;
unsigned char bColorCount;
unsigned char bReserved;
short wPlanes;
short wBitCount;
long dwBytesInRes;
long dwIconID;
} GRPICONDIRENTRY;

typedef struct Dat
{
unsigned char *Data;
} Dat;

typedef struct Ico
{
ICONDIR IcoDir;
ICONDIRENTRY *Entries;
Dat *IcoData;
} Ico;

typedef struct IcoExe
{
GRPICONDIR IcoDir;
GRPICONDIRENTRY *Entries;
} IcoExe;

Ico OpenIconFile(const char *Filename)
{
Ico t;
FILE *fisier;
int i;

fisier = fopen(Filename, "rb");

fread(&t.IcoDir, sizeof(ICONDIR), 1, fisier);

t.Entries = (ICONDIRENTRY *)malloc(sizeof(ICONDIRENTRY) * t.IcoDir.idCount);
t.IcoData = (Dat *)malloc(sizeof(Dat) * t.IcoDir.idCount);

for(i = 0; i <= t.IcoDir.idCount - 1; i++)
{
fseek(fisier, 6 + (16 * i), SEEK_SET);
fread(&t.Entries[i], sizeof(ICONDIRENTRY), 1, fisier);

t.IcoData[i].Data = (unsigned char *)malloc(t.Entries[i].dwBytesInRes);

fseek(fisier, t.Entries[i].dwImageOffset, SEEK_SET);

t.IcoData[i].Data = (unsigned char *)malloc(t.Entries[i].dwBytesInRes);
fread(t.IcoData[i].Data, t.Entries[i].dwBytesInRes, 1, fisier);
}

fclose(fisier);

return t;
}

IcoExe MakeIcoExe(Ico IconFile)
{
IcoExe t;
long i;

t.IcoDir.idCount = IconFile.IcoDir.idCount;
t.IcoDir.idType = 1;
t.IcoDir.idReserved = 0;

t.Entries = (GRPICONDIRENTRY *)malloc(sizeof(GRPICONDIRENTRY) * t.IcoDir.idCount);

for(i = 0; i <= t.IcoDir.idCount - 1; i++)
{
t.Entries[i].bColorCount = IconFile.Entries[i].bColorCount;
t.Entries[i].bHeight = IconFile.Entries[i].bHeight;
t.Entries[i].bReserved = IconFile.Entries[i].bReserved;
t.Entries[i].bWidth = IconFile.Entries[i].bWidth;
t.Entries[i].dwBytesInRes = IconFile.Entries[i].dwBytesInRes;
t.Entries[i].dwIconID = i + 1;
t.Entries[i].wBitCount = IconFile.Entries[i].wBitCount;
t.Entries[i].wPlanes = IconFile.Entries[i].wPlanes;
}

return t;
}

int ReplaceIcoInExe(const char *FileName, Ico IcoFile)
{
int ret, i, aux;
HANDLE hWrite;
IcoExe Exe;
unsigned char *D;

hWrite = BeginUpdateResource(FileName, 0);

Exe = MakeIcoExe(IcoFile);

aux = 6 + 14 * Exe.IcoDir.idCount;
D = (unsigned char *)malloc(aux);
CopyMemory(D, &Exe.IcoDir, 6);

for(i = 0; i <= Exe.IcoDir.idCount - 1; i++)
{
CopyMemory(&D[6 + 14 * i], &Exe.Entries[i], 14);
}

ret = UpdateResource(hWrite, RT_GROUP_ICON, MAKEINTRESOURCE(1), 0, D, aux);

if(ret == 0)
{
EndUpdateResource(hWrite, 1);
return 0;
}

for(i = 0; i <= Exe.IcoDir.idCount - 1; i++)
{
ret = UpdateResource(hWrite, RT_ICON, MAKEINTRESOURCE(Exe.Entries[i].dwIconID), 0, IcoFile.IcoData[i].Data, Exe.Entries[i].dwBytesInRes);
}

ret = EndUpdateResource(hWrite, 0);

if(ret == 0) return 0;
else return 1;
}

int main()
{
printf("Rezultat: %d\n\n", ReplaceIcoInExe("F:\\x.exe", OpenIconFile("F:\\g.ico")));
return 0;
}

  • Upvote 1
Posted

merci Nytro! o sa încerc sa vad dac? reu?esc..

Later:

- am f?cut proba pe aplica?ii ?i într-adev?r pe unele le strica,

- am testat pe acelea?i aplica?ii ?i cu XN Resource Editor ?i nici el nu se descurca mai bine (?i el stric? aplica?iile, în majoritatea cazurilor acestea fiind installer-e)

- partea buna este ca pentru aplica?ia(consola) pentru care aveam nevoie merge perfect

Posted

Cu placere.

Cred ca buba e la "ReplaceIcoInExe". Am verificat valorile datelor din celelalte functii si nu am gasit probleme.

Codul original in VB6 foloseste dimensiuni fixe pentru structuri ca 6, 16... Si:

aux = 6 + 14 * Exe.IcoDir.idCount;

Cred ca e de fapt: aux = 6 + 16 * Exe.IcoDir.idCount;

Deoarece acea structura cred ca e de sizeof() == 16.

Problema e probabil sa fie la

ret = UpdateResource(hWrite, RT_GROUP_ICON, MAKEINTRESOURCE(1), 0, D, aux);

sau la celalalt apel al acestei functii. Am avut probleme, in VB6 erau declarate cu parametrii de tip Long 2 dintre parametrii, si sunt de fapt LPTCSTR.

Ma mai uit peste el, poate gasesc problema... Ciudat e ca imi facea executabilul mult mai mic.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...