简体   繁体   中英

Update folder icon with desktop.ini & instantly change (C++)

After reading a lot and trying for 2 days in a row, I managed to make something work by following this Microsoft tutorial on folder icons , but it's not perfect - changes don't take place immediately. I need to restart explorer / reboot my computer or wait a couple of minutes (randomly) until I see the old icon change to the new icon.

TL;DR

Expected result: I want to programmatically update my folder icon and see that the new icon take place instantly, without waiting. (using c++ , .bat , node.js or anything else that would work, I don't mind really).

Problem: After chaining my .ico file, I expect to see the result immideiately, but I only see it after 30 seconds to 4 minutes or so. It changes instantly as well sometimes, but very rarely, and I want it to work 100% of the time.

Requirements and notes:

  • It must not restart Explorer.
  • It would be better if it would not clear the entire thumbnail cache from all folders and files, as it only needs to update a single folder icon.

Hopes / unfulfilling attempts

Renaming desktop.ini programmatically (Not working unfortunately)

I found a way to see the icon change immediately, but it worked only when manually renaming desktop.ini through the explorer itself. (changing desktop.ini to uppercase/lowercase or to desktop-temp.ini and then back to desktop.ini) When doing so, I see the folder icon change immediately.

That led me to a hope that I can do the same programmatically, so I tried this C++ code, that changes desktop.ini to desktop-temp.ini and back to desktop.ini , also with notifying windows that a change has occurred, but it did not work unfortunately.

#include <stdio.h>
#include <Windows.h>
#include <winbase.h>
#include <Tchar.h>
#include <shlobj.h> // for SHGetSpecialFolderPathA


const char folderpath[] = "C:\\Users\\elron\\Elron Apps C\\005 Folder Icon\\paste-folder-icon";

int main()
{
    // rename("C:\\Users\\elron\\Elron Apps C\\005 Folder Icon\\paste-folder-icon\\desktop.ini", "desktop-temp.ini");

    if (MoveFile(_T("C:\\Users\\elron\\Elron Apps C\\005 Folder Icon\\paste-folder-icon\\desktop.ini"), _T("desktop-temp.ini")))
    {
        printf("succeeded\n");
    }
    else
    {
        printf("Error %d\n", GetLastError());
    }

    SHChangeNotify(SHCNE_ALLEVENTS, SHCNF_NOTIFYRECURSIVE, NULL, NULL);
    SHChangeNotify(SHCNE_ALLEVENTS, SHCNF_NOTIFYRECURSIVE, folderpath, NULL);

    if (MoveFile(_T("C:\\Users\\elron\\Elron Apps C\\005 Folder Icon\\paste-folder-icon\\desktop-temp.ini"), _T("desktop.ini")))
    {
        printf("succeeded\n");
    }
    else
    {
        printf("Error %d\n", GetLastError());
    }

    SHChangeNotify(SHCNE_ALLEVENTS, SHCNF_NOTIFYRECURSIVE, NULL, NULL);
    SHChangeNotify(SHCNE_ALLEVENTS, SHCNF_NOTIFYRECURSIVE, folderpath, NULL);
}

SHChangeNotify() (works, but not immidiately)

Inspired by: How to refresh the folder icon instantly in Windows

I tried running this C++ code (after compiling using npm command g++ -o refresh-folder-icons refresh-folder-icons.cpp ) and it worked, but I the changes take place between 1 to 5 minutes and if you're lucky. then you see it instantly. This is not reliable. I tested this on two computers (both Windows 10).

#include <windows.h>
#include <ShlObj.h>

const char folderPath[] = "path/to/folder";

int main()
{
    SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, folderPath, NULL);
    SHChangeNotify(SHCNE_ALLEVENTS, SHCNF_NOTIFYRECURSIVE, "path/to/folder/desktop.ini", NULL);
}

"Use a shell function that will notify all running Explorer windows to use the updated desktop.ini" using VBScript (Did not work for me)

