0

We have several Windows 8 Store C++ apps that need to maintain configuration and data files.

Files are written in subfolders of Windows::Storage::ApplicationData::Current->LocalFolder. Example:

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

In Windows 8.1 we have received a few reports from users that say state isn't remembered between app invocations. Upon closer inspection the files are not created (the subfolders are indeed created, but there are no files inside them)

Notes:

  1. Subfolders are created using CreateDirectory(), files are created using fopen()

  2. Files are created/opened using absolute paths

  3. This always worked under Windows 8.0 and the code has not been changed since. In fact, one of our user reports stated that the app saved files fine under Windows 8.0, but stopped saving after the user upgraded to Windows 8.1.

  4. We have not been able to replicate the issue locally using Windows 8.1. We're not sure how common this failure is, but we estimate that most users are unaffected. Affected users do not appear to have any special hardware/software configuration.

  5. If a user is affected, then files are consistently never saved, even after retrying or uninstalling and re-installing the app (i.e., it's not a case of intermittent failure)

  6. It's hard to get error information given (i) the rarity of the issue (ii) the fact that the logs that would reveal this are by definition not saved, and (iii) the apps don't require internet connectivity so there is no alternative communication channel.

Can anyone think of any reason why this might fail under Windows 8.1?

Xaxx
  • 127
  • 11
  • `errno` / `GetLastError()` ? But do report this to Microsoft, they still have employees who care about such regressions. – MSalters Nov 14 '13 at 01:35
  • @MSalters: It's hard to get error information given (i) the rarity of the issue (ii) the fact that the logs that would reveal this are by definition not saved, and (iii) the apps don't require internet connectivity so there is no alternative communication channel. A solution would be to instrument the builds specifically to somehow trap/report this error, but I am hesitant to do this on live builds for rather obvious reasons :) – Xaxx Nov 14 '13 at 08:51
  • A wild guess: Do your filenames contain non-ascii characters? – SigTerm Nov 15 '13 at 10:41
  • @SigTerm: No, just standard 7-bit ASCII. For example: CI3.log, CI3.cfg, CI3.pro – Xaxx Nov 15 '13 at 13:24
  • @Xaxx: Are there non-ascii characters in path to appdata? I'm asking because CreateDirectory has unicode version, but fopen takes char. Anyway, on machine with a problem you can monitor calls using something like process monitor. You could instruct user with a problem to do that and send you a log. Also, if I were you, I'd try to abstract away from OS-specific calls using something like boost or Qt. That might work. – SigTerm Nov 15 '13 at 16:49
  • @SigTerm: Excellent catch. It is in fact the user name (which forms part of the %LOCALAPPDATA% path) which uses extended ASCII chars. I have contacted the end users for confirmation. In the meantime, if you'd like to add an official answer, I'd be glad to accept it. – Xaxx Nov 18 '13 at 21:23
  • @Xaxx: I've added the answer. – SigTerm Nov 19 '13 at 11:12

2 Answers2

1

Are there non-ascii characters in path to appdata? CreateDirectory has unicode version, but fopen takes const char* strings as argument.

If I were you, I'd try to abstract away from OS-specific calls using something like boost or Qt. That should work, because Qt uses unicode string for opening files and Boost should have something similar (unsure about this one).

Also on windows compiler _wfopen may be present. It is the same as fopen, but takes wchar_t strings as argument. It should work for you, but you'll need a few ifdefs here and there.

You could also try setting current directory with function that supports unicode and then calling fopen, but I wouldn't call it a "clean" solution.

Anyway, when you run into problem that is related to system calls, then on machine with a problem you can monitor calls using something like process monitor. You could instruct user with a problem to do that and send you a log.

SigTerm
  • 26,089
  • 6
  • 66
  • 115
0

Why don't you use the Windows.Storage classes to work with filesystem? WinRT is recommended way to work with IO not legacy C API. I believe it is more robust approach and you could get more info about the cause from WinRT exception rather than from an unknown failure of old API.

ixSci
  • 13,100
  • 5
  • 45
  • 79
  • 2
    It's recommended _by Microsoft_, as they benefit if your application is tied to Windows. My interests include to have portable programs, which is entirely the opposite. – MSalters Nov 14 '13 at 01:33
  • @MSalters, it is new API and it is supposed to be used if you want to have maintainable soft. No one can guarantee that in, say, windows 8.2 fopen and streams will be abandoned at all. Like getenv and _beginthreadex were. And if you are developing cross-platform apps you should have known already that you need an abstraction around many of the system specific APIs. – ixSci Nov 14 '13 at 04:12
  • Our file-handling code base is shared between Windows (desktop), Linux, Mac, iOS, Android, Windows Phone, and Windows (RT), so we use the legacy C API to keep things as common/maintainable as possible. – Xaxx Nov 14 '13 at 08:57
  • @ixSci: No version of Windows has `fopen`. It's a CRT function. Similarly, `` is a C++ abstraction, and any platform which claims to support C++ must support streams. In theory Microsoft could decide to drop MSVC++ tomorrow, but that's about as unlikely as them suddenly embracing Java. `getenv` is not abandoned for the same reason. `_beginthreadex` is NOT a standard C function, hence the underscore. C++ has `std::thread`, which probably is an abstraction around `_beginthreadex`. – MSalters Nov 14 '13 at 09:53
  • @MSalters, I know what I'm talking about. `getenv` is NO MORE in CRT for windows 8.1 apps. And I don't see why they can't just drop fopen the same way. – ixSci Nov 14 '13 at 09:56
  • 1
    @ixSci: Then we're no longer talking about a C Run Time. It's that simple: ISO/IEC SC22 WG14 decides what must be in the C Run Time, and Microsoft may not remove things unilaterally. They may _add_ functions, using reserved names (hence the underscore in `_beginthreadex`). – MSalters Nov 14 '13 at 10:25
  • @MSalters, what is the difference for me as a programmer of the name? There is the fact: you don't have `getenv` in Windows 8.1 Store applications. You can't create application which uses it. And if you have used Visual Studio you should know that it didn't support C99. And never did. Yet the library you link is called *CRT. – ixSci Nov 14 '13 at 10:36
  • @ixSci: Well, MSVC is a C++ compiler, not a C99 compiler, so I don't blame them for that. As for the lack of C++ support on Windows 8.1, well, who cares about Windows 8.x anyway? Microsoft has got reasonable support for C++11 on Windows 7, and I expect the same for Windows 9. Microsoft has always wavered like that; consistent vision is not their forte. – MSalters Nov 14 '13 at 11:08