Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I check local OneDrive folder is in sync?

I need to be able to check if the local OneDrive folder is in sync/up to date.

Can I check this by looking at any of the file/folder properties(in C# code) Without using any of One Drive APIs?

like image 645
monika pathak Avatar asked Dec 20 '16 11:12

monika pathak


People also ask

How do I know which OneDrive folders to sync?

To choose which folders you're syncing, right-click the blue cloud icon in the taskbar notification area, and select Settings > Account > Choose folders.

How do I know if my OneDrive files are syncing?

Check the little icon in the bottom left corner. If it has a green circle with a white checkmark, it is being synced to the cloud. This file is being synced. These files, from my Download folder, are NOT being synced.

Can OneDrive sync with local folder?

You can back up your important folders (your Desktop, Documents, and Pictures folders) on your Windows PC with OneDrive PC folder backup, so they're protected and available on other devices.


1 Answers

I was stuck with that and tought to check the main folder Icon.

EDITED

The point is to extract the synced folder icon and get the overlay CLSID.

You first need a class to extract the info you need :

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32;


namespace MyApp.Classes
{
    public class ExtractIconInfo
    {
        [Flags]
        private enum SHGFI : uint
        {
            SHGFI_ICON = 0x000000100,
            SHGFI_DISPLAYNAME = 0x000000200,
            SHGFI_TYPENAME = 0x000000400,
            SHGFI_ATTRIBUTES = 0x000000800,
            SHGFI_ICONLOCATION = 0x000001000,
            SHGFI_EXETYPE = 0x000002000,
            SHGFI_SYSICONINDEX = 0x000004000,
            SHGFI_LINKOVERLAY = 0x000008000,
            SHGFI_SELECTED = 0x000010000,
            SHGFI_ATTR_SPECIFIED = 0x000020000,
            SHGFI_LARGEICON = 0x000000000,
            SHGFI_SMALLICON = 0x000000001,
            SHGFI_OPENICON = 0x000000002,
            SHGFI_SHELLICONSIZE = 0x000000004,
            SHGFI_PIDL = 0x000000008,
            SHGFI_USEFILEATTRIBUTES = 0x000000010,
            SHGFI_ADDOVERLAYS = 0x000000020,
            SHGFI_OVERLAYINDEX = 0x000000040
        }

        [Flags]
        private enum FileAttributes : uint
        {
            Readonly = 0x00000001,
            Hidden = 0x00000002,
            System = 0x00000004,
            Directory = 0x00000010,
            Archive = 0x00000020,
            Device = 0x00000040,
            Normal = 0x00000080,
            Temporary = 0x00000100,
            SparseFile = 0x00000200,
            ReparsePoint = 0x00000400,
            Compressed = 0x00000800,
            Offline = 0x00001000,
            NotContentIndexed = 0x00002000,
            Encrypted = 0x00004000,
            Virtual = 0x00010000
        }

        [Flags]
        public enum ISIOI : uint
        {
            ISIOI_ICONFILE = 0x00000001,
            ISIOI_ICONINDEX = 0x00000002
        }

        private SortedDictionary<string, Guid> ShellIconOverlayIdentifiers;

        public string IconName { get; private set; }
        public Icon Icon { get; private set; }
        public int IconOverlayIndex { get; private set; }
        public Guid IconOverlayGuid { get; private set; }

        public ExtractIconInfo(FileInfo fi)
        {
            ExtractIcon(fi.FullName, false);
        }
        public ExtractIconInfo(DirectoryInfo di)
        {
            ExtractIcon(di.FullName, true);
        }
        public ExtractIconInfo(string path, bool isFolder)
        {
            ExtractIcon(path, isFolder);
        }

        [ComVisible(false)]
        [ComImport]
        [Guid("0C6C4200-C589-11D0-999A-00C04FD655E1")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IShellIconOverlayIdentifier
        {
            [PreserveSig]
            int IsMemberOf([MarshalAs(UnmanagedType.LPWStr)] string path, uint attributes);
            [PreserveSig]
            int GetOverlayInfo([MarshalAs(UnmanagedType.LPWStr)] string iconFileBuffer, int iconFileBufferSize, out int iconIndex, out uint flags);
            [PreserveSig]
            int GetPriority(out int priority);
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct SHFILEINFO
        {
            internal IntPtr hIcon;
            internal int iIcon;
            internal uint dwAttributes;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            internal string szDisplayName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
            internal string szTypeName;
        };

        [DllImport("shell32.dll")]
        private static extern IntPtr SHGetFileInfo(
            string pszPath,
            uint dwFileAttributes,
            ref SHFILEINFO psfi,
            uint cbSizeFileInfo,
            uint uFlags
        );

        [DllImport("shell32.dll")]
        private static extern int SHGetIconOverlayIndex(
            string pszIconPath,
            int iIconIndex
        );

        [DllImport("user32.dll")]
        public static extern int DestroyIcon(IntPtr hIcon);

        private void ExtractIcon(string path, bool isFolder)
        {
            SHFILEINFO shIconInfo = new SHFILEINFO();
            SHGetFileInfo(path, isFolder ? (uint)FileAttributes.Directory : (uint)FileAttributes.Normal, ref shIconInfo, (uint)Marshal.SizeOf(shIconInfo), (uint)SHGFI.SHGFI_ICON | (uint)SHGFI.SHGFI_LARGEICON | (uint)SHGFI.SHGFI_DISPLAYNAME | (uint)SHGFI.SHGFI_ADDOVERLAYS | (uint)SHGFI.SHGFI_OVERLAYINDEX);
            Icon = (Icon)Icon.FromHandle(shIconInfo.hIcon).Clone();
            IconName = shIconInfo.szDisplayName;
            IconOverlayIndex = (shIconInfo.iIcon >> 24) & 0xFF;
            GetOverlayIconGuid();

            DestroyIcon(shIconInfo.hIcon);
        }

        private void GetOverlayIconGuid()
        {
            IconOverlayGuid = Guid.Empty;
            GetRegistryShellIconOverlayIdentifiers();
            foreach (string key in ShellIconOverlayIdentifiers.Keys)
            {
                string AIconFileName = string.Empty;
                int AIconIndex = 0;
                Guid value = ShellIconOverlayIdentifiers[key];
                GetOverlayIconInfo(value, out AIconFileName, out AIconIndex);
                if (SHGetIconOverlayIndex(AIconFileName, AIconIndex) == IconOverlayIndex)
                    IconOverlayGuid = value;
            }
        }

        private void GetOverlayIconInfo(Guid CLSID, out string path, out int index)
        {
            try
            {
                path = new string(' ', 256);
                uint flags = 0;
                IShellIconOverlayIdentifier SHIOI = Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID, true), true) as IShellIconOverlayIdentifier;
                SHIOI.GetOverlayInfo(path, path.Length, out index, out flags);
                Marshal.ReleaseComObject(SHIOI);

                if ((flags & (uint)ISIOI.ISIOI_ICONFILE) != 0)
                {
                    if ((flags & (uint)ISIOI.ISIOI_ICONINDEX) == 0) index = 0;
                }
                else
                {
                    path = string.Empty;
                    index = 0;
                }
                path = path.Substring(0, path.IndexOf('\0'));
            }
            catch
            {
                path = string.Empty;
                index = 0;
            }
        }

        private void GetRegistryShellIconOverlayIdentifiers()
        {
            ShellIconOverlayIdentifiers = new SortedDictionary<string, Guid>();

            using (RegistryKey key32 = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, Environment.MachineName, RegistryView.Registry32).OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers"))
                foreach (string subKey in key32.GetSubKeyNames())
                {
                    Guid value = Guid.Parse((string)key32.OpenSubKey(subKey).GetValue(null));
                    if (!ShellIconOverlayIdentifiers.ContainsKey(subKey))
                        ShellIconOverlayIdentifiers.Add(subKey, value);
                }

            using (RegistryKey key64 = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, Environment.MachineName, RegistryView.Registry64).OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers"))
                foreach (string subKey in key64.GetSubKeyNames())
                {
                    Guid value = Guid.Parse((string)key64.OpenSubKey(subKey).GetValue(null));
                    if (!ShellIconOverlayIdentifiers.ContainsKey(subKey))
                        ShellIconOverlayIdentifiers.Add(subKey, value);
                }
        }
    }
}

The relevant info here is IconOverlayGuid.

Then compare :

public enum SyncStatus { Off, Unknown, Syncing, Synced, SharedSyncing, SharedSynced, Error }

private SyncStatus CheckIfSync(DirectoryInfo di)
{
    ExtractIconInfo IcoInfo = new ExtractIconInfo(di);
    if (IcoInfo != null)
    {
        if (IcoInfo.IconOverlayGuid == Guid.Empty) return SyncStatus.Off;
        else if (IcoInfo.IconOverlayGuid == new Guid("{BBACC218-34EA-4666-9D7A-C78F2274A524}")) return SyncStatus.Error;
        else if (IcoInfo.IconOverlayGuid == new Guid("{F241C880-6982-4CE5-8CF7-7085BA96DA5A}")) return SyncStatus.Synced;
        else if (IcoInfo.IconOverlayGuid == new Guid("{A0396A93-DC06-4AEF-BEE9-95FFCCAEF20E}")) return SyncStatus.Syncing;
        else if (IcoInfo.IconOverlayGuid == new Guid("{5AB7172C-9C11-405C-8DD5-AF20F3606282}")) return SyncStatus.SharedSynced;
        else if (IcoInfo.IconOverlayGuid == new Guid("{A78ED123-AB77-406B-9962-2A5D9D2F7F30}")) return SyncStatus.SharedSyncing;
        else return SyncStatus.Unknown;
    }
    else return SyncStatus.Unknown;
}

The Overlay Icons are stored in FileSyncShell.dll. Their CLSID are stored in the registry : HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers and HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers.

REGEDIT

  • OneDrive1 : Sync in error
  • OneDrive2 : Synced Shared
  • OneDrive3 : Syncing Shared
  • OneDrive4 : Synced
  • OneDrive5 : Syncing

Hope that helps !

(I spent way too much time on that one, but I learned a lot !)

like image 142
DKH Avatar answered Oct 16 '22 07:10

DKH