65.9K
CodeProject is changing. Read more.
Home

Get Elements of a Known Folder with Windows API for w10

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (5 votes)

May 23, 2021

CPOL
viewsIcon

5250

Get elements of known folder with the most recent API

Download

Introduction

It shows subelements, directly from a known folder under Windows 10, with the most recent APIs. It's a very simple example for beginners. Written in C#, .NET Core 3.1. There is no UI, just console to not interfere.

Background

This tip have been written with research on pinvoke, internet, and I found most of the solution on the Raymon Chen's blog.

Using the Code

Here is the most part of the code, to understand easily how to deal with API windows. All the interfaces and enums are available in the package source or on my github.

 

 class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Start...");

            HResult reslt = HResult.E_FAIL;

            // On récupère l'élement
            // Get element
            IShellItem spsiFolder;
            int res = ShellAPI.SHGetKnownFolderItem(
                        new Guid(KnownFolderID.ComputerFolder),
                        (uint)KnownFolderFlags.None,
                        IntPtr.Zero,
                        typeof(IShellItem).GUID,
                        out spsiFolder);

            // Récupération du nom
            // Get Name
            IntPtr pName;
            reslt = spsiFolder.GetDisplayName(SIGDN.NORMALDISPLAY, out pName);
            if (reslt == HResult.S_OK)
            {
                // On affiche
                // Show directly value
                Console.WriteLine(Marshal.PtrToStringUni(pName));
                // On libère
                // Free it
                Marshal.FreeCoTaskMem(pName);
            }

        // Get handle on sub elements
        IntPtr pEnum;
            reslt = spsiFolder.BindToHandler(IntPtr.Zero, new Guid(BHID.EnumItems),
                                typeof(IEnumShellItems).GUID, out pEnum);

            if (reslt == HResult.S_OK)
            {
                IntPtr pszName = IntPtr.Zero;
                IntPtr pszPath = IntPtr.Zero;
                IEnumShellItems pEnumShellItems = null;

                pEnumShellItems = Marshal.GetObjectForIUnknown(pEnum) as IEnumShellItems;

                IShellItem psi = null;
                uint nFetched = 0;
                while (HResult.S_OK == 
                       pEnumShellItems.Next(1, out psi, out nFetched) && nFetched == 1)
                {
                    pszName = pszPath = IntPtr.Zero;

                    // Pointeurs
                    reslt = psi.GetDisplayName(SIGDN.NORMALDISPLAY, out pszName);
                    reslt = psi.GetDisplayName(SIGDN.DESKTOPABSOLUTEEDITING, out pszPath);

                    if (reslt == HResult.S_OK)
                    {
                        // Récupérer les valeurs
                        // Retrieve values to a string
                        string sDisplayName = Marshal.PtrToStringUni(pszName);
                        string sDisplayPath = Marshal.PtrToStringUni(pszPath);

                        // Résultat
                        Console.WriteLine(string.Format("\tItem Name : {0}", sDisplayName));
                        Console.WriteLine(string.Format("\tItem Path : {0}", sDisplayPath));

                        // On libère
                        // Free it
                        Marshal.FreeCoTaskMem(pszName);
                        Marshal.FreeCoTaskMem(pszPath);
                    }
                }
            }
            return;

            Console.WriteLine("End...");
        }

Screenshot

Points of Interest

It took me a long time to find all the information. I was not even sure each time if it was what I wanted to do. Then I would share to help others. Now, I understand how Windows APIs work.

History

  • 22nd May, 2021: Initial version