UWP:使用简单快速的 PInvoke 调用 CreateFile 和 WriteFile 将文件写入磁盘
UWP: write file to disk using the simple and fast PInvoke calls CreateFile and WriteFile
我们有一个生成视频数据的非托管内存 C++ dll。用户界面在 UWP VB 中。
我需要将视频数据写入磁盘。用户从文件选择器中提供要写入的位置,并将此路径和文件名传递给 dll。使用 CreateFile 和 WriteFile 将数据写入磁盘。
这是VB代码
<DllImport("mycplus.dll", CallingConvention:=CallingConvention.StdCall)>
Public Function MainFrozen(ByVal EvF() As UInteger) As UInteger
End Function
Private Async Sub btnSaveAs_Click(sender As Object, e As RoutedEventArgs) Handles btnSaveAs.Click
Dim savePicker = New Windows.Storage.Pickers.FileSavePicker()
savePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary
savePicker.FileTypeChoices.Add("Video Files", New List(Of String)() From {".bin"})
savePicker.SuggestedFileName = gVideoFileName
Dim file As Windows.Storage.StorageFile = Await savePicker.PickSaveFileAsync()
If file IsNot Nothing Then
Dim fileName As String = file.Path
Dim d(0 To 15) As UInt32
d(0) = VIDEO_FILE_WRITE
d(1) = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(fileName)
d(2) = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(gAuthorName)
d(3) = gReserved
d(8) = MainFrozen(d)
Else
'txtDeubg.Text = "Operation cancelled."
End If
End Sub
下面是C++代码
extern "C" __declspec (dllexport) ULONG __stdcall MainFrozen(PULONG ptrEv)
{
ULONG eve = ptrEv[0];
switch (eve)
{
case VIDEO_FILE_WRITE:
SaveScanVideosToFile((LPCSTR)ptrEv[1], (LPCSTR)ptrEv[2], ptrEv[3]);
break;
}
return 0;
}
ULONG SaveScanVideosToFile(LPCSTR lpFileName,
LPCSTR lpAuthorName,
ULONG reserved)
{
HANDLE hFile;
ULONG bytesWritten;
ULONG n;
hFile = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
for (n=0; n<gScanVideoCnt; n++)
{
WriteFile(hFile, ScanVideos[n].pImg->Bcine.pCineMem, SCAN_VIDEO_MEM_SIZ, &bytesWritten, NULL);
WriteFile(hFile, ScanVideos[n].pImg, sizeof(IMG_TYPE), &bytesWritten, NULL);
}
CloseHandle(hFile);
return 0;
}
问题是我无法写入除以下位置以外的任何位置:Windows.Storage.ApplicationData.Current.LocalFolder
即 C:\Users\ravi\AppData\Local\Packagesd6e339b-614b-4161-8c7d-3570f07fc01f_2ygbv2t9jdb9y\LocalState\
在其他位置,CreateFile 失败并拒绝访问。
但是使用.net 文件功能,我可以在最新的win10 creators 版本中将其他测试文件写入我PC 的几乎所有位置,这是非常受欢迎和令人鼓舞的。
问题是:应该设置哪些安全属性才能使 CreateFile 成功并像本机 .net 文件函数一样写入所有位置?
可能有解决方法,例如将整个数据编组到托管内存或将文件写入 ApplicationData.Current.LocalFolder,然后使用 vb.net 调用移动它。但没有什么比让 CreateFile 成功更重要的了。
PS:我们的应用程序是侧加载的,仅供企业使用,我们不介意它未通过 windows 存储测试。 (我们的客户从“windows NT”天开始就信任我们:-)
Microsoft 论坛的帮助让这个工作正常。click here for the full thread
基本上将文件对象转换为IStorageItemHandleAccess 并调用Create 来获取文件HANDLE。然后在非托管代码中使用 WriteFile 和 Close。
代码如下:
<ComImport>
<Guid("5CA296B2-2C25-4D22-B785-B885C8201E6A")>
<InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
Friend Interface IStorageItemHandleAccess
Function Create(ao As Int32, so As Int32, o As Int32, oploc As Int32,
ByRef ptrHandle As IntPtr) As IntPtr
End Interface
' 在您的函数中只需 2 行额外代码即可获得神奇的 HANDLE!
Dim storageHandleIface = DirectCast(file, IStorageItemHandleAccess)
Dim myfileHandle As IntPtr
Dim res = storageHandleIface.Create(&H120116, 2, 0, 0, myfileHandle) ' WindowsStorageCom.h
我们有一个生成视频数据的非托管内存 C++ dll。用户界面在 UWP VB 中。 我需要将视频数据写入磁盘。用户从文件选择器中提供要写入的位置,并将此路径和文件名传递给 dll。使用 CreateFile 和 WriteFile 将数据写入磁盘。
这是VB代码
<DllImport("mycplus.dll", CallingConvention:=CallingConvention.StdCall)>
Public Function MainFrozen(ByVal EvF() As UInteger) As UInteger
End Function
Private Async Sub btnSaveAs_Click(sender As Object, e As RoutedEventArgs) Handles btnSaveAs.Click
Dim savePicker = New Windows.Storage.Pickers.FileSavePicker()
savePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary
savePicker.FileTypeChoices.Add("Video Files", New List(Of String)() From {".bin"})
savePicker.SuggestedFileName = gVideoFileName
Dim file As Windows.Storage.StorageFile = Await savePicker.PickSaveFileAsync()
If file IsNot Nothing Then
Dim fileName As String = file.Path
Dim d(0 To 15) As UInt32
d(0) = VIDEO_FILE_WRITE
d(1) = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(fileName)
d(2) = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(gAuthorName)
d(3) = gReserved
d(8) = MainFrozen(d)
Else
'txtDeubg.Text = "Operation cancelled."
End If
End Sub
下面是C++代码
extern "C" __declspec (dllexport) ULONG __stdcall MainFrozen(PULONG ptrEv)
{
ULONG eve = ptrEv[0];
switch (eve)
{
case VIDEO_FILE_WRITE:
SaveScanVideosToFile((LPCSTR)ptrEv[1], (LPCSTR)ptrEv[2], ptrEv[3]);
break;
}
return 0;
}
ULONG SaveScanVideosToFile(LPCSTR lpFileName,
LPCSTR lpAuthorName,
ULONG reserved)
{
HANDLE hFile;
ULONG bytesWritten;
ULONG n;
hFile = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
for (n=0; n<gScanVideoCnt; n++)
{
WriteFile(hFile, ScanVideos[n].pImg->Bcine.pCineMem, SCAN_VIDEO_MEM_SIZ, &bytesWritten, NULL);
WriteFile(hFile, ScanVideos[n].pImg, sizeof(IMG_TYPE), &bytesWritten, NULL);
}
CloseHandle(hFile);
return 0;
}
问题是我无法写入除以下位置以外的任何位置:Windows.Storage.ApplicationData.Current.LocalFolder 即 C:\Users\ravi\AppData\Local\Packagesd6e339b-614b-4161-8c7d-3570f07fc01f_2ygbv2t9jdb9y\LocalState\
在其他位置,CreateFile 失败并拒绝访问。 但是使用.net 文件功能,我可以在最新的win10 creators 版本中将其他测试文件写入我PC 的几乎所有位置,这是非常受欢迎和令人鼓舞的。
问题是:应该设置哪些安全属性才能使 CreateFile 成功并像本机 .net 文件函数一样写入所有位置?
可能有解决方法,例如将整个数据编组到托管内存或将文件写入 ApplicationData.Current.LocalFolder,然后使用 vb.net 调用移动它。但没有什么比让 CreateFile 成功更重要的了。
PS:我们的应用程序是侧加载的,仅供企业使用,我们不介意它未通过 windows 存储测试。 (我们的客户从“windows NT”天开始就信任我们:-)
Microsoft 论坛的帮助让这个工作正常。click here for the full thread
基本上将文件对象转换为IStorageItemHandleAccess 并调用Create 来获取文件HANDLE。然后在非托管代码中使用 WriteFile 和 Close。
代码如下:
<ComImport>
<Guid("5CA296B2-2C25-4D22-B785-B885C8201E6A")>
<InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
Friend Interface IStorageItemHandleAccess
Function Create(ao As Int32, so As Int32, o As Int32, oploc As Int32,
ByRef ptrHandle As IntPtr) As IntPtr
End Interface
' 在您的函数中只需 2 行额外代码即可获得神奇的 HANDLE!
Dim storageHandleIface = DirectCast(file, IStorageItemHandleAccess)
Dim myfileHandle As IntPtr
Dim res = storageHandleIface.Create(&H120116, 2, 0, 0, myfileHandle) ' WindowsStorageCom.h