Reputation: 22261
When OneDrive is installed with Known Folder Move enabled, the first logon of a user starts with no redirection of known folders then midway through the session, they are redirected to the OneDrive folders.
How can I detect that?
I've already tried WM_SETTINGCHANGE
and SHChangeNotifyRegister
on CSIDL_Desktop
to no avail.
Upvotes: 1
Views: 326
Reputation: 22261
It is a dirty undocumented hack, but if you monitor HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
for changes, it will trigger on redirection.
A C# example of how to do so is:
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);
}
Upvotes: 1