如何在UWP中获取StorageFile或StorageFolder的Win32 HANDLE?

时间:2017-03-15 00:46:28

标签: winapi windows-runtime uwp windows-10-universal

我知道我可以使用Win32 API访问我自己的本地数据文件夹中的文件(例如,请参阅this answered question)但我需要访问我的应用程序之外的文件(例如,从图片库)和库我正在尝试使用全部基于Win32文件HANDLE和/或它们依赖于使用相对文件名。

由于获取图片库中文件(或从拾取器返回文件/文件夹)的唯一方法是通过StorageFile个对象,如何重新使用现有代码?我是否必须将其重新编写为异步并依赖WinRT存储API?

1 个答案:

答案 0 :(得分:15)

从“周年纪念更新”(又名“RS1”或版本10.0.14393)开始,您可以从HANDLE(文件或文件夹)获取Win32 StorageItem并创建新命名HANDLE内的文件(返回StorageFolder)。您可以使用新的IStorageFolderHandleAccessIStorageItemHandleAccess API执行此操作。

  

注意:这些API意外地放在WINAPI_PARTITION_DESKTOP分区内(它们不是特定于桌面的;它们可供UWP使用)。这将在未来的SDK更新中解决。

要使用这些新的COM接口之一,您只需为接口启用StorageFileStorageFolder。如果不支持该接口,则意味着您的应用程序在低级操作系统上运行(或者存储项实际上不是由真实文件支持,而是伪文件)。您可以使用C ++(C ++ / CX或WRL)或C#中的这些接口。

这是一个简单的示例,使用FolderPicker让用户在其磁盘上选择一个位置(返回一个代理的StorageFolder对象),然后使用Win32 API ReadFile和{{ 1}}从该位置读取和写入文件。

如上所述,我们必须将接口的声明复制到我们自己的代码中,因为真正的SDK版本位于错误的API分区中。 (我建议不要修改SDK文件来解决问题)。首先是我们自己的头文件,例如WriteFile,它复制SDK文件StorageHandleAccess.h中的声明:

WindowsStorageCOM.h

接下来是API的简单用法。此示例采用#pragma once // These are copied from WindowsStorageCOM.h // You can remove this header file once the real file has been updated // to fix the WINAPI_PARTITION_DESKTOP block typedef interface IOplockBreakingHandler IOplockBreakingHandler; typedef interface IStorageItemHandleAccess IStorageItemHandleAccess; typedef interface IStorageFolderHandleAccess IStorageFolderHandleAccess; #ifdef __cplusplus extern "C" { #endif typedef /* [v1_enum] */ enum HANDLE_OPTIONS { HO_NONE = 0, HO_OPEN_REQUIRING_OPLOCK = 0x40000, HO_DELETE_ON_CLOSE = 0x4000000, HO_SEQUENTIAL_SCAN = 0x8000000, HO_RANDOM_ACCESS = 0x10000000, HO_NO_BUFFERING = 0x20000000, HO_OVERLAPPED = 0x40000000, HO_WRITE_THROUGH = 0x80000000 } HANDLE_OPTIONS; DEFINE_ENUM_FLAG_OPERATORS(HANDLE_OPTIONS); typedef /* [v1_enum] */ enum HANDLE_ACCESS_OPTIONS { HAO_NONE = 0, HAO_READ_ATTRIBUTES = 0x80, HAO_READ = 0x120089, HAO_WRITE = 0x120116, HAO_DELETE = 0x10000 } HANDLE_ACCESS_OPTIONS; DEFINE_ENUM_FLAG_OPERATORS(HANDLE_ACCESS_OPTIONS); typedef /* [v1_enum] */ enum HANDLE_SHARING_OPTIONS { HSO_SHARE_NONE = 0, HSO_SHARE_READ = 0x1, HSO_SHARE_WRITE = 0x2, HSO_SHARE_DELETE = 0x4 } HANDLE_SHARING_OPTIONS; DEFINE_ENUM_FLAG_OPERATORS(HANDLE_SHARING_OPTIONS); typedef /* [v1_enum] */ enum HANDLE_CREATION_OPTIONS { HCO_CREATE_NEW = 0x1, HCO_CREATE_ALWAYS = 0x2, HCO_OPEN_EXISTING = 0x3, HCO_OPEN_ALWAYS = 0x4, HCO_TRUNCATE_EXISTING = 0x5 } HANDLE_CREATION_OPTIONS; EXTERN_C const IID IID_IOplockBreakingHandler; MIDL_INTERFACE("826ABE3D-3ACD-47D3-84F2-88AAEDCF6304") IOplockBreakingHandler : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE OplockBreaking(void) = 0; }; EXTERN_C const IID IID_IStorageItemHandleAccess; MIDL_INTERFACE("5CA296B2-2C25-4D22-B785-B885C8201E6A") IStorageItemHandleAccess : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Create( /* [in] */ HANDLE_ACCESS_OPTIONS accessOptions, /* [in] */ HANDLE_SHARING_OPTIONS sharingOptions, /* [in] */ HANDLE_OPTIONS options, /* [optional][in] */ __RPC__in_opt IOplockBreakingHandler *oplockBreakingHandler, /* [system_handle][retval][out] */ __RPC__deref_out_opt HANDLE *interopHandle) = 0; }; EXTERN_C const IID IID_IStorageFolderHandleAccess; MIDL_INTERFACE("DF19938F-5462-48A0-BE65-D2A3271A08D6") IStorageFolderHandleAccess : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Create( /* [string][in] */ __RPC__in_string LPCWSTR fileName, /* [in] */ HANDLE_CREATION_OPTIONS creationOptions, /* [in] */ HANDLE_ACCESS_OPTIONS accessOptions, /* [in] */ HANDLE_SHARING_OPTIONS sharingOptions, /* [in] */ HANDLE_OPTIONS options, /* [optional][in] */ __RPC__in_opt IOplockBreakingHandler *oplockBreakingHandler, /* [system_handle][retval][out] */ __RPC__deref_out_opt HANDLE *interopHandle) = 0; }; #ifdef __cplusplus } #endif ,文件名和创建标志(打开或创建)并尝试打开(或创建)指定文件,从(到)文件读取(或写入)某些文本,并写入一些输出到Debug控制台。

代码在实际环境中并不特别有用,但说明了如何使用API​​。这可以在空白的C ++ XAML项目中使用,以替换StorageFolder文件(您只需要更新命名空间):

MainPage.xaml.cpp