WPD API - 无法从设备传输内容(包括 SSCCE)

WPD API - Cannot transfer content from device (SSCCE included)

我需要枚举 MTP android 设备的内容并将文件从设备传输到 Windows PC。

按照此处找到的指南 Transferring Content from a Device to a PC 我试图将一个简单的文本文档传输到指定目录。但是,输出文件 始终 为空,即使返回值表明 X number of bytes have been written.

我仅使用推荐的 Windows API 调用创建了一个 SSCCE,以便轻松重现该问题。我使用了 API 文档和 official sample project 作为参考。

main.cpp

Qt project file

为了测试,我有一个 android phone 通过 MTP 连接到根文件夹 testFolder 并且里面有一个文件 testfile.txt 与文本hello world。在 运行 此应用程序上,输出表明已写入 11 个字节,但文件为空。请亲身体验一下?

我似乎无法理解为什么文件总是空的。有什么想法吗?

感谢您的宝贵时间。

  hr = SHCreateStreamOnFile(strOriginalFileName, STGM_CREATE|STGM_WRITE, &finalFileStream);

它通常有助于识别常见的编码模式。无论何时创建文件,都必须始终关闭该文件。在 C 语言中你有 fopen(),你必须调用 fclose()。在你有 CreateFile() 的 winapi 中,你必须调用 CloseHandle()。即使在许多资源管理是自动的运行时环境中,如 .NET,当您创建 FileStream 时,您也必须调用 Close() 或使用 using 语句。

代码没有明确关闭 finalFileStream

那是有后果的,你找到了。如果没有内存泄漏,SHCreateStreamOnFile 的实现不知道何时将任何缓冲但尚未写入文件的数据刷新。所以你最终得到一个没有内容的文件。

任何接口指针(如 IStream)的约定是您始终必须显式调用其 Release() 函数。请注意,代码忘记为它使用的 all 接口指针始终如一地执行此操作。不是唯一的问题,当您调用 CoInitialize/Ex() 时,您必须调用 CoUninitialize()。只需使用黄金法则,您始终必须在这样的代码中明确清理。

修复:

  hr = StreamCopy(finalFileStream, ...);
  if (FAILED(hr)) saysomething(hr);          // Forgotten in original code
  finalFileStream->Release();                // Now it is good.

您可以在 C++ 中使用智能指针类型 CComPtr<> 来自动完成它。