5

I have an app created in MFC that needs to have one of several icons set for the exe. I don't know which icon to use until the app is installed on the users' machine. I have followed several sites (including https://learn.microsoft.com/en-us/windows/win32/menurc/using-resources) on how to do this programmatically.

The icon the exe uses in the app's .rc file is IDR_MAINFRAME (ID 128) and is just a standard .ico file. After running the update code, when I open the exe in Visual Studio, I see that the icon for IDR_MAINFRAME has been updated to the correct icon, but the image used for the exe in Explorer is still showing the old (original) icon. I don't see any references to the original icon in the updated exe.

What am I missing here?

HGLOBAL hResLoad;   // handle to loaded resource
HMODULE hExe;       // handle to existing .EXE file
HRSRC hRes;         // handle/ptr. to res. info. in hExe
HANDLE hUpdateRes;  // update resource handle
LPVOID lpResLock;   // pointer to resource data
BOOL result;

hExe = LoadLibrary(TEXT("app.exe"));
if (hExe == NULL)
{
  return;
}

// Locate the icon resource in the .EXE file.
hRes = FindResource(hExe, MAKEINTRESOURCE(IDI_TB_SAVE), RT_GROUP_ICON);
if (hRes == NULL)
{
  return;
}

// Load the resource into global memory.
hResLoad = LoadResource(hExe, hRes);
if (hResLoad == NULL)
{
  return;
}

// Lock the resourcex into global memory.
lpResLock = LockResource(hResLoad);
if (lpResLock == NULL)
{
  return;
}
 
// Open the file to which you want to add the icon resource.
hUpdateRes = BeginUpdateResource(TEXT("app_updated.exe"), FALSE);
if (hUpdateRes == NULL)
{
  return;
}

result = UpdateResource(hUpdateRes,    // update resource handle
  RT_GROUP_ICON,                         // change icon resource
  MAKEINTRESOURCE(IDR_MAINFRAME),         // resource id
  MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),  // english
  lpResLock,                         // ptr to resource info
  SizeofResource(hExe, hRes));       // size of resource info

if (result == FALSE)
{
  return;
}

// Write changes to app_updated.exe and then close it.
if (!EndUpdateResource(hUpdateRes, FALSE))
{
  return;
}

// Clean up.
if (!FreeLibrary(hExe))
{
  return;
}
drescherjm
  • 10,365
  • 5
  • 44
  • 64
Tony Nelson
  • 141
  • 5
  • 3
    Explorer caches Icons for a time. If it didn't it would be too slow opening a folder with a large number of executable files (it would have to read and parse each one). Try https://superuser.com/questions/499078/refresh-icon-cache-without-rebooting – Richard Critten May 25 '21 at 15:48
  • @RichardCritten Yep, it was a caching problem. Thanks! – Tony Nelson May 25 '21 at 16:01
  • 1
    Such a rare chance to upvote a well-formed, well-phrased, and well-scoped question. – IInspectable May 25 '21 at 16:05

1 Answers1

0

Following @RichardCritten's suggestion, I refreshed the icon cache (just restarted explorer.exe) and the updated icon showed up correctly. The code is sound.

Tony Nelson
  • 141
  • 5