locked
Get the Font file name Path as shown in File Explorer RRS feed

  • Question

  • I hope all are doing well.

    Using: Visual Studio 2017 Windows Form C#:

    I know how to get the path of a file using the following code:

    Path.Combine(Directory.GetCurrentDirectory(), "Path to file")

    When looking for the path of a Font file it will bring back the following: C:\Windows\Fonts\Script Regular

    The path that I need to get is C:\Windows\Fonts\SCRIPT.FON as shown below.

    Any suggestions is appreciated.



    Regards

    Friday, September 25, 2020 5:49 PM

Answers

  • A test with a loop on fonts (+ another loop for "sub-fonts", like for Arial)

    Add a Button for the click

    The result is displayed in Output window

    I get this :

    Name : System Gras - Type : Raster - File Name : C:\WINDOWS\Fonts\VGASYS.FON
    Name : Terminal - Type : Raster - File Name : [See below]
         Name : Terminal Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\VGAOEM.FON
         Name : Terminal Gras - Type : Raster - File Name : C:\WINDOWS\Fonts\DOSAPP.FON
    Name : Fixedsys Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\VGAFIX.FON
    Name : Modern Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\MODERN.FON
    Name : Roman Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\ROMAN.FON
    Name : Script Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\SCRIPT.FON
    Name : Courier Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\COURE.FON
    Name : MS Serif Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\SERIFE.FON
    Name : MS Sans Serif Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\SSERIFE.FON
    Name : Small Fonts Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\SMALLE.FON
    Name : Adobe Devanagari - Type : OpenType - File Name : [See below]
         Name : Adobe Devanagari Normal - Type : OpenType - File Name : C:\PROGRAM FILES (X86)\ADOBE\ACROBAT READER DC\RESOURCE\FONT\ADOBEDEVANAGARI-REGULAR.OTF
         Name : Adobe Devanagari Gras - Type : OpenType - File Name : C:\PROGRAM FILES (X86)\ADOBE\ACROBAT READER DC\RESOURCE\FONT\ADOBEDEVANAGARI-BOLD.OTF
         Name : Adobe Devanagari Italique gras - Type : OpenType - File Name : C:\PROGRAM FILES (X86)\ADOBE\ACROBAT READER DC\RESOURCE\FONT\ADOBEDEVANAGARI-BOLDITALIC.OTF
         Name : Adobe Devanagari Italique - Type : OpenType - File Name : C:\PROGRAM FILES (X86)\ADOBE\ACROBAT READER DC\RESOURCE\FONT\ADOBEDEVANAGARI-ITALIC.OTF
    Name : SWMacro Normal - Type : OpenType - File Name : C:\WINDOWS\Fonts\SWMACRO.OTF
    Name : Avenir Noir - Type : OpenType - File Name : C:\USERS\CHRISTIAN\APPDATA\LOCAL\MICROSOFT\WINDOWS\FONTS\AVENIR-BLACK.OTF
    Name : Arial - Type : OpenType - File Name : [See below]
         Name : Arial Normal - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIAL.TTF
         Name : Arial Noir - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIBLK.TTF
         Name : Arial Semi-condensé - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALN.TTF
         Name : Arial Gras - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALBD.TTF
         Name : Arial Italique gras - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALBI.TTF
         Name : Arial Italique - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALI.TTF
         Name : Arial Semi-condensé Gras - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALNB.TTF
         Name : Arial Semi-condensé Gras Italique - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALNBI.TTF
         Name : Arial Semi-condensé Italique - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALNI.TTF

    // etc...

        public partial class Form1 : Form
        {
            public enum HRESULT : int
            {
                S_OK = 0,
                S_FALSE = 1,
                E_NOINTERFACE = unchecked((int)0x80004002),
                E_NOTIMPL = unchecked((int)0x80004001),
                E_FAIL = unchecked((int)0x80004005),
                E_UNEXPECTED = unchecked((int)0x8000FFFF),
                E_OUTOFMEMORY = unchecked((int)0x8007000E)
            }
    
            [DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern HRESULT SHGetDesktopFolder([MarshalAs(UnmanagedType.Interface)] out IShellFolder ppshf);
      
            [DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern HRESULT SHGetKnownFolderIDList(ref Guid rfid, int dwFlags, IntPtr hToken, out IntPtr pidl);
    
            [DllImport("Shlwapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern HRESULT StrRetToBuf(ref STRRET pstr, IntPtr pidl, StringBuilder pszBuf, [MarshalAs(UnmanagedType.U4)] uint cchBuf);
    
            [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            [Guid("000214E6-0000-0000-C000-000000000046")]
            public interface IShellFolder
            {
                HRESULT ParseDisplayName(IntPtr hwnd,
                    // IBindCtx pbc,
                    IntPtr pbc,
                    [MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, [In, Out] ref uint pchEaten, out IntPtr ppidl, [In, Out] ref SFGAO pdwAttributes);
                HRESULT EnumObjects(IntPtr hwnd, SHCONTF grfFlags, out IEnumIDList ppenumIDList);
                HRESULT BindToObject(IntPtr pidl,
                    //IBindCtx pbc,
                    IntPtr pbc,
                    [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT BindToStorage(IntPtr pidl, IntPtr pbc, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT CompareIDs(IntPtr lParam, IntPtr pidl1, IntPtr pidl2);
                HRESULT CreateViewObject(IntPtr hwndOwner, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT GetAttributesOf(uint cidl, IntPtr apidl, [In, Out] ref SFGAO rgfInOut);
                HRESULT GetUIObjectOf(IntPtr hwndOwner, uint cidl, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 1)] IntPtr apidl,
                    [In] ref Guid riid, [In, Out] ref uint rgfReserved, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT GetDisplayNameOf(IntPtr pidl, SHGDNF uFlags, out STRRET pName);
                HRESULT SetNameOf(IntPtr hwnd, IntPtr pidl, [MarshalAs(UnmanagedType.LPWStr)] string pszName, SHGDNF uFlags, out IntPtr ppidlOut);
            }
    
            [Flags]
            public enum SHCONTF : ushort
            {
                SHCONTF_CHECKING_FOR_CHILDREN = 0x0010,
                SHCONTF_FOLDERS = 0x0020,
                SHCONTF_NONFOLDERS = 0x0040,
                SHCONTF_INCLUDEHIDDEN = 0x0080,
                SHCONTF_INIT_ON_FIRST_NEXT = 0x0100,
                SHCONTF_NETPRINTERSRCH = 0x0200,
                SHCONTF_SHAREABLE = 0x0400,
                SHCONTF_STORAGE = 0x0800,
                SHCONTF_NAVIGATION_ENUM = 0x1000,
                SHCONTF_FASTITEMS = 0x2000,
                SHCONTF_FLATLIST = 0x4000,
                SHCONTF_ENABLE_ASYNC = 0x8000
            }
    
            [Flags]
            public enum SFGAO : uint
            {
                CANCOPY = 0x00000001,
                CANMOVE = 0x00000002,
                CANLINK = 0x00000004,
                STORAGE = 0x00000008,
                CANRENAME = 0x00000010,
                CANDELETE = 0x00000020,
                HASPROPSHEET = 0x00000040,
                DROPTARGET = 0x00000100,
                CAPABILITYMASK = 0x00000177,
                ENCRYPTED = 0x00002000,
                ISSLOW = 0x00004000,
                GHOSTED = 0x00008000,
                LINK = 0x00010000,
                SHARE = 0x00020000,
                READONLY = 0x00040000,
                HIDDEN = 0x00080000,
                DISPLAYATTRMASK = 0x000FC000,
                STREAM = 0x00400000,
                STORAGEANCESTOR = 0x00800000,
                VALIDATE = 0x01000000,
                REMOVABLE = 0x02000000,
                COMPRESSED = 0x04000000,
                BROWSABLE = 0x08000000,
                FILESYSANCESTOR = 0x10000000,
                FOLDER = 0x20000000,
                FILESYSTEM = 0x40000000,
                HASSUBFOLDER = 0x80000000,
                CONTENTSMASK = 0x80000000,
                STORAGECAPMASK = 0x70C50008,
                PKEYSFGAOMASK = 0x81044000
            }
    
            [Flags]
            public enum SHGDNF : uint
            {
                SHGDN_NORMAL = 0,
                SHGDN_INFOLDER = 0x1,
                SHGDN_FOREDITING = 0x1000,
                SHGDN_FORADDRESSBAR = 0x4000,
                SHGDN_FORPARSING = 0x8000
            }
    
            [StructLayout(LayoutKind.Explicit, Size = 264)]
            public struct STRRET
            {
                [FieldOffset(0)]
                public uint uType;
                [FieldOffset(4)]
                 public IntPtr pOleStr;
                [FieldOffset(4)]
                public uint uOffset;
                [FieldOffset(4)]
                public IntPtr cString;
            }
    
            [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            [Guid("000214F2-0000-0000-C000-000000000046")]
            public interface IEnumIDList
            {
                [PreserveSig()]
                HRESULT Next(uint celt, out IntPtr rgelt, out int pceltFetched);
                [PreserveSig()]
                HRESULT Skip(uint celt);
                void Reset();
                [return: MarshalAs(UnmanagedType.Interface)]
                IEnumIDList Clone();
            }
    
            [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            [Guid("93F2F68C-1D1B-11d3-A30E-00C04F79ABD1")]
            public interface IShellFolder2 : IShellFolder
            {
                #region IShellFolder overrides for COM/C# compatibility.
    
                [PreserveSig]
                new HRESULT ParseDisplayName(IntPtr hwnd, IntPtr pbc, [MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, [In, Out] ref uint pchEaten, out IntPtr ppidl, [In, Out] ref SFGAO pdwAttributes);
                [PreserveSig]
                new HRESULT EnumObjects(IntPtr hwnd, SHCONTF grfFlags, out IEnumIDList ppenumIDList);
                [PreserveSig]
                new HRESULT BindToObject(IntPtr pidl, IntPtr pbc, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                [PreserveSig]
                new HRESULT BindToStorage(IntPtr pidl, IntPtr pbc, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                [PreserveSig]
                new HRESULT CompareIDs(IntPtr lParam, IntPtr pidl1, IntPtr pidl2);
                [PreserveSig]
                new HRESULT CreateViewObject(IntPtr hwndOwner, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                [PreserveSig]
                new HRESULT GetAttributesOf(uint cidl, IntPtr apidl, [In, Out] ref SFGAO rgfInOut);
                [PreserveSig]
                new HRESULT GetUIObjectOf(IntPtr hwndOwner, uint cidl, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 1)] IntPtr apidl,
                    [In] ref Guid riid, [In, Out] ref uint rgfReserved, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                [PreserveSig]
                new HRESULT GetDisplayNameOf(IntPtr pidl, SHGDNF uFlags, out STRRET pName);
                [PreserveSig]
                new HRESULT SetNameOf(IntPtr hwnd, IntPtr pidl, [MarshalAs(UnmanagedType.LPWStr)] string pszName, SHGDNF uFlags, out IntPtr ppidlOut);
    
                #endregion
    
                [PreserveSig]
                HRESULT GetDefaultSearchGUID(out Guid pguid);
                [PreserveSig]
                HRESULT EnumSearches([MarshalAs(UnmanagedType.Interface)] out object ppenum);
                [PreserveSig]
                HRESULT GetDefaultColumn(uint dwRes, out uint pSort, out uint pDisplay);
                [PreserveSig]
                HRESULT GetDefaultColumnState(uint iColumn, out SHCOLSTATEF pcsFlags);
                [PreserveSig]
                HRESULT GetDetailsEx(IntPtr pidl, ref PROPERTYKEY pscid, [MarshalAs(UnmanagedType.Struct)] out object pv);
                [PreserveSig]
                HRESULT GetDetailsOf(IntPtr pidl, uint iColumn, out SHELLDETAILS psd);
                [PreserveSig]
                HRESULT MapColumnToSCID(uint iColumn, out PROPERTYKEY pscid);
            }
    
            [Flags]
            public enum SHCOLSTATEF
            {
                SHCOLSTATE_DEFAULT = 0,
                SHCOLSTATE_TYPE_STR = 0x1,
                SHCOLSTATE_TYPE_INT = 0x2,
                SHCOLSTATE_TYPE_DATE = 0x3,
                SHCOLSTATE_ONBYDEFAULT = 0x10,
                SHCOLSTATE_SLOW = 0x20,
                SHCOLSTATE_EXTENDED = 0x40,
                SHCOLSTATE_SECONDARYUI = 0x80,
                SHCOLSTATE_HIDDEN = 0x100,
                SHCOLSTATE_PREFER_VARCMP = 0x200,
                SHCOLSTATE_PREFER_FMTCMP = 0x400,
                SHCOLSTATE_NOSORTBYFOLDERNESS = 0x800,
                SHCOLSTATE_VIEWONLY = 0x10000,
                SHCOLSTATE_BATCHREAD = 0x20000,
                SHCOLSTATE_NO_GROUPBY = 0x40000,
                SHCOLSTATE_FIXED_WIDTH = 0x1000,
                SHCOLSTATE_NODPISCALE = 0x2000,
                SHCOLSTATE_FIXED_RATIO = 0x4000,
            }
    
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
            public struct SHELLDETAILS
            {
                int fmt;
                int cxChar;
                STRRET str;
            }
    
            [StructLayout(LayoutKind.Sequential, Pack = 4)]
            public struct PROPERTYKEY
            {
                private readonly Guid _fmtid;
                private readonly uint _pid;
    
                public PROPERTYKEY(Guid fmtid, uint pid)
                {
                    _fmtid = fmtid;
                    _pid = pid;
                }
    
                public static readonly PROPERTYKEY PKEY_AppUserModel_ID = new PROPERTYKEY(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 5);
                public static readonly PROPERTYKEY PKEY_Software_InstallLocation = new PROPERTYKEY(new Guid("841E4F90-FF59-4D16-8947-E81BBFFAB36D"), 9);
                public static readonly PROPERTYKEY PKEY_ItemNameDisplay = new PROPERTYKEY(new Guid("B725F130-47EF-101A-A5F1-02608C9EEBAC"), 10);
                public static readonly PROPERTYKEY PKEY_Software_InstallDate = new PROPERTYKEY(new Guid("841E4F90-FF59-4D16-8947-E81BBFFAB36D"), 11);
                public static readonly PROPERTYKEY PKEY_FileVersion = new PROPERTYKEY(new Guid("0CEF7D53-FA64-11D1-A203-0000F81FEDEE"), 4);
                public static readonly PROPERTYKEY PKEY_Fonts_Version = new PROPERTYKEY(new Guid("fec7952b-4bf0-4c03-b6e1-2796818b7ca9"), 0x00000064);
                public static readonly PROPERTYKEY PKEY_Fonts_FileNames = new PROPERTYKEY(new Guid("4530d076-b598-4a81-8813-9b11286ef6ea"), 7);
                public static readonly PROPERTYKEY PKEY_Fonts_Type = new PROPERTYKEY(new Guid("4530d076-b598-4a81-8813-9b11286ef6ea"), 5);            
            }
    
    
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                IShellFolder psfDesktop;
                HRESULT hr = SHGetDesktopFolder(out psfDesktop);
                IntPtr pidlFonts = IntPtr.Zero;
                Guid FOLDERID_Fonts = new Guid("FD228CB7-AE11-4AE3-864C-16F3910AB8FE");
                hr = SHGetKnownFolderIDList(ref FOLDERID_Fonts, 0, IntPtr.Zero, out pidlFonts);
                if (hr == HRESULT.S_OK)
                {
                    object ObjpsfFonts = null;
                    hr = psfDesktop.BindToObject(pidlFonts, IntPtr.Zero, typeof(IShellFolder).GUID, out ObjpsfFonts);
                    if (hr == HRESULT.S_OK)
                    {
                        IEnumIDList ppenum;
                        IShellFolder psfFonts = (IShellFolder)ObjpsfFonts;
                        hr = psfFonts.EnumObjects(IntPtr.Zero, SHCONTF.SHCONTF_ENABLE_ASYNC | SHCONTF.SHCONTF_FLATLIST | SHCONTF.SHCONTF_FOLDERS | SHCONTF.SHCONTF_INCLUDEHIDDEN | SHCONTF.SHCONTF_NONFOLDERS, out ppenum);
                        if (hr == HRESULT.S_OK)
                        {
                            IntPtr pidlChild = IntPtr.Zero;
                            int celtFetched = 0;
                            while ((hr = ppenum.Next(1, out pidlChild, out celtFetched)) == HRESULT.S_OK && celtFetched == 1)
                            {
                                // Name
                                STRRET strretFolderName;
                                hr = psfFonts.GetDisplayNameOf(pidlChild, SHGDNF.SHGDN_INFOLDER, out strretFolderName);
                                string sDisplayName = null;
                                //StringBuilder sbDisplayName = default;
                                StringBuilder sbDisplayName = new StringBuilder(256);
                                StrRetToBuf(ref strretFolderName, pidlChild, sbDisplayName, (uint)sbDisplayName.Capacity);
                                sDisplayName = sbDisplayName.ToString();
    
                                IShellFolder2 psf2Fonts = (IShellFolder2)psfFonts;
                                // System.Fonts.Type
                                object vVariantFontsType = null;
                                PROPERTYKEY pkFontsType = PROPERTYKEY.PKEY_Fonts_Type;
                                hr = psf2Fonts.GetDetailsEx(pidlChild, ref pkFontsType, out vVariantFontsType);
                                // System.Fonts.FileNames
                                object vVariantFontsFilenames = null;
                                PROPERTYKEY pkFontsFileNames = PROPERTYKEY.PKEY_Fonts_FileNames;
                                hr = psf2Fonts.GetDetailsEx(pidlChild, ref pkFontsFileNames, out vVariantFontsFilenames);
                                Console.WriteLine(string.Format("Name : {0} - Type : {1} - File Name : {2}", sDisplayName, vVariantFontsType, vVariantFontsFilenames == null?"[See below]":((string[])vVariantFontsFilenames)[0]));
                                // Enumerate sub-fonts
                                if (vVariantFontsFilenames == null)
                                {
                                    object ObjpsfProgramChilds = null;
                                    hr = psf2Fonts.BindToObject(pidlChild, IntPtr.Zero, typeof(IShellFolder).GUID, out ObjpsfProgramChilds);
                                    if (hr == HRESULT.S_OK)
                                    {
                                        IEnumIDList ppenumChild;
                                        IShellFolder psfFontsChild = (IShellFolder)ObjpsfProgramChilds;
                                        hr = psfFontsChild.EnumObjects(IntPtr.Zero, SHCONTF.SHCONTF_ENABLE_ASYNC | SHCONTF.SHCONTF_FLATLIST | SHCONTF.SHCONTF_FOLDERS | SHCONTF.SHCONTF_INCLUDEHIDDEN | SHCONTF.SHCONTF_NONFOLDERS, out ppenumChild);
                                        if (hr == HRESULT.S_OK)
                                        {
                                            IntPtr pidlChild2 = IntPtr.Zero;
                                            int celtFetched2 = 0;
                                            while ((hr = ppenumChild.Next(1, out pidlChild2, out celtFetched2)) == HRESULT.S_OK && celtFetched2 == 1)
                                            {   
                                                // Name
                                                hr = psfFontsChild.GetDisplayNameOf(pidlChild2, SHGDNF.SHGDN_INFOLDER, out strretFolderName);
                                                sDisplayName = null;                                            
                                                StringBuilder sbDisplayName2 = new StringBuilder(256);
                                                StrRetToBuf(ref strretFolderName, pidlChild, sbDisplayName2, (uint)sbDisplayName2.Capacity);
                                                sDisplayName = sbDisplayName2.ToString();
    
                                                // System.Fonts.FileNames
                                                IShellFolder2 psf2FontsChild = (IShellFolder2)psfFontsChild;
                                                hr = psf2FontsChild.GetDetailsEx(pidlChild2, ref pkFontsFileNames, out vVariantFontsFilenames);
                                                Console.WriteLine(string.Format("\tName : {0} - Type : {1} - File Name : {2}", sDisplayName, vVariantFontsType, vVariantFontsFilenames == null ? "" : ((string[])vVariantFontsFilenames)[0]));
                                            }
                                            Marshal.ReleaseComObject(ppenumChild);
                                        }
                                        Marshal.ReleaseComObject(psfFontsChild);
                                    }
                                }
                            }
                            Marshal.ReleaseComObject(ppenum);
                        }
                        Marshal.ReleaseComObject(psfFonts);
                    }
                }
                Marshal.ReleaseComObject(psfDesktop);
            }
        }



    • Edited by Castorix31 Sunday, September 27, 2020 12:26 PM
    • Marked as answer by Jo Srm Sunday, September 27, 2020 2:21 PM
    Sunday, September 27, 2020 12:22 PM

All replies

  • The C:\Windows\Fonts folder is a virtual folder in Windows Explorer. What you see there is a combination of installed fonts and fonts that are stored elsewhere (used to be WinSxS). When looking at it from the command prompt you'll see the base files that were put there but not necessarily all of them. I've never gone to look to see how it works. So the path may not be Windows\Fonts.

    Not really sure why you'd ever need this. How are you getting the "fonts" now such that you then want to get the file path?


    Michael Taylor http://www.michaeltaylorp3.net

    Friday, September 25, 2020 6:03 PM
  • The path that I need to get is C:\Windows\Fonts\SCRIPT.FON as shown below.



    You can get it with the Shell (IShellFolder2) and PKEY_Fonts_FileNames

    (tested on Windows 10)

    Saturday, September 26, 2020 9:22 AM
  • The path that I need to get is C:\Windows\Fonts\SCRIPT.FON as shown below.



    You can get it with the Shell (IShellFolder2) and PKEY_Fonts_FileNames

    (tested on Windows 10)

    Castorix31,

    Could you please provide an example?



    Regards

    Sunday, September 27, 2020 12:00 PM
  • A test with a loop on fonts (+ another loop for "sub-fonts", like for Arial)

    Add a Button for the click

    The result is displayed in Output window

    I get this :

    Name : System Gras - Type : Raster - File Name : C:\WINDOWS\Fonts\VGASYS.FON
    Name : Terminal - Type : Raster - File Name : [See below]
         Name : Terminal Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\VGAOEM.FON
         Name : Terminal Gras - Type : Raster - File Name : C:\WINDOWS\Fonts\DOSAPP.FON
    Name : Fixedsys Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\VGAFIX.FON
    Name : Modern Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\MODERN.FON
    Name : Roman Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\ROMAN.FON
    Name : Script Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\SCRIPT.FON
    Name : Courier Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\COURE.FON
    Name : MS Serif Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\SERIFE.FON
    Name : MS Sans Serif Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\SSERIFE.FON
    Name : Small Fonts Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\SMALLE.FON
    Name : Adobe Devanagari - Type : OpenType - File Name : [See below]
         Name : Adobe Devanagari Normal - Type : OpenType - File Name : C:\PROGRAM FILES (X86)\ADOBE\ACROBAT READER DC\RESOURCE\FONT\ADOBEDEVANAGARI-REGULAR.OTF
         Name : Adobe Devanagari Gras - Type : OpenType - File Name : C:\PROGRAM FILES (X86)\ADOBE\ACROBAT READER DC\RESOURCE\FONT\ADOBEDEVANAGARI-BOLD.OTF
         Name : Adobe Devanagari Italique gras - Type : OpenType - File Name : C:\PROGRAM FILES (X86)\ADOBE\ACROBAT READER DC\RESOURCE\FONT\ADOBEDEVANAGARI-BOLDITALIC.OTF
         Name : Adobe Devanagari Italique - Type : OpenType - File Name : C:\PROGRAM FILES (X86)\ADOBE\ACROBAT READER DC\RESOURCE\FONT\ADOBEDEVANAGARI-ITALIC.OTF
    Name : SWMacro Normal - Type : OpenType - File Name : C:\WINDOWS\Fonts\SWMACRO.OTF
    Name : Avenir Noir - Type : OpenType - File Name : C:\USERS\CHRISTIAN\APPDATA\LOCAL\MICROSOFT\WINDOWS\FONTS\AVENIR-BLACK.OTF
    Name : Arial - Type : OpenType - File Name : [See below]
         Name : Arial Normal - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIAL.TTF
         Name : Arial Noir - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIBLK.TTF
         Name : Arial Semi-condensé - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALN.TTF
         Name : Arial Gras - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALBD.TTF
         Name : Arial Italique gras - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALBI.TTF
         Name : Arial Italique - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALI.TTF
         Name : Arial Semi-condensé Gras - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALNB.TTF
         Name : Arial Semi-condensé Gras Italique - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALNBI.TTF
         Name : Arial Semi-condensé Italique - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALNI.TTF

    // etc...

        public partial class Form1 : Form
        {
            public enum HRESULT : int
            {
                S_OK = 0,
                S_FALSE = 1,
                E_NOINTERFACE = unchecked((int)0x80004002),
                E_NOTIMPL = unchecked((int)0x80004001),
                E_FAIL = unchecked((int)0x80004005),
                E_UNEXPECTED = unchecked((int)0x8000FFFF),
                E_OUTOFMEMORY = unchecked((int)0x8007000E)
            }
    
            [DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern HRESULT SHGetDesktopFolder([MarshalAs(UnmanagedType.Interface)] out IShellFolder ppshf);
      
            [DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern HRESULT SHGetKnownFolderIDList(ref Guid rfid, int dwFlags, IntPtr hToken, out IntPtr pidl);
    
            [DllImport("Shlwapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern HRESULT StrRetToBuf(ref STRRET pstr, IntPtr pidl, StringBuilder pszBuf, [MarshalAs(UnmanagedType.U4)] uint cchBuf);
    
            [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            [Guid("000214E6-0000-0000-C000-000000000046")]
            public interface IShellFolder
            {
                HRESULT ParseDisplayName(IntPtr hwnd,
                    // IBindCtx pbc,
                    IntPtr pbc,
                    [MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, [In, Out] ref uint pchEaten, out IntPtr ppidl, [In, Out] ref SFGAO pdwAttributes);
                HRESULT EnumObjects(IntPtr hwnd, SHCONTF grfFlags, out IEnumIDList ppenumIDList);
                HRESULT BindToObject(IntPtr pidl,
                    //IBindCtx pbc,
                    IntPtr pbc,
                    [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT BindToStorage(IntPtr pidl, IntPtr pbc, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT CompareIDs(IntPtr lParam, IntPtr pidl1, IntPtr pidl2);
                HRESULT CreateViewObject(IntPtr hwndOwner, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT GetAttributesOf(uint cidl, IntPtr apidl, [In, Out] ref SFGAO rgfInOut);
                HRESULT GetUIObjectOf(IntPtr hwndOwner, uint cidl, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 1)] IntPtr apidl,
                    [In] ref Guid riid, [In, Out] ref uint rgfReserved, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT GetDisplayNameOf(IntPtr pidl, SHGDNF uFlags, out STRRET pName);
                HRESULT SetNameOf(IntPtr hwnd, IntPtr pidl, [MarshalAs(UnmanagedType.LPWStr)] string pszName, SHGDNF uFlags, out IntPtr ppidlOut);
            }
    
            [Flags]
            public enum SHCONTF : ushort
            {
                SHCONTF_CHECKING_FOR_CHILDREN = 0x0010,
                SHCONTF_FOLDERS = 0x0020,
                SHCONTF_NONFOLDERS = 0x0040,
                SHCONTF_INCLUDEHIDDEN = 0x0080,
                SHCONTF_INIT_ON_FIRST_NEXT = 0x0100,
                SHCONTF_NETPRINTERSRCH = 0x0200,
                SHCONTF_SHAREABLE = 0x0400,
                SHCONTF_STORAGE = 0x0800,
                SHCONTF_NAVIGATION_ENUM = 0x1000,
                SHCONTF_FASTITEMS = 0x2000,
                SHCONTF_FLATLIST = 0x4000,
                SHCONTF_ENABLE_ASYNC = 0x8000
            }
    
            [Flags]
            public enum SFGAO : uint
            {
                CANCOPY = 0x00000001,
                CANMOVE = 0x00000002,
                CANLINK = 0x00000004,
                STORAGE = 0x00000008,
                CANRENAME = 0x00000010,
                CANDELETE = 0x00000020,
                HASPROPSHEET = 0x00000040,
                DROPTARGET = 0x00000100,
                CAPABILITYMASK = 0x00000177,
                ENCRYPTED = 0x00002000,
                ISSLOW = 0x00004000,
                GHOSTED = 0x00008000,
                LINK = 0x00010000,
                SHARE = 0x00020000,
                READONLY = 0x00040000,
                HIDDEN = 0x00080000,
                DISPLAYATTRMASK = 0x000FC000,
                STREAM = 0x00400000,
                STORAGEANCESTOR = 0x00800000,
                VALIDATE = 0x01000000,
                REMOVABLE = 0x02000000,
                COMPRESSED = 0x04000000,
                BROWSABLE = 0x08000000,
                FILESYSANCESTOR = 0x10000000,
                FOLDER = 0x20000000,
                FILESYSTEM = 0x40000000,
                HASSUBFOLDER = 0x80000000,
                CONTENTSMASK = 0x80000000,
                STORAGECAPMASK = 0x70C50008,
                PKEYSFGAOMASK = 0x81044000
            }
    
            [Flags]
            public enum SHGDNF : uint
            {
                SHGDN_NORMAL = 0,
                SHGDN_INFOLDER = 0x1,
                SHGDN_FOREDITING = 0x1000,
                SHGDN_FORADDRESSBAR = 0x4000,
                SHGDN_FORPARSING = 0x8000
            }
    
            [StructLayout(LayoutKind.Explicit, Size = 264)]
            public struct STRRET
            {
                [FieldOffset(0)]
                public uint uType;
                [FieldOffset(4)]
                 public IntPtr pOleStr;
                [FieldOffset(4)]
                public uint uOffset;
                [FieldOffset(4)]
                public IntPtr cString;
            }
    
            [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            [Guid("000214F2-0000-0000-C000-000000000046")]
            public interface IEnumIDList
            {
                [PreserveSig()]
                HRESULT Next(uint celt, out IntPtr rgelt, out int pceltFetched);
                [PreserveSig()]
                HRESULT Skip(uint celt);
                void Reset();
                [return: MarshalAs(UnmanagedType.Interface)]
                IEnumIDList Clone();
            }
    
            [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            [Guid("93F2F68C-1D1B-11d3-A30E-00C04F79ABD1")]
            public interface IShellFolder2 : IShellFolder
            {
                #region IShellFolder overrides for COM/C# compatibility.
    
                [PreserveSig]
                new HRESULT ParseDisplayName(IntPtr hwnd, IntPtr pbc, [MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, [In, Out] ref uint pchEaten, out IntPtr ppidl, [In, Out] ref SFGAO pdwAttributes);
                [PreserveSig]
                new HRESULT EnumObjects(IntPtr hwnd, SHCONTF grfFlags, out IEnumIDList ppenumIDList);
                [PreserveSig]
                new HRESULT BindToObject(IntPtr pidl, IntPtr pbc, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                [PreserveSig]
                new HRESULT BindToStorage(IntPtr pidl, IntPtr pbc, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                [PreserveSig]
                new HRESULT CompareIDs(IntPtr lParam, IntPtr pidl1, IntPtr pidl2);
                [PreserveSig]
                new HRESULT CreateViewObject(IntPtr hwndOwner, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                [PreserveSig]
                new HRESULT GetAttributesOf(uint cidl, IntPtr apidl, [In, Out] ref SFGAO rgfInOut);
                [PreserveSig]
                new HRESULT GetUIObjectOf(IntPtr hwndOwner, uint cidl, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 1)] IntPtr apidl,
                    [In] ref Guid riid, [In, Out] ref uint rgfReserved, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                [PreserveSig]
                new HRESULT GetDisplayNameOf(IntPtr pidl, SHGDNF uFlags, out STRRET pName);
                [PreserveSig]
                new HRESULT SetNameOf(IntPtr hwnd, IntPtr pidl, [MarshalAs(UnmanagedType.LPWStr)] string pszName, SHGDNF uFlags, out IntPtr ppidlOut);
    
                #endregion
    
                [PreserveSig]
                HRESULT GetDefaultSearchGUID(out Guid pguid);
                [PreserveSig]
                HRESULT EnumSearches([MarshalAs(UnmanagedType.Interface)] out object ppenum);
                [PreserveSig]
                HRESULT GetDefaultColumn(uint dwRes, out uint pSort, out uint pDisplay);
                [PreserveSig]
                HRESULT GetDefaultColumnState(uint iColumn, out SHCOLSTATEF pcsFlags);
                [PreserveSig]
                HRESULT GetDetailsEx(IntPtr pidl, ref PROPERTYKEY pscid, [MarshalAs(UnmanagedType.Struct)] out object pv);
                [PreserveSig]
                HRESULT GetDetailsOf(IntPtr pidl, uint iColumn, out SHELLDETAILS psd);
                [PreserveSig]
                HRESULT MapColumnToSCID(uint iColumn, out PROPERTYKEY pscid);
            }
    
            [Flags]
            public enum SHCOLSTATEF
            {
                SHCOLSTATE_DEFAULT = 0,
                SHCOLSTATE_TYPE_STR = 0x1,
                SHCOLSTATE_TYPE_INT = 0x2,
                SHCOLSTATE_TYPE_DATE = 0x3,
                SHCOLSTATE_ONBYDEFAULT = 0x10,
                SHCOLSTATE_SLOW = 0x20,
                SHCOLSTATE_EXTENDED = 0x40,
                SHCOLSTATE_SECONDARYUI = 0x80,
                SHCOLSTATE_HIDDEN = 0x100,
                SHCOLSTATE_PREFER_VARCMP = 0x200,
                SHCOLSTATE_PREFER_FMTCMP = 0x400,
                SHCOLSTATE_NOSORTBYFOLDERNESS = 0x800,
                SHCOLSTATE_VIEWONLY = 0x10000,
                SHCOLSTATE_BATCHREAD = 0x20000,
                SHCOLSTATE_NO_GROUPBY = 0x40000,
                SHCOLSTATE_FIXED_WIDTH = 0x1000,
                SHCOLSTATE_NODPISCALE = 0x2000,
                SHCOLSTATE_FIXED_RATIO = 0x4000,
            }
    
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
            public struct SHELLDETAILS
            {
                int fmt;
                int cxChar;
                STRRET str;
            }
    
            [StructLayout(LayoutKind.Sequential, Pack = 4)]
            public struct PROPERTYKEY
            {
                private readonly Guid _fmtid;
                private readonly uint _pid;
    
                public PROPERTYKEY(Guid fmtid, uint pid)
                {
                    _fmtid = fmtid;
                    _pid = pid;
                }
    
                public static readonly PROPERTYKEY PKEY_AppUserModel_ID = new PROPERTYKEY(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 5);
                public static readonly PROPERTYKEY PKEY_Software_InstallLocation = new PROPERTYKEY(new Guid("841E4F90-FF59-4D16-8947-E81BBFFAB36D"), 9);
                public static readonly PROPERTYKEY PKEY_ItemNameDisplay = new PROPERTYKEY(new Guid("B725F130-47EF-101A-A5F1-02608C9EEBAC"), 10);
                public static readonly PROPERTYKEY PKEY_Software_InstallDate = new PROPERTYKEY(new Guid("841E4F90-FF59-4D16-8947-E81BBFFAB36D"), 11);
                public static readonly PROPERTYKEY PKEY_FileVersion = new PROPERTYKEY(new Guid("0CEF7D53-FA64-11D1-A203-0000F81FEDEE"), 4);
                public static readonly PROPERTYKEY PKEY_Fonts_Version = new PROPERTYKEY(new Guid("fec7952b-4bf0-4c03-b6e1-2796818b7ca9"), 0x00000064);
                public static readonly PROPERTYKEY PKEY_Fonts_FileNames = new PROPERTYKEY(new Guid("4530d076-b598-4a81-8813-9b11286ef6ea"), 7);
                public static readonly PROPERTYKEY PKEY_Fonts_Type = new PROPERTYKEY(new Guid("4530d076-b598-4a81-8813-9b11286ef6ea"), 5);            
            }
    
    
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                IShellFolder psfDesktop;
                HRESULT hr = SHGetDesktopFolder(out psfDesktop);
                IntPtr pidlFonts = IntPtr.Zero;
                Guid FOLDERID_Fonts = new Guid("FD228CB7-AE11-4AE3-864C-16F3910AB8FE");
                hr = SHGetKnownFolderIDList(ref FOLDERID_Fonts, 0, IntPtr.Zero, out pidlFonts);
                if (hr == HRESULT.S_OK)
                {
                    object ObjpsfFonts = null;
                    hr = psfDesktop.BindToObject(pidlFonts, IntPtr.Zero, typeof(IShellFolder).GUID, out ObjpsfFonts);
                    if (hr == HRESULT.S_OK)
                    {
                        IEnumIDList ppenum;
                        IShellFolder psfFonts = (IShellFolder)ObjpsfFonts;
                        hr = psfFonts.EnumObjects(IntPtr.Zero, SHCONTF.SHCONTF_ENABLE_ASYNC | SHCONTF.SHCONTF_FLATLIST | SHCONTF.SHCONTF_FOLDERS | SHCONTF.SHCONTF_INCLUDEHIDDEN | SHCONTF.SHCONTF_NONFOLDERS, out ppenum);
                        if (hr == HRESULT.S_OK)
                        {
                            IntPtr pidlChild = IntPtr.Zero;
                            int celtFetched = 0;
                            while ((hr = ppenum.Next(1, out pidlChild, out celtFetched)) == HRESULT.S_OK && celtFetched == 1)
                            {
                                // Name
                                STRRET strretFolderName;
                                hr = psfFonts.GetDisplayNameOf(pidlChild, SHGDNF.SHGDN_INFOLDER, out strretFolderName);
                                string sDisplayName = null;
                                //StringBuilder sbDisplayName = default;
                                StringBuilder sbDisplayName = new StringBuilder(256);
                                StrRetToBuf(ref strretFolderName, pidlChild, sbDisplayName, (uint)sbDisplayName.Capacity);
                                sDisplayName = sbDisplayName.ToString();
    
                                IShellFolder2 psf2Fonts = (IShellFolder2)psfFonts;
                                // System.Fonts.Type
                                object vVariantFontsType = null;
                                PROPERTYKEY pkFontsType = PROPERTYKEY.PKEY_Fonts_Type;
                                hr = psf2Fonts.GetDetailsEx(pidlChild, ref pkFontsType, out vVariantFontsType);
                                // System.Fonts.FileNames
                                object vVariantFontsFilenames = null;
                                PROPERTYKEY pkFontsFileNames = PROPERTYKEY.PKEY_Fonts_FileNames;
                                hr = psf2Fonts.GetDetailsEx(pidlChild, ref pkFontsFileNames, out vVariantFontsFilenames);
                                Console.WriteLine(string.Format("Name : {0} - Type : {1} - File Name : {2}", sDisplayName, vVariantFontsType, vVariantFontsFilenames == null?"[See below]":((string[])vVariantFontsFilenames)[0]));
                                // Enumerate sub-fonts
                                if (vVariantFontsFilenames == null)
                                {
                                    object ObjpsfProgramChilds = null;
                                    hr = psf2Fonts.BindToObject(pidlChild, IntPtr.Zero, typeof(IShellFolder).GUID, out ObjpsfProgramChilds);
                                    if (hr == HRESULT.S_OK)
                                    {
                                        IEnumIDList ppenumChild;
                                        IShellFolder psfFontsChild = (IShellFolder)ObjpsfProgramChilds;
                                        hr = psfFontsChild.EnumObjects(IntPtr.Zero, SHCONTF.SHCONTF_ENABLE_ASYNC | SHCONTF.SHCONTF_FLATLIST | SHCONTF.SHCONTF_FOLDERS | SHCONTF.SHCONTF_INCLUDEHIDDEN | SHCONTF.SHCONTF_NONFOLDERS, out ppenumChild);
                                        if (hr == HRESULT.S_OK)
                                        {
                                            IntPtr pidlChild2 = IntPtr.Zero;
                                            int celtFetched2 = 0;
                                            while ((hr = ppenumChild.Next(1, out pidlChild2, out celtFetched2)) == HRESULT.S_OK && celtFetched2 == 1)
                                            {   
                                                // Name
                                                hr = psfFontsChild.GetDisplayNameOf(pidlChild2, SHGDNF.SHGDN_INFOLDER, out strretFolderName);
                                                sDisplayName = null;                                            
                                                StringBuilder sbDisplayName2 = new StringBuilder(256);
                                                StrRetToBuf(ref strretFolderName, pidlChild, sbDisplayName2, (uint)sbDisplayName2.Capacity);
                                                sDisplayName = sbDisplayName2.ToString();
    
                                                // System.Fonts.FileNames
                                                IShellFolder2 psf2FontsChild = (IShellFolder2)psfFontsChild;
                                                hr = psf2FontsChild.GetDetailsEx(pidlChild2, ref pkFontsFileNames, out vVariantFontsFilenames);
                                                Console.WriteLine(string.Format("\tName : {0} - Type : {1} - File Name : {2}", sDisplayName, vVariantFontsType, vVariantFontsFilenames == null ? "" : ((string[])vVariantFontsFilenames)[0]));
                                            }
                                            Marshal.ReleaseComObject(ppenumChild);
                                        }
                                        Marshal.ReleaseComObject(psfFontsChild);
                                    }
                                }
                            }
                            Marshal.ReleaseComObject(ppenum);
                        }
                        Marshal.ReleaseComObject(psfFonts);
                    }
                }
                Marshal.ReleaseComObject(psfDesktop);
            }
        }



    • Edited by Castorix31 Sunday, September 27, 2020 12:26 PM
    • Marked as answer by Jo Srm Sunday, September 27, 2020 2:21 PM
    Sunday, September 27, 2020 12:22 PM
  • A test with a loop on fonts (+ another loop for "sub-fonts", like for Arial)

    Add a Button for the click

    The result is displayed in Output window

    I get this :

    Name : System Gras - Type : Raster - File Name : C:\WINDOWS\Fonts\VGASYS.FON
    Name : Terminal - Type : Raster - File Name : [See below]
         Name : Terminal Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\VGAOEM.FON
         Name : Terminal Gras - Type : Raster - File Name : C:\WINDOWS\Fonts\DOSAPP.FON
    Name : Fixedsys Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\VGAFIX.FON
    Name : Modern Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\MODERN.FON
    Name : Roman Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\ROMAN.FON
    Name : Script Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\SCRIPT.FON
    Name : Courier Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\COURE.FON
    Name : MS Serif Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\SERIFE.FON
    Name : MS Sans Serif Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\SSERIFE.FON
    Name : Small Fonts Normal - Type : Raster - File Name : C:\WINDOWS\Fonts\SMALLE.FON
    Name : Adobe Devanagari - Type : OpenType - File Name : [See below]
         Name : Adobe Devanagari Normal - Type : OpenType - File Name : C:\PROGRAM FILES (X86)\ADOBE\ACROBAT READER DC\RESOURCE\FONT\ADOBEDEVANAGARI-REGULAR.OTF
         Name : Adobe Devanagari Gras - Type : OpenType - File Name : C:\PROGRAM FILES (X86)\ADOBE\ACROBAT READER DC\RESOURCE\FONT\ADOBEDEVANAGARI-BOLD.OTF
         Name : Adobe Devanagari Italique gras - Type : OpenType - File Name : C:\PROGRAM FILES (X86)\ADOBE\ACROBAT READER DC\RESOURCE\FONT\ADOBEDEVANAGARI-BOLDITALIC.OTF
         Name : Adobe Devanagari Italique - Type : OpenType - File Name : C:\PROGRAM FILES (X86)\ADOBE\ACROBAT READER DC\RESOURCE\FONT\ADOBEDEVANAGARI-ITALIC.OTF
    Name : SWMacro Normal - Type : OpenType - File Name : C:\WINDOWS\Fonts\SWMACRO.OTF
    Name : Avenir Noir - Type : OpenType - File Name : C:\USERS\CHRISTIAN\APPDATA\LOCAL\MICROSOFT\WINDOWS\FONTS\AVENIR-BLACK.OTF
    Name : Arial - Type : OpenType - File Name : [See below]
         Name : Arial Normal - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIAL.TTF
         Name : Arial Noir - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIBLK.TTF
         Name : Arial Semi-condensé - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALN.TTF
         Name : Arial Gras - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALBD.TTF
         Name : Arial Italique gras - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALBI.TTF
         Name : Arial Italique - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALI.TTF
         Name : Arial Semi-condensé Gras - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALNB.TTF
         Name : Arial Semi-condensé Gras Italique - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALNBI.TTF
         Name : Arial Semi-condensé Italique - Type : OpenType - File Name : C:\WINDOWS\Fonts\ARIALNI.TTF

    // etc...

        public partial class Form1 : Form
        {
            public enum HRESULT : int
            {
                S_OK = 0,
                S_FALSE = 1,
                E_NOINTERFACE = unchecked((int)0x80004002),
                E_NOTIMPL = unchecked((int)0x80004001),
                E_FAIL = unchecked((int)0x80004005),
                E_UNEXPECTED = unchecked((int)0x8000FFFF),
                E_OUTOFMEMORY = unchecked((int)0x8007000E)
            }
    
            [DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern HRESULT SHGetDesktopFolder([MarshalAs(UnmanagedType.Interface)] out IShellFolder ppshf);
      
            [DllImport("Shell32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern HRESULT SHGetKnownFolderIDList(ref Guid rfid, int dwFlags, IntPtr hToken, out IntPtr pidl);
    
            [DllImport("Shlwapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern HRESULT StrRetToBuf(ref STRRET pstr, IntPtr pidl, StringBuilder pszBuf, [MarshalAs(UnmanagedType.U4)] uint cchBuf);
    
            [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            [Guid("000214E6-0000-0000-C000-000000000046")]
            public interface IShellFolder
            {
                HRESULT ParseDisplayName(IntPtr hwnd,
                    // IBindCtx pbc,
                    IntPtr pbc,
                    [MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, [In, Out] ref uint pchEaten, out IntPtr ppidl, [In, Out] ref SFGAO pdwAttributes);
                HRESULT EnumObjects(IntPtr hwnd, SHCONTF grfFlags, out IEnumIDList ppenumIDList);
                HRESULT BindToObject(IntPtr pidl,
                    //IBindCtx pbc,
                    IntPtr pbc,
                    [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT BindToStorage(IntPtr pidl, IntPtr pbc, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT CompareIDs(IntPtr lParam, IntPtr pidl1, IntPtr pidl2);
                HRESULT CreateViewObject(IntPtr hwndOwner, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT GetAttributesOf(uint cidl, IntPtr apidl, [In, Out] ref SFGAO rgfInOut);
                HRESULT GetUIObjectOf(IntPtr hwndOwner, uint cidl, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 1)] IntPtr apidl,
                    [In] ref Guid riid, [In, Out] ref uint rgfReserved, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                HRESULT GetDisplayNameOf(IntPtr pidl, SHGDNF uFlags, out STRRET pName);
                HRESULT SetNameOf(IntPtr hwnd, IntPtr pidl, [MarshalAs(UnmanagedType.LPWStr)] string pszName, SHGDNF uFlags, out IntPtr ppidlOut);
            }
    
            [Flags]
            public enum SHCONTF : ushort
            {
                SHCONTF_CHECKING_FOR_CHILDREN = 0x0010,
                SHCONTF_FOLDERS = 0x0020,
                SHCONTF_NONFOLDERS = 0x0040,
                SHCONTF_INCLUDEHIDDEN = 0x0080,
                SHCONTF_INIT_ON_FIRST_NEXT = 0x0100,
                SHCONTF_NETPRINTERSRCH = 0x0200,
                SHCONTF_SHAREABLE = 0x0400,
                SHCONTF_STORAGE = 0x0800,
                SHCONTF_NAVIGATION_ENUM = 0x1000,
                SHCONTF_FASTITEMS = 0x2000,
                SHCONTF_FLATLIST = 0x4000,
                SHCONTF_ENABLE_ASYNC = 0x8000
            }
    
            [Flags]
            public enum SFGAO : uint
            {
                CANCOPY = 0x00000001,
                CANMOVE = 0x00000002,
                CANLINK = 0x00000004,
                STORAGE = 0x00000008,
                CANRENAME = 0x00000010,
                CANDELETE = 0x00000020,
                HASPROPSHEET = 0x00000040,
                DROPTARGET = 0x00000100,
                CAPABILITYMASK = 0x00000177,
                ENCRYPTED = 0x00002000,
                ISSLOW = 0x00004000,
                GHOSTED = 0x00008000,
                LINK = 0x00010000,
                SHARE = 0x00020000,
                READONLY = 0x00040000,
                HIDDEN = 0x00080000,
                DISPLAYATTRMASK = 0x000FC000,
                STREAM = 0x00400000,
                STORAGEANCESTOR = 0x00800000,
                VALIDATE = 0x01000000,
                REMOVABLE = 0x02000000,
                COMPRESSED = 0x04000000,
                BROWSABLE = 0x08000000,
                FILESYSANCESTOR = 0x10000000,
                FOLDER = 0x20000000,
                FILESYSTEM = 0x40000000,
                HASSUBFOLDER = 0x80000000,
                CONTENTSMASK = 0x80000000,
                STORAGECAPMASK = 0x70C50008,
                PKEYSFGAOMASK = 0x81044000
            }
    
            [Flags]
            public enum SHGDNF : uint
            {
                SHGDN_NORMAL = 0,
                SHGDN_INFOLDER = 0x1,
                SHGDN_FOREDITING = 0x1000,
                SHGDN_FORADDRESSBAR = 0x4000,
                SHGDN_FORPARSING = 0x8000
            }
    
            [StructLayout(LayoutKind.Explicit, Size = 264)]
            public struct STRRET
            {
                [FieldOffset(0)]
                public uint uType;
                [FieldOffset(4)]
                 public IntPtr pOleStr;
                [FieldOffset(4)]
                public uint uOffset;
                [FieldOffset(4)]
                public IntPtr cString;
            }
    
            [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            [Guid("000214F2-0000-0000-C000-000000000046")]
            public interface IEnumIDList
            {
                [PreserveSig()]
                HRESULT Next(uint celt, out IntPtr rgelt, out int pceltFetched);
                [PreserveSig()]
                HRESULT Skip(uint celt);
                void Reset();
                [return: MarshalAs(UnmanagedType.Interface)]
                IEnumIDList Clone();
            }
    
            [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
            [Guid("93F2F68C-1D1B-11d3-A30E-00C04F79ABD1")]
            public interface IShellFolder2 : IShellFolder
            {
                #region IShellFolder overrides for COM/C# compatibility.
    
                [PreserveSig]
                new HRESULT ParseDisplayName(IntPtr hwnd, IntPtr pbc, [MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, [In, Out] ref uint pchEaten, out IntPtr ppidl, [In, Out] ref SFGAO pdwAttributes);
                [PreserveSig]
                new HRESULT EnumObjects(IntPtr hwnd, SHCONTF grfFlags, out IEnumIDList ppenumIDList);
                [PreserveSig]
                new HRESULT BindToObject(IntPtr pidl, IntPtr pbc, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                [PreserveSig]
                new HRESULT BindToStorage(IntPtr pidl, IntPtr pbc, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                [PreserveSig]
                new HRESULT CompareIDs(IntPtr lParam, IntPtr pidl1, IntPtr pidl2);
                [PreserveSig]
                new HRESULT CreateViewObject(IntPtr hwndOwner, [In] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                [PreserveSig]
                new HRESULT GetAttributesOf(uint cidl, IntPtr apidl, [In, Out] ref SFGAO rgfInOut);
                [PreserveSig]
                new HRESULT GetUIObjectOf(IntPtr hwndOwner, uint cidl, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysInt, SizeParamIndex = 1)] IntPtr apidl,
                    [In] ref Guid riid, [In, Out] ref uint rgfReserved, [MarshalAs(UnmanagedType.Interface)] out object ppv);
                [PreserveSig]
                new HRESULT GetDisplayNameOf(IntPtr pidl, SHGDNF uFlags, out STRRET pName);
                [PreserveSig]
                new HRESULT SetNameOf(IntPtr hwnd, IntPtr pidl, [MarshalAs(UnmanagedType.LPWStr)] string pszName, SHGDNF uFlags, out IntPtr ppidlOut);
    
                #endregion
    
                [PreserveSig]
                HRESULT GetDefaultSearchGUID(out Guid pguid);
                [PreserveSig]
                HRESULT EnumSearches([MarshalAs(UnmanagedType.Interface)] out object ppenum);
                [PreserveSig]
                HRESULT GetDefaultColumn(uint dwRes, out uint pSort, out uint pDisplay);
                [PreserveSig]
                HRESULT GetDefaultColumnState(uint iColumn, out SHCOLSTATEF pcsFlags);
                [PreserveSig]
                HRESULT GetDetailsEx(IntPtr pidl, ref PROPERTYKEY pscid, [MarshalAs(UnmanagedType.Struct)] out object pv);
                [PreserveSig]
                HRESULT GetDetailsOf(IntPtr pidl, uint iColumn, out SHELLDETAILS psd);
                [PreserveSig]
                HRESULT MapColumnToSCID(uint iColumn, out PROPERTYKEY pscid);
            }
    
            [Flags]
            public enum SHCOLSTATEF
            {
                SHCOLSTATE_DEFAULT = 0,
                SHCOLSTATE_TYPE_STR = 0x1,
                SHCOLSTATE_TYPE_INT = 0x2,
                SHCOLSTATE_TYPE_DATE = 0x3,
                SHCOLSTATE_ONBYDEFAULT = 0x10,
                SHCOLSTATE_SLOW = 0x20,
                SHCOLSTATE_EXTENDED = 0x40,
                SHCOLSTATE_SECONDARYUI = 0x80,
                SHCOLSTATE_HIDDEN = 0x100,
                SHCOLSTATE_PREFER_VARCMP = 0x200,
                SHCOLSTATE_PREFER_FMTCMP = 0x400,
                SHCOLSTATE_NOSORTBYFOLDERNESS = 0x800,
                SHCOLSTATE_VIEWONLY = 0x10000,
                SHCOLSTATE_BATCHREAD = 0x20000,
                SHCOLSTATE_NO_GROUPBY = 0x40000,
                SHCOLSTATE_FIXED_WIDTH = 0x1000,
                SHCOLSTATE_NODPISCALE = 0x2000,
                SHCOLSTATE_FIXED_RATIO = 0x4000,
            }
    
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
            public struct SHELLDETAILS
            {
                int fmt;
                int cxChar;
                STRRET str;
            }
    
            [StructLayout(LayoutKind.Sequential, Pack = 4)]
            public struct PROPERTYKEY
            {
                private readonly Guid _fmtid;
                private readonly uint _pid;
    
                public PROPERTYKEY(Guid fmtid, uint pid)
                {
                    _fmtid = fmtid;
                    _pid = pid;
                }
    
                public static readonly PROPERTYKEY PKEY_AppUserModel_ID = new PROPERTYKEY(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 5);
                public static readonly PROPERTYKEY PKEY_Software_InstallLocation = new PROPERTYKEY(new Guid("841E4F90-FF59-4D16-8947-E81BBFFAB36D"), 9);
                public static readonly PROPERTYKEY PKEY_ItemNameDisplay = new PROPERTYKEY(new Guid("B725F130-47EF-101A-A5F1-02608C9EEBAC"), 10);
                public static readonly PROPERTYKEY PKEY_Software_InstallDate = new PROPERTYKEY(new Guid("841E4F90-FF59-4D16-8947-E81BBFFAB36D"), 11);
                public static readonly PROPERTYKEY PKEY_FileVersion = new PROPERTYKEY(new Guid("0CEF7D53-FA64-11D1-A203-0000F81FEDEE"), 4);
                public static readonly PROPERTYKEY PKEY_Fonts_Version = new PROPERTYKEY(new Guid("fec7952b-4bf0-4c03-b6e1-2796818b7ca9"), 0x00000064);
                public static readonly PROPERTYKEY PKEY_Fonts_FileNames = new PROPERTYKEY(new Guid("4530d076-b598-4a81-8813-9b11286ef6ea"), 7);
                public static readonly PROPERTYKEY PKEY_Fonts_Type = new PROPERTYKEY(new Guid("4530d076-b598-4a81-8813-9b11286ef6ea"), 5);            
            }
    
    
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                IShellFolder psfDesktop;
                HRESULT hr = SHGetDesktopFolder(out psfDesktop);
                IntPtr pidlFonts = IntPtr.Zero;
                Guid FOLDERID_Fonts = new Guid("FD228CB7-AE11-4AE3-864C-16F3910AB8FE");
                hr = SHGetKnownFolderIDList(ref FOLDERID_Fonts, 0, IntPtr.Zero, out pidlFonts);
                if (hr == HRESULT.S_OK)
                {
                    object ObjpsfFonts = null;
                    hr = psfDesktop.BindToObject(pidlFonts, IntPtr.Zero, typeof(IShellFolder).GUID, out ObjpsfFonts);
                    if (hr == HRESULT.S_OK)
                    {
                        IEnumIDList ppenum;
                        IShellFolder psfFonts = (IShellFolder)ObjpsfFonts;
                        hr = psfFonts.EnumObjects(IntPtr.Zero, SHCONTF.SHCONTF_ENABLE_ASYNC | SHCONTF.SHCONTF_FLATLIST | SHCONTF.SHCONTF_FOLDERS | SHCONTF.SHCONTF_INCLUDEHIDDEN | SHCONTF.SHCONTF_NONFOLDERS, out ppenum);
                        if (hr == HRESULT.S_OK)
                        {
                            IntPtr pidlChild = IntPtr.Zero;
                            int celtFetched = 0;
                            while ((hr = ppenum.Next(1, out pidlChild, out celtFetched)) == HRESULT.S_OK && celtFetched == 1)
                            {
                                // Name
                                STRRET strretFolderName;
                                hr = psfFonts.GetDisplayNameOf(pidlChild, SHGDNF.SHGDN_INFOLDER, out strretFolderName);
                                string sDisplayName = null;
                                //StringBuilder sbDisplayName = default;
                                StringBuilder sbDisplayName = new StringBuilder(256);
                                StrRetToBuf(ref strretFolderName, pidlChild, sbDisplayName, (uint)sbDisplayName.Capacity);
                                sDisplayName = sbDisplayName.ToString();
    
                                IShellFolder2 psf2Fonts = (IShellFolder2)psfFonts;
                                // System.Fonts.Type
                                object vVariantFontsType = null;
                                PROPERTYKEY pkFontsType = PROPERTYKEY.PKEY_Fonts_Type;
                                hr = psf2Fonts.GetDetailsEx(pidlChild, ref pkFontsType, out vVariantFontsType);
                                // System.Fonts.FileNames
                                object vVariantFontsFilenames = null;
                                PROPERTYKEY pkFontsFileNames = PROPERTYKEY.PKEY_Fonts_FileNames;
                                hr = psf2Fonts.GetDetailsEx(pidlChild, ref pkFontsFileNames, out vVariantFontsFilenames);
                                Console.WriteLine(string.Format("Name : {0} - Type : {1} - File Name : {2}", sDisplayName, vVariantFontsType, vVariantFontsFilenames == null?"[See below]":((string[])vVariantFontsFilenames)[0]));
                                // Enumerate sub-fonts
                                if (vVariantFontsFilenames == null)
                                {
                                    object ObjpsfProgramChilds = null;
                                    hr = psf2Fonts.BindToObject(pidlChild, IntPtr.Zero, typeof(IShellFolder).GUID, out ObjpsfProgramChilds);
                                    if (hr == HRESULT.S_OK)
                                    {
                                        IEnumIDList ppenumChild;
                                        IShellFolder psfFontsChild = (IShellFolder)ObjpsfProgramChilds;
                                        hr = psfFontsChild.EnumObjects(IntPtr.Zero, SHCONTF.SHCONTF_ENABLE_ASYNC | SHCONTF.SHCONTF_FLATLIST | SHCONTF.SHCONTF_FOLDERS | SHCONTF.SHCONTF_INCLUDEHIDDEN | SHCONTF.SHCONTF_NONFOLDERS, out ppenumChild);
                                        if (hr == HRESULT.S_OK)
                                        {
                                            IntPtr pidlChild2 = IntPtr.Zero;
                                            int celtFetched2 = 0;
                                            while ((hr = ppenumChild.Next(1, out pidlChild2, out celtFetched2)) == HRESULT.S_OK && celtFetched2 == 1)
                                            {   
                                                // Name
                                                hr = psfFontsChild.GetDisplayNameOf(pidlChild2, SHGDNF.SHGDN_INFOLDER, out strretFolderName);
                                                sDisplayName = null;                                            
                                                StringBuilder sbDisplayName2 = new StringBuilder(256);
                                                StrRetToBuf(ref strretFolderName, pidlChild, sbDisplayName2, (uint)sbDisplayName2.Capacity);
                                                sDisplayName = sbDisplayName2.ToString();
    
                                                // System.Fonts.FileNames
                                                IShellFolder2 psf2FontsChild = (IShellFolder2)psfFontsChild;
                                                hr = psf2FontsChild.GetDetailsEx(pidlChild2, ref pkFontsFileNames, out vVariantFontsFilenames);
                                                Console.WriteLine(string.Format("\tName : {0} - Type : {1} - File Name : {2}", sDisplayName, vVariantFontsType, vVariantFontsFilenames == null ? "" : ((string[])vVariantFontsFilenames)[0]));
                                            }
                                            Marshal.ReleaseComObject(ppenumChild);
                                        }
                                        Marshal.ReleaseComObject(psfFontsChild);
                                    }
                                }
                            }
                            Marshal.ReleaseComObject(ppenum);
                        }
                        Marshal.ReleaseComObject(psfFonts);
                    }
                }
                Marshal.ReleaseComObject(psfDesktop);
            }
        }


    This solution worked!


    Thank you Castorix31



    Regards

    Sunday, September 27, 2020 2:21 PM