// This is a work around for the STA thread bug. This will execute the call on a non-sta thread, then return the result private static bool IsVirtualKnownFolder(IShellItem2 nativeShellItem2) { IntPtr pidl = IntPtr.Zero; try { IKnownFolderNative nativeFolder = null; KnownFoldersSafeNativeMethods.NativeFolderDefinition definition = new KnownFoldersSafeNativeMethods.NativeFolderDefinition(); // We found a bug where the enumeration of shell folders was // not reliable when called from a STA thread - it would return // different results the first time vs the other times. // // This is a work around. We call FindFolderFromIDList on a // worker MTA thread instead of the main STA thread. // // Ultimately, it would be a very good idea to replace the 'getting shell object' logic // to get a list of pidl's in 1 step, then look up their information in a 2nd, rather than // looking them up as we get them. This would replace the need for the work around. object padlock = new object(); lock (padlock) { IntPtr unknown = Marshal.GetIUnknownForObject(nativeShellItem2); ThreadPool.QueueUserWorkItem(obj => { lock (padlock) { pidl = ShellHelper.PidlFromUnknown(unknown); new KnownFolderManagerClass().FindFolderFromIDList(pidl, out nativeFolder); if (nativeFolder != null) { nativeFolder.GetFolderDefinition(out definition); } Monitor.Pulse(padlock); } }); Monitor.Wait(padlock); } return(nativeFolder != null && definition.category == FolderCategory.Virtual); } finally { ShellNativeMethods.ILFree(pidl); } }
public virtual extern void RegisterFolder( [In, MarshalAs(UnmanagedType.LPStruct)] Guid knownFolderGuid, [In] ref KnownFoldersSafeNativeMethods.NativeFolderDefinition knownFolderDefinition);
// This is a work around for the STA thread bug. This will execute the call on a non-sta thread, then return the result private static bool IsVirtualKnownFolder(IShellItem2 nativeShellItem2) { IntPtr pidl = IntPtr.Zero; try { IKnownFolderNative nativeFolder = null; KnownFoldersSafeNativeMethods.NativeFolderDefinition definition = new KnownFoldersSafeNativeMethods.NativeFolderDefinition(); // We found a bug where the enumeration of shell folders was // not reliable when called from a STA thread - it would return // different results the first time vs the other times. // // This is a work around. We call FindFolderFromIDList on a // worker MTA thread instead of the main STA thread. // // Ultimately, it would be a very good idea to replace the 'getting shell object' logic // to get a list of pidl's in 1 step, then look up their information in a 2nd, rather than // looking them up as we get them. This would replace the need for the work around. object padlock = new object(); lock (padlock) { IntPtr unknown = Marshal.GetIUnknownForObject(nativeShellItem2); ThreadPool.QueueUserWorkItem(obj => { lock (padlock) { pidl = ShellHelper.PidlFromUnknown(unknown); new KnownFolderManagerClass().FindFolderFromIDList(pidl, out nativeFolder); if (nativeFolder != null) { nativeFolder.GetFolderDefinition(out definition); } Monitor.Pulse(padlock); } }); Monitor.Wait(padlock); } return nativeFolder != null && definition.category == FolderCategory.Virtual; } finally { ShellNativeMethods.ILFree(pidl); } }
private static void RegisterFolder() { Console.WriteLine("===============ADD================"); KnownFoldersSafeNativeMethods.NativeFolderDefinition d = new KnownFoldersSafeNativeMethods.NativeFolderDefinition(); d.category = FolderCategory.Common; d.localizedName = Marshal.StringToBSTR(EXT_NAME); d.definitionOptions = DefinitionOptions.LocalRedirectOnly; d.name = Marshal.StringToBSTR(EXT_NAME); d.description = Marshal.StringToBSTR("我的扩展描述"); d.localizedName = Marshal.StringToBSTR("MyExtension"); //var parent = KnownFolderHelper.FromKnownFolderId(new Guid("20D04FE0-3AEA-1069-A2D8-08002B30309D")); d.parentId = _computerGuid; d.folderTypeId = FolderTypes.Documents; d.relativePath = Marshal.StringToBSTR("MyExtension"); d.parsingName = Marshal.StringToBSTR("::{" + _guid + "}"); d.attributes = 1; m.RegisterFolder(_guid, ref d); Console.WriteLine("Extension added: {0}", EXT_NAME); Console.WriteLine(); Console.WriteLine(); }