Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

StackOverflow Point

StackOverflow Point Navigation

  • Web Stories
  • Badges
  • Tags
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Web Stories
  • Badges
  • Tags
Home/ Questions/Q 185781
Alex Hales
  • 0
Alex HalesTeacher
Asked: June 10, 20222022-06-10T06:52:12+00:00 2022-06-10T06:52:12+00:00

c# – How to get localized name of Known Folder?

  • 0

[ad_1]

Note: .NET solution on the bottom.


you need got IShellItem interface for your folder and call IShellItem::GetDisplayName with SIGDN_NORMALDISPLAY

In UI this name is generally ideal for display to the user.

this return localized names

code in c++ can be like this

HRESULT GetKnownFolderName(int csidl, PWSTR* ppszName)
{
    PIDLIST_ABSOLUTE pidl;

    HRESULT hr = SHGetFolderLocation(0, csidl, 0, 0, &pidl);

    if (S_OK == hr)
    {
        IShellItem* pItem;

        hr = SHCreateItemFromIDList(pidl, IID_PPV_ARGS(&pItem));

        ILFree(pidl);

        if (S_OK == hr)
        {
            hr = pItem->GetDisplayName(SIGDN_NORMALDISPLAY, ppszName);

            pItem->Release();
        }
    }

    return hr;
}

void testDN()
{
    if (0 <= CoInitialize(0))
    {
        PWSTR szName;
        // CSIDL_CONTROLS - for "Control Panel"
        // CSIDL_DRIVES - for "My Computer"
        if (S_OK == GetKnownFolderName(CSIDL_DRIVES, &szName))
        {
            DbgPrint("%S\n", szName);
            CoTaskMemFree(szName);
        }

        CoUninitialize();
    }
}

also if we running only on Vista+ we can use SHGetKnownFolderIDList instead SHGetFolderLocation with FOLDERID_ComputerFolder in place CSIDL_DRIVES or we can get (or already have) IKnownFolder interface first and then got IShellItem from it by IKnownFolder::GetShellItem – so yet two alternative variants begin from vista:

HRESULT GetKnownFolderName(IKnownFolder* kf, PWSTR* ppszName)
{
    IShellItem* psi;

    HRESULT hr = kf->GetShellItem(KF_FLAG_DEFAULT_PATH, IID_PPV_ARGS(&psi));

    if (S_OK == hr)
    {
        hr = psi->GetDisplayName(SIGDN_NORMALDISPLAY, ppszName);

        psi->Release();
    }

    return hr;
}

HRESULT GetKnownFolderNameVista2(REFKNOWNFOLDERID rfid, PWSTR* ppszName)
{
    IKnownFolderManager* mgr;

    HRESULT hr = CoCreateInstance(__uuidof(KnownFolderManager), 0, CLSCTX_ALL, IID_PPV_ARGS(&mgr));

    if (0 <= hr)
    {
        IKnownFolder* kf;

        hr = mgr->GetFolder(rfid, &kf);

        mgr->Release();

        if (S_OK == hr)
        {
            hr = GetKnownFolderName(kf, ppszName);
            kf->Release();
        }
    }

    return hr;
}

HRESULT GetKnownFolderNameVista(REFKNOWNFOLDERID rfid, PWSTR* ppszName)
{
    PIDLIST_ABSOLUTE pidl;

    HRESULT hr = SHGetKnownFolderIDList(rfid, KF_FLAG_NO_ALIAS, 0, &pidl);

    if (S_OK == hr)
    {
        IShellItem* pItem;

        hr = SHCreateItemFromIDList(pidl, IID_PPV_ARGS(&pItem));

        ILFree(pidl);

        if (S_OK == hr)
        {
            hr = pItem->GetDisplayName(SIGDN_NORMALDISPLAY, ppszName);

            pItem->Release();
        }
    }

    return hr;
}

void testDN()
{
    if (0 <= CoInitialize(0))
    {
        PWSTR szName;
        if (S_OK == GetKnownFolderNameVista(FOLDERID_ControlPanelFolder, &szName))
        {
            DbgPrint("%S\n", szName);
            CoTaskMemFree(szName);
        }

        if (S_OK == GetKnownFolderNameVista2(FOLDERID_ComputerFolder, &szName))
        {
            DbgPrint("%S\n", szName);
            CoTaskMemFree(szName);
        }

        CoUninitialize();
    }
}

else one way – use IShellFolder::GetDisplayNameOf with this code will be look like

HRESULT GetKnownFolderName(int csidl, PWSTR* ppszName)
{
    PIDLIST_ABSOLUTE pidl;

    HRESULT hr = SHGetFolderLocation(0, csidl, 0, 0, &pidl);

    if (S_OK == hr)
    {
        IShellFolder* psf;
        PCUITEMID_CHILD pidlLast;

        hr = SHBindToParent(pidl, IID_PPV_ARGS(&psf), &pidlLast);

        if (S_OK == hr)
        {
            STRRET str;
            hr = psf->GetDisplayNameOf(pidlLast, SHGDN_NORMAL, &str);
            psf->Release();

            if (hr == S_OK)
            {
                str.uType == STRRET_WSTR ? *ppszName = str.pOleStr, S_OK : hr = E_FAIL;
            }
        }
    }

    return hr;
}

