Search code examples
c++windowsregistrycontextmenuregedit

Windows registry key AppliesTo does not work with Users directory


What I am trying to do is to enable a customized context menu item to appear when users right-click folders in a specific directory.

So in HKEY_CLASSES_ROOT\Directory\shell I created my key (say with the name: MyProgram), and I created the subkey command that has the path to my program to run (say, "C:\Users\myuser\myApp\MyProgram.exe").

Until now it is ok and works correctly. But when I add the entry AppliesTo under HKEY_CLASSES_ROOT\Directory\shell\MyProgram and set it to C:\Users it does not work and the context menu item does not appear anymore!

Important Note: My windows language is German and the display name of Users folder in my windows explorer is Benutzer. Whenever I set AppliesTo to C:\Benutzer instead it works correctly, despite the fact that the command works with Users path properly! Alsowhen I echo %USERPROFILE% in the cmd it is printed in English as C:\Users\myuser and not Benutzer.

Is there a way to programmatically get the display path of Users or any folder in the system?

Please note: I cannot simply write Benutzer instead of Users in the path because the path can be dynamic. I am doing it programmatically and want my code to have consistent behavior in different machines with different languages. I am using C++ winreg API to set the registry values (for example: RegOpenKeyEx() and RegSetValueEx()).

Below is an export of the working version of the key:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Directory\shell\MyProgram]
"AppliesTo"="C:\\Benutzer\\myuser"

[HKEY_CLASSES_ROOT\Directory\shell\MyProgram\command]
@="\"C:\\Users\\myuser\\path\\to\\MyProgram.exe\" \"%1\""

Solution

  • I found the solution. The localized name of folders can be obtained using the function SHGetLocalizedName, however it requires some additional work to get the string representation of the localized name. The following code snippet shows an example of how to do it.

    PWSTR name = new WCHAR[100];;
    PCWSTR folder = TEXT("C:\\Users");
    UINT len=100;
    int id=0;
    
    HRESULT hr = SHGetLocalizedName(folder, name, len, &id);
    
    if (SUCCEEDED(hr)) {
        wprintf(L"%ls\n", name);
        ExpandEnvironmentStrings(name, name, len);
        HMODULE shell_handle = LoadLibraryEx(name, NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
        if (shell_handle) {
            if (LoadString(shell_handle, id, name, len) != 0) {
                wprintf(L"%ls\n", name);
            }
            FreeLibrary(shell_handle);
        }
    }
    

    The result of the previous code will be Benutzer in case of German locale.

    You will need to include the following headers as well

    #include <wchar.h>
    #include <Shellapi.h>