当OneDrive安装时启用了已知文件夹移动,用户的第一次登录开始时不重定向已知文件夹,然后在会话进行到一半时,它们被重定向到OneDrive文件夹。
我该如何检测?
我已经在CSIDL_Desktop
上尝试过WM_SETTINGCHANGE
和SHChangeNotifyRegister
,但都没有成功。
这是一个肮脏的未记录的黑客,但如果您监视HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionExplorerUser Shell Folders
的更改,它将在重定向时触发。
如何做到这一点的C#示例是:
public sealed class KnownFolderWatcher : IDisposable
{
private readonly SynchronizationContext SyncCtx;
private readonly RegistryKey Key;
private readonly Thread thRead;
private readonly AutoResetEvent mreTriggered;
public event EventHandler KeyChanged;
private Exception Exception;
private bool isDisposed;
public KnownFolderWatcher(SynchronizationContext syncCtx)
{
this.SyncCtx = syncCtx ?? throw new ArgumentNullException(nameof(syncCtx));
this.Key = Registry.CurrentUser.OpenSubKey(@"SoftwareMicrosoftWindowsCurrentVersionExplorerUser Shell Folders", false)
?? throw new InvalidOperationException("Could not open User Shell Folders key");
this.mreTriggered = new AutoResetEvent(false);
this.thRead = new Thread(thRead_Main);
this.thRead.Name = "Registry Change Reader";
this.thRead.IsBackground = true;
this.thRead.Start();
}
private void thRead_Main()
{
try
{
while (true)
{
NativeMethods.RegNotifyChangeKeyValue(Key.Handle, false, 4 /* REG_NOTIFY_CHANGE_LAST_SET */, mreTriggered.SafeWaitHandle, true);
mreTriggered.WaitOne();
if (isDisposed)
{
break;
}
SyncCtx.Post(_1 =>
{
KeyChanged?.Invoke(this, EventArgs.Empty);
}, null);
}
}
catch (Exception ex)
{
this.Exception = ex;
}
}
public void Dispose()
{
if (isDisposed)
{
throw new ObjectDisposedException(nameof(KnownFolderWatcher));
}
isDisposed = true;
mreTriggered.Set();
thRead.Join();
if (this.Exception != null)
{
throw new InvalidOperationException("Exception from read thread", Exception);
}
}
}
internal static class NativeMethods
{
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern uint RegNotifyChangeKeyValue(SafeRegistryHandle key, bool watchSubTree, uint notifyFilter, SafeWaitHandle regEvent, bool async);
}