I'm myself a beginner in Windows API, I spent a lot of time trying to understand how the new API worked, lost between a lot of old tutorials and answers using deprecated API. This is why after I resolved a part of my problem, I wanted to share it with the community.
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 enum
s 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;
IShellItem spsiFolder;
int res = ShellAPI.SHGetKnownFolderItem(
new Guid(KnownFolderID.ComputerFolder),
(uint)KnownFolderFlags.None,
IntPtr.Zero,
typeof(IShellItem).GUID,
out spsiFolder);
IntPtr pName;
reslt = spsiFolder.GetDisplayName(SIGDN.NORMALDISPLAY, out pName);
if (reslt == HResult.S_OK)
{
Console.WriteLine(Marshal.PtrToStringUni(pName));
Marshal.FreeCoTaskMem(pName);
}
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;
reslt = psi.GetDisplayName(SIGDN.NORMALDISPLAY, out pszName);
reslt = psi.GetDisplayName(SIGDN.DESKTOPABSOLUTEEDITING, out pszPath);
if (reslt == HResult.S_OK)
{
string sDisplayName = Marshal.PtrToStringUni(pszName);
string sDisplayPath = Marshal.PtrToStringUni(pszPath);
Console.WriteLine(string.Format("\tItem Name : {0}", sDisplayName));
Console.WriteLine(string.Format("\tItem Path : {0}", sDisplayPath));
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