问题描述
我需要创建一个虚拟文件系统,以将文件从我的Azure应用服务同步到本地驱动器并向后同步。我只需要将一些文件和文件夹同步到本地文件系统并可以脱机使用。文件/文件夹应在首次访问时或用户选择“始终保留在此设备上”菜单时进行同步。与OneDrive的操作类似。我发现Microsoft CloudMirror C ++示例具有一些基本的OneDrive功能,但是在启动过程中一次同步了所有文件,并且在首次访问时没有列表/加载。
解决方法
要构建类似OneDrive的客户端,您需要使用云过滤器API创建Sync Provider,该API主要可以通过Win32编程(有一些例外,请参阅下文),但是您可以在.NET中构建完整的OneDrive模拟,包括“始终保留在此设备上”菜单和按需加载。
这是.NET可用的功能,因此您无需PInvoke它:
- 可以通过StorageProviderSyncRootManager和StorageProviderSyncRootInfo类在.NET中完成同步根注册。
- 您可以使用StorageProviderItemProperty类和IStorageProviderItemPropertySource界面在.NET中创建属性。
- 可以通过StorageProviderItemProperties.SetAsync()方法和StorageFile / StorageFolder类设置Windows File Manager中文件和文件夹上的图标。
- 您可以使用File.GetAttributes() / File.SetAttributes()在.NET中读取和设置文件属性。您将需要它们读取脱机属性,固定和未固定的属性。
- 可以通过实现IStorageProviderUriSource接口来完成URI映射的文件系统路径。
此处仅通过Win32函数提供的功能,您需要通过PInvoke对其进行调用:
- 文件夹按需枚举,按需文件内容加载仅可通过Win32回调进行。您将需要使用CfConnectSyncRoot()注册回调。
- 通过Windows资源管理器菜单对文件进行水合/脱水。您将需要监视文件系统并调用CfHydratePlaceholder()和CfUpdatePlaceholder()。
- 下载进度报告,错误报告,到Windows的通知,同步提供程序状态报告。要报告进度,请使用CfReportProviderProgress()。通过CfExecute()报告错误。
- 检测是文件是常规文件/文件夹还是占位符文件/文件夹。可以通过CfGetPlaceholderStateFromFileInfo()调用来完成。
- 创建占位符并更新占位符的信息。可以使用CfCreatePlaceholders()和CfUpdatePlaceholder()函数来完成。
- 将文件/文件夹转换为占位符并返回。可以使用CfConvertToPlaceholder()和CfRevertPlaceholder()完成。
- 设置和读取占位符状态,例如同步/不同步。可以使用CfGetPlaceholderStateFromFileInfo()和CfGetPlaceholderInfo()完成。
您可以执行以下操作以在.NET中编写所有代码:
-
一种选择是使用.NET的extern import all required Win32 functions,例如:
[DllImport("cldapi.dll",SetLastError = true,ExactSpelling = true)] public static extern int CfGetPlaceholderStateFromFileInfo(IntPtr infoBuffer,FILE_INFO_BY_HANDLE_CLASS infoClass); [DllImport("cldapi.dll",ExactSpelling = true)] public static extern HRESULT CfSetPinState(IntPtr fileHandle,int pinState,int pinFlags,IntPtr overlapped);
-
另一个选项可以是using this sample。
关于构建类似OneDrive的文件系统的更多说明:
- 同步根注册后,将自动显示“始终保留在此设备上” /“释放空间”。但是它仅设置“固定”和“不固定”文件属性。您需要监视文件系统,检查固定/未固定的属性,然后对每个文件进行水合/脱水。
- 按需列出文件夹是在CF_CALLBACK_TYPE_FETCH_PLACEHOLDERS回调内部完成的。您需要使用CfConnectSyncRoot()注册回调并以.NET代码收听。
- 按需文件内容下载(水化)是在CF_CALLBACK_TYPE_FETCH_DATA回调内部完成的。您需要使用.NET代码进行注册和收听。