我知道我可以使用Win32 API访问我自己的本地数据文件夹中的文件(例如,请参阅this answered question)但我需要访问我的应用程序之外的文件(例如,从图片库)和库我正在尝试使用全部基于Win32文件HANDLE
和/或它们依赖于使用相对文件名。
由于获取图片库中文件(或从拾取器返回文件/文件夹)的唯一方法是通过StorageFile
个对象,如何重新使用现有代码?我是否必须将其重新编写为异步并依赖WinRT存储API?
答案 0 :(得分:15)
从“周年纪念更新”(又名“RS1”或版本10.0.14393)开始,您可以从HANDLE
(文件或文件夹)获取Win32 StorageItem
并创建新命名HANDLE
内的文件(返回StorageFolder
)。您可以使用新的IStorageFolderHandleAccess
和IStorageItemHandleAccess
API执行此操作。
注意:这些API意外地放在
WINAPI_PARTITION_DESKTOP
分区内(它们不是特定于桌面的;它们可供UWP使用)。这将在未来的SDK更新中解决。
要使用这些新的COM接口之一,您只需为接口启用StorageFile
或StorageFolder
。如果不支持该接口,则意味着您的应用程序在低级操作系统上运行(或者存储项实际上不是由真实文件支持,而是伪文件)。您可以使用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