当 OneDrive 安装时启用了已知文件夹移动,用户首次登录时不会重定向已知文件夹,然后在会话中途,它们会被重定向到 OneDrive 文件夹。
我怎样才能检测到呢?
我已经尝试过,WM_SETTINGCHANGE
但无济于事。SHChangeNotifyRegister
CSIDL_Desktop
当 OneDrive 安装时启用了已知文件夹移动,用户首次登录时不会重定向已知文件夹,然后在会话中途,它们会被重定向到 OneDrive 文件夹。
我怎样才能检测到呢?
我已经尝试过,WM_SETTINGCHANGE
但无济于事。SHChangeNotifyRegister
CSIDL_Desktop
这是一个肮脏的无证黑客,但是如果您监视HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
更改,它将在重定向时触发。
如何执行此操作的 AC# 示例是:
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(@"Software\Microsoft\Windows\CurrentVersion\Explorer\User 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);
}