I've also tried creating a .bat file followed by this: Changing desktop.ini doesn't update folder icon automatically in Windows but my folder still shows the previous icon.

Refresh Icons Using IE4UINIT

Following this

Run the following command (for Windows 10) and hit Enter: ie4uinit.exe -show For Windows 8 and earlier, run this command instead: ie4uinit.exe -ClearIconCache

Refresh Icons Using NirCmd

Following this tutorial (step 3) , I tried installing NirCmd and running all three, none of them refreshed my folder icon:

nircmd.exe sysrefresh 

nircmd.exe sysrefresh environment 

nircmd.exe sysrefresh policy

SHGetSetFolderCustomSettings() (My main hope!!!)

Someone wrote here that the SHGetSetFolderCustomSettings "function sets an icon and sends all necessary notification by itself", and that really have me hope that this is the right path.

Also, in Peter Tseng's answer here and here he shows a sample code that worked, but when I try to complie this C++ code into .exe , I get errors. This is the code:

#include <windows.h>
#include <shlobj.h>

int main()
{
    SHFOLDERCUSTOMSETTINGS pfcs;
    pfcs.dwMask = "C:\\Users\\elron\\Elron Apps C\\005 Folder Icon\\paste-folder-icon\\folderico-1629960936.ico";
    pfcs.pszIconFile = "C:\\Users\\elron\\Elron Apps C\\005 Folder Icon\\paste-folder-icon\\folderico-1629960936.ico";
    pfcs.cchIconFile = 0;
    pfcs.iIconIndex = 0;
    PCWSTR pszPath = L"C:\\Users\\elron\\Elron Apps C\\005 Folder Icon\\paste-folder-icon\\test\\hey";
    SHGetSetFolderCustomSettings(pfcs, pszPath, FCS_FORCEWRITE);
}

but I get three errors, all indicating to the same problem:

  • 'SHFOLDERCUSTOMSETTINGS' was not declared in this scope (gcc)
  • 'pfcs' was not declared in this scope (gcc)
  • 'SHGetSetFolderCustomSettings' was not declared in this scope (gcc)

Why am I getting this error? Is there's a dependency I'm missing? I'm using windows 10.


I managed to get working the last approach (using SHGetSetFolderCustomSettings() )

#include <windows.h>
#include <shlobj.h>

int main()
{
    /*
    convert the icon's path to LPWSTR, as required by field pszIconFile
    method taken from https://stackoverflow.com/questions/29847036/convert-char-to-wchar-t-using-mbstowcs-s
    */
    const char* iconPath = "C:\\Users\\YourUsername\\PathTo\\YourIcon\\file.ico";
    size_t size = strlen(iconPath) + 1;
    wchar_t* wtext = new wchar_t[size];

    size_t outSize;
    mbstowcs_s(&outSize, wtext, size, iconPath, size - 1);
    LPWSTR ptr = wtext;

    // (fixed the initialization of some fields)
    SHFOLDERCUSTOMSETTINGS pfcs{};
    pfcs.dwSize = sizeof(SHFOLDERCUSTOMSETTINGS);
    pfcs.dwMask = FCSM_ICONFILE;
    pfcs.pszIconFile = ptr;
    pfcs.cchIconFile = 0;
    pfcs.iIconIndex = 0;
    PCWSTR pszPath = L"C:\\Users\\YourUsername\\PathTo\\YourFolder\\FolderToCustomize";
    SHGetSetFolderCustomSettings(&pfcs, pszPath, FCS_FORCEWRITE);
}

I think the problems you mentioned:

but I get three errors, all indicating to the same problem:

  • 'SHFOLDERCUSTOMSETTINGS' was not declared in this scope (gcc)

might be caused because you weren't using the appropriate compiler. I got similar compile errors when using g++ directly from the console/on Visual Studio Code, but the same code worked when using Visual Studio 2022 (Visual C++ compiler). I'm also new to C++, so feel free to correct me if this is not the source of the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM