using System; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; namespace Framework.Support { /// Helper methods for invoking the Windows shell API public static class ShellApiHelper { /// Special folder id of the user's 'My Documents' folder public const int CSIDL_PERSONAL = 0x0005; /// ID of the 'Saved Games' folder in the known folder manager public static readonly Guid FOLDERID_SavedGames = new Guid( 0x4c5c32ff, 0xbb9d, 0x43b0, 0xb5, 0xb4, 0x2d, 0x72, 0xe5, 0x4e, 0xaa, 0xa4 ); /// Maximum buffer size most Win32 API functions expect private const int MAX_PATH = 260; /// COM ClassID of the KnownFolderManager proxy coclass private const string CLSID_KnownFolderManager = "4df0c730-df9d-4ae3-9153-aa6b82e9795a"; /// COM InterfaceID of the IKnownFolder interface private const string IID_IKnownFolder = "3aa7af7e-9b36-420c-a8e3-f77d4674a488"; /// COM InterfaceID of the IKnownFolderManager interface private const string IID_IKnownFolderManager = "8be2d872-86aa-4d47-b776-32cca40c7018"; /// Retrieves the path of a special folder, identified by its CSIDL /// Not used, always set to IntPtr.Zero /// Received the drive and path o the specified folder /// /// CSIDL that identifies that folder whose path will be retrieved /// /// /// Whether the folder should be created if it doesn't exist /// /// Any nonzero value if successful, otherwise 0 [DllImport("Shell32", CharSet = CharSet.Unicode)] private static extern int SHGetSpecialFolderPath( IntPtr ownerWindowHandle, StringBuilder path, int folderId, int createFlag ); #region interface IKnownFolder /// Accesses informations about a known folder, including its path [ ComImport, Guid(IID_IKnownFolder), InterfaceType(ComInterfaceType.InterfaceIsIUnknown) ] private interface IKnownFolder { /// GetId() is not provided void GetId_Stub(); /// GetCategory() is not provided void GetCategory_Stub(); /// GetShellItem() is not provided void GetShellItem_Stub(); /// Retrieves the path of a known folder as a string /// /// Flags that specify special retrieval options. This value can be 0; /// otherwise, one or more of the KNOWN_FOLDER_FLAG values /// /// /// Receives a pointer to a null-terminated buffer that contains the path /// [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] void GetPath([In] uint flags, [MarshalAs(UnmanagedType.LPWStr)] out string path); /// SetPath() is not provided void SetPath_Stub(); /// GetLocation() is not provided void GetLocation_Stub(); /// GetFolderType() is not provided void GetFolderType_Stub(); /// GetRedirectionCapabilities() is not provided void GetRedirectionCapabilities_Stub(); /// GetFolderDefinition() is not provided void GetFolderDefinition_Stub(); } #endregion // interface IKnownFolder #region interface IKnownFolderManager /// Enumerates, creates and manages known folders [ ComImport, Guid(IID_IKnownFolderManager), InterfaceType(ComInterfaceType.InterfaceIsIUnknown) ] private interface IKnownFolderManager { /// FolderIdFromCsidl() is not provided void FolderIdFromCsidl_Stub(); /// FolderIdToCsidl() is not provided void FolderIdToCsidl_Stub(); /// GetFolderIds() is not provided void GetFolderIds_Stub(); /// Retrieves informations about a known folder by its id /// /// Id of the known folder whose informations will be retrieved /// /// Receives the known folder information instance [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] void GetFolder( [In] ref Guid folderId, [MarshalAs(UnmanagedType.Interface)] out IKnownFolder knownFolder ); /// GetFolderByName() is not provided void GetFolderByName_Stub(); /// RegisterFolder() is not provided void RegisterFolder_Stub(); /// UnregisterFolder() is not provided void UnregisterFolder_Stub(); /// FindFolderFromPath() is not provided void FindFolderFromPath_Stub(); /// FindFolderFromIDList() is not provided void FindFolderFromIDList_Stub(); /// Redirect() is not provided void Redirect_Stub(); } #endregion // interface IKnownFolderManager #region class KnownFolderManagerImpl /// KnownFolderManager proxy coclass [ComImport, Guid(CLSID_KnownFolderManager)] internal class KnownFolderManagerImpl { } #endregion // class KnownFolderManagerImpl /// Retrieves the path of a special folder by its CSIDL /// /// CSIDL of the special folder whose path will be retrieved /// /// The path of the special folder with the specified CSIDL public static string GetSpecialFolder(int folderId) { var path = new StringBuilder(MAX_PATH); int result = SHGetSpecialFolderPath(IntPtr.Zero, path, folderId, 1); if(result == 0) { throw new Win32Exception("Could not query special folder path"); } return path.ToString(); } /// Retrieves the path of a known folder /// GUID of the known folderparam> /// The path of the known folder with the specified GUID public static string GetKnownFolder(Guid knownFolderId) { var instance = new KnownFolderManagerImpl(); if(instance == null) { throw new COMException("Could not create instance of known folder manager coclass"); } IKnownFolderManager knownFolderManager = (IKnownFolderManager)instance as IKnownFolderManager; if(knownFolderManager == null) { throw new COMException("Could not query known folder manager interface"); } IKnownFolder knownFolder; knownFolderManager.GetFolder(ref knownFolderId, out knownFolder); if(knownFolder == null) { throw new COMException("Could not query known folder"); } string path; knownFolder.GetPath(0, out path); return path; } } } // namespace Framework.Support