【问题标题】:Windows Store C++ apps cannot create files using fopen() under Windows 8.1Windows Store C++ 应用程序无法在 Windows 8.1 下使用 fopen() 创建文件
【发布时间】:2013-11-13 16:11:38
【问题描述】:

我们有几个需要维护配置和数据文件的 Windows 8 应用商店 C++ 应用。

文件被写入Windows::Storage::ApplicationData::Current->LocalFolder 的子文件夹中。示例:

C:\Users\<username>\AppData\Local\Packages\<packagename>\LocalState\SubFolder1\SubFolder2\data.txt

在 Windows 8.1 中,我们收到了一些来自用户的报告,称在应用调用之间没有记住状态。仔细检查后,文件没有创建(确实创建了子文件夹,但其中没有文件)

注意事项:

  1. 使用CreateDirectory()创建子文件夹,使用fopen()创建文件

  2. 使用绝对路径创建/打开文件

  3. 这在 Windows 8.0 下始终有效,此后代码未更改。事实上,我们的一份用户报告称,该应用在 Windows 8.0 下可以正常保存文件,但在用户升级到 Windows 8.1 后停止保存。

  4. 我们无法使用 Windows 8.1 在本地复制该问题。我们不确定这种故障有多普遍,但我们估计大多数用户都没有受到影响。受影响的用户似乎没有任何特殊的硬件/软件配置。

  5. 如果用户受到影响,则文件始终不会保存,即使在重试或卸载并重新安装应用程序之后(即,这不是间歇性故障)

  6. 很难获得错误信息,因为 (i) 问题的罕见性 (ii) 显示此问题的日志未保​​存,以及 (iii) 应用程序不需要互联网连通性,因此没有替代的通信渠道。

谁能想到在 Windows 8.1 下这可能会失败的任何原因?

【问题讨论】:

  • errno / GetLastError() ?但是请务必向微软报告,他们仍然有员工关心这种回归。
  • @MSalters:很难获得错误信息,因为 (i) 问题的罕见性 (ii) 显示此问题的日志根据定义未保存,以及 (iii) 应用程序不需要互联网连接,因此没有替代的通信渠道。一种解决方案是专门检测构建以某种方式捕获/报告此错误,但出于相当明显的原因,我对在实时构建中执行此操作犹豫不决:)
  • 一个疯狂的猜测:你的文件名是否包含非 ascii 字符?
  • @SigTerm:不,只是标准的 7 位 ASCII。例如:CI3.log、CI3.cfg、CI3.pro
  • @Xaxx:appdata 的路径中是否有非 ascii 字符?我问是因为 CreateDirectory 有 unicode 版本,但 fopen 需要 char。无论如何,在有问题的机器上,您可以使用进程监视器之类的东西来监视呼叫。您可以指示有问题的用户执行此操作并向您发送日志。另外,如果我是你,我会尝试使用 boost 或 Qt 之类的东西从特定于操作系统的调用中抽象出来。这可能行得通。

标签: c++ windows-store-apps windows-8.1 winapp


【解决方案1】:

appdata 的路径中是否有非 ASCII 字符? CreateDirectory 具有 unicode 版本,但 fopen 将 const char* 字符串作为参数。

如果我是你,我会尝试使用 boost 或 Qt 之类的东西从特定于操作系统的调用中抽象出来。这应该可行,因为 Qt 使用 unicode 字符串打开文件,而 Boost 应该有类似的东西(不确定这个)。

Windows 编译器上也可能存在_wfopen。它与 fopen 相同,但将 wchar_t 字符串作为参数。它应该对你有用,但你需要一些ifdefs 在这里和那里。

您也可以尝试使用支持 unicode 的函数设置当前目录,然后调用 fopen,但我不会称其为“干净”的解决方案。

无论如何,当您遇到与系统调用相关的问题时,在出现问题的机器上,您可以使用process monitor 之类的东西来监控调用。您可以指示有问题的用户执行此操作并向您发送日志。

【讨论】:

    【解决方案2】:

    为什么不使用Windows.Storage 类来处理文件系统? WinRT 是使用 IO 而非传统 C API 的推荐方式。我相信这是一种更强大的方法,您可以从 WinRT 异常而不是从旧 API 的未知故障中获得有关原因的更多信息。

    【讨论】:

    • 它是 Microsoft 推荐的,因为如果您的应用程序绑定到 Windows,它们会受益。我的兴趣包括拥有可移植的程序,这完全相反。
    • @MSalters,它是新的 API,如果您想拥有可维护的软件,应该使用它。没有人可以保证在 Windows 8.2 中 fopen 和流将被完全放弃。就像 getenv 和 _beginthreadex 一样。如果您正在开发跨平台应用程序,您应该已经知道您需要围绕许多系统特定 API 进行抽象。
    • 我们的文件处理代码库在 Windows(桌面)、Linux、Mac、iOS、Android、Windows Phone 和 Windows (RT) 之间共享,因此我们使用旧版 C API 将内容保持为尽可能通用/可维护。
    • @ixSci:没有任何版本的 Windows 具有 fopen。这是一个 CRT 功能。同样,&lt;iostream&gt; 是 C++ 抽象,任何声称支持 C++ 的平台都必须支持流。从理论上讲,微软明天可能会决定放弃 MSVC++,但这与他们突然拥抱 Java 一样不太可能。 getenv 并没有因为同样的原因被放弃。 _beginthreadex 不是标准的 C 函数,因此是下划线。 C++ 有std::thread,它可能是围绕_beginthreadex 的抽象。
    • @ixSci:那么我们不再谈论 C 运行时。就这么简单:ISO/IEC SC22 WG14 决定 C 运行时必须包含哪些内容,而微软可能不会单方面删除这些内容。他们可以添加函数,使用保留名称(因此_beginthreadex中的下划线)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-06
    • 2014-04-07
    • 1970-01-01
    相关资源
    最近更新 更多