void testDN()
{
    if (0 <= CoInitialize(0))
    {
        PWSTR szName;
        if (S_OK == GetKnownFolderName(CSIDL_DRIVES, &szName))
        {
            DbgPrint("%S\n", szName);
            CoTaskMemFree(szName);
        }

        if (S_OK == GetKnownFolderName(CSIDL_CONTROLS, &szName))
        {
            DbgPrint("%S\n", szName);
            CoTaskMemFree(szName);
        }

        CoUninitialize();
    }
}

You can use WinApiCodePack library (download from Nuget), which provides .NET implementation of several of mentioned before APIs. Sample code would look like following:

private static string GenerateLocalizedName(IKnownFolder shellFolder)
{
    // Attempt to obtain localized name of folder

    // 1. Directly from KnownFolder
    string localizedName = shellFolder.LocalizedName;

    // 2. From ShellObject (this solves This Computer and Control Panel issue)
    if (String.IsNullOrEmpty(localizedName))
        localizedName = (shellFolder as ShellObject)?.Name;

    // 3. If folder is not virtual, use its localized name from desktop.ini
    if (String.IsNullOrEmpty(localizedName) && Directory.Exists(shellFolder.Path))
    {
        try
        {
            localizedName = WinApiInterop.GetLocalizedName(shellFolder.Path);
        }
        catch
        {
            // Intentionally left empty
        }
    }

    // 4. If folder is not virtual, use its filename
    if (String.IsNullOrEmpty(localizedName) && Directory.Exists(shellFolder.Path))
        localizedName = Path.GetFileName(shellFolder.Path);

    // 5. If everything else fails, use its canonicalName (eg. MyComputerFolder)
    if (String.IsNullOrEmpty(localizedName))
        localizedName = shellFolder.CanonicalName;

    return localizedName;
}

private void LoadShellFolders()
{
    foreach (var shellFolder in KnownFolders.All)
    {
        string localizedName = GenerateLocalizedName(shellFolder);

        string comment = shellFolder.PathExists ? shellFolder.Path : $"shell:{shellFolder.CanonicalName}";

        infos.Add(new ShellFolderInfo(shellFolder.CanonicalName,
            localizedName,
            comment,
            shellFolder.CanonicalName,
            shellFolder.PathExists ? shellFolder.Path : null));
    }
}

Also, the WinApiInterop class, which resolves localized strings from desktop.ini:

static class WinApiInterop
{
    [DllImport("shell32.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode)]
    internal static extern int SHGetLocalizedName(string pszPath, StringBuilder pszResModule, ref int cch, out int pidsRes);

    [DllImport("user32.dll", EntryPoint = "LoadStringW", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode)]
    internal static extern int LoadString(IntPtr hModule, int resourceID, StringBuilder resourceValue, int len);

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, EntryPoint = "LoadLibraryExW")]
    internal static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);

    internal const uint DONT_RESOLVE_DLL_REFERENCES = 0x00000001;
    internal const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;

    [DllImport("kernel32.dll", ExactSpelling = true)]
    internal static extern int FreeLibrary(IntPtr hModule);

    [DllImport("kernel32.dll", EntryPoint = "ExpandEnvironmentStringsW", CharSet = CharSet.Unicode, ExactSpelling = true)]
    internal static extern uint ExpandEnvironmentStrings(string lpSrc, StringBuilder lpDst, int nSize);

    public static string GetFullPath(string path)
    {
        StringBuilder sb = new StringBuilder(1024);

        ExpandEnvironmentStrings(path, sb, sb.Capacity);

        return sb.ToString();
    }

    public static string GetLocalizedName(string path)
    {
        StringBuilder resourcePath = new StringBuilder(1024);
        StringBuilder localizedName = new StringBuilder(1024);
        int len, id;
        len = resourcePath.Capacity;

        if (SHGetLocalizedName(path, resourcePath, ref len, out id) == 0)
        {               
            ExpandEnvironmentStrings(resourcePath.ToString(), resourcePath, resourcePath.Capacity);
            IntPtr hMod = LoadLibraryEx(resourcePath.ToString(), IntPtr.Zero, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
            if (hMod != IntPtr.Zero)
            {
                if (LoadString(hMod, id, localizedName, localizedName.Capacity) != 0)
                {
                    return localizedName.ToString();
                }
                FreeLibrary(hMod);
            }
        }

        return null;
    }
}

[ad_2]

  • 0 0 Answers
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report
Leave an answer

Leave an answer
Cancel reply

Browse

Sidebar

Ask A Question

Related Questions

  • xcode - Can you build dynamic libraries for iOS and ...

    • 0 Answers
  • bash - How to check if a process id (PID) ...

    • 396 Answers
  • database - Oracle: Changing VARCHAR2 column to CLOB

    • 370 Answers
  • What's the difference between HEAD, working tree and index, in ...

    • 361 Answers
  • Amazon EC2 Free tier - how many instances can I ...

    • 0 Answers

Stats

  • Questions : 43k

Subscribe

Login

Forgot Password?

Footer

Follow

© 2022 Stackoverflow Point. All Rights Reserved.

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.