現在、名前空間拡張の作成に取り組んでいます。そのため、Computer にエントリを作成し、explorer.exe で IShellFolder 実装を呼び出すようにしました。数分間動作させたので (コミットする前に愚かにもコードをクリーンアップすることにしました)、どこか近くにいます。
しかし、非常に奇妙なことに気付きました。クラスの GUID 値を変更すると、explorer.exe に表示される内容が変わります。
私は何か悪いことをしていないことを教えてくれる質問を見つけました
コードは次のとおりです。
AssemblyInfo.cs:
[assembly: ComVisible(false)]
[assembly: Guid("007C5100-4251-47BE-8141-D2AD3F496E6A")]
ルートフォルダー.cs:
[ClassInterface(ClassInterfaceType.None)
[Guid("007C5101-4251-47BE-8141-D2AD3F496E6A"), ComVisible(true)]
public class RootFolder : IShellFolder, IShellFolder2, IPersistFolder, IPersistFolder2 {
private const String _mountPoint = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\NameSpace\\{0}";
private const String _mountName = "CLSID\\{0}";
#region Shell Extension Registration
[ComRegisterFunction()]
public static void Register(Type t)
{
Console.WriteLine("Registering {0}...", t.GUID);
try {
if (t.GUID == null)
throw new ArgumentException("CLSID must not be null");
using (RegistryKey key = Registry.CurrentUser.CreateSubKey(String.Format(_mountPoint, t.GUID.ToString("B")))) {
key.SetValue(null, "RootFolder");
}
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(String.Format(_mountName, t.GUID.ToString("B")), true)) {
key.SetValue(null, "RootFolder");
using (RegistryKey shFolder = key.CreateSubKey("ShellFolder")) {
shFolder.SetValue("Attributes", 0x78000040);
shFolder.SetValue("WantsFORPARSING", "");
}
}
using (RegistryKey key = Registry.LocalMachine.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved")) {
key.SetValue(t.GUID.ToString("B"), "RootFolder");
}
IntPtr pidl = NativeMethod.SHGetKnownFolderIDList(KnownFolder.ComputerFolder.clsid, 0, IntPtr.Zero);
NativeMethod.SHChangeNotify(NativeMethod.FSNotification.UpdateDir, NativeMethod.ItemMeaning.IDList, pidl, IntPtr.Zero);
} catch (Exception ex) {
Logger.Write(Logger.Severity.Fatal, "Registration error: {0}", ex.Message);
throw; // Re-throw the exception
}
}
[ComUnregisterFunction()]
public static void Unregister(Type t)
{
try {
if (t.GUID == null)
throw new ArgumentException("CLSID must not be null");
Registry.CurrentUser.DeleteSubKey(String.Format(_mountPoint, t.GUID.ToString("B")), false);
using (RegistryKey k = Registry.ClassesRoot.OpenSubKey(String.Format(_mountName, t.GUID.ToString("B")), true)) {
if (k != null)
k.DeleteSubKey("ShellFolder");
}
using (RegistryKey key = Registry.LocalMachine.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved")) {
if (key != null)
key.DeleteValue(t.GUID.ToString("B"), false);
}
IntPtr pidl = NativeMethod.SHGetKnownFolderIDList(KnownFolder.ComputerFolder.clsid, 0, IntPtr.Zero);
NativeMethod.SHChangeNotify(NativeMethod.FSNotification.UpdateDir, NativeMethod.ItemMeaning.IDList, pidl, IntPtr.Zero);
} catch (Exception ex) {
Logger.Write(Logger.Severity.Critical, "Registration error: {0}", ex.Message);
throw; // Re-throw the exception
}
}
#endregion
#region IShellFolder2 Inheritance
[All the methods looks like that, this is just a test]
public IEnumIDList EnumObjects(IntPtr hwndOwner, EnumObject flags)
{
Logger.Write("Tracing....");
throw new NotImplementedException();
}
#endregion
#region IPersistFolder2 Inheritance
[Ditto]
#endregion
}
GUID に範囲 007C5{100...120}-4251-47BE-8141-D2AD3F496E6A を使用しています。拡張機能に GUID 007C5101 がある場合、属性なしで「RootFolder」と表示されます。007C5100 (アセンブリと同じ)、または 007C5102、または 007C5103 がある場合、「システム フォルダー」として表示されます (DLL を呼び出していません)。私はこの動作に少し戸惑っています.GUIDを変更すると、この変更がどのように発生するのでしょうか?
注:レジストリで 4251-47BE-8141-D2AD3F496E6A (GUID の不変部分) を検索しましたが、登録解除後に何も見つかりませんでした。