Why does the common file save dialog create a temporary file and then delete it?

When you call GetSaveFileName, the common file save dialog will ask the user to choose a file name, and just before it returns it does a little create/delete dance where it creates the file the user entered, and then deletes it. What's up with that?

This is a leftover from the ancient days of 16-bit Windows 3.1, back when file systems were real file systems and didn't have this namby-pamby "long file name" or "security" nonsense. (Insert sound effect of muscle flexing and gutteral grunting.)

Back in those days, the file system interface was MS-DOS, and MS-DOS didn't have a way to query security attributes because, well, the file systems of the day didn't have security attributes to query in the first place.

But network servers did.

If you mapped a network drive from a server running one of those fancy new file systems, then you were in this case where your computer didn't know anything about file system security, but the server did. The only way to find out whether you had permission to create a file in a directory was to try it and see whether it worked or whether it failed with the error ERROR_ACCESS_DENIED (or, as it was called back in the MS-DOS days, "5"),

Another reason why a server might reject a file name was that it contained a character that, while legal in Windows, was not legal on the server. At the time, the most common reason for this was that you used a so-called "extended character" (in other words, a character outside the ASCII range like an accented lowercase e) which was part of your local code page but not on the server's.

Yet another possibility was that the file name you chose would exceed the server's path name limit. For example, suppose the server is running Windows for Workgroups (which has a 64-character maximum path name limit), and it shared out C:\some\deep\directory\on\the\server as \\server\share. If you mapped M: to \\server\share, then the maximum path name on M: was only about 30 characters because C:\some\deep\directory\on\the\server used up half of your 64-character limit.

The only way to tell whether the file could be created, then, was to try to create it and see what happens. After creating the test file (to see if it could), the common file save dialog immediately deleted it in order to cover its tracks. (This could lead to some weird behavior if users picked a directory where they had permission to create files but no permission to delete files that they created!)

This "test to see if I can create the file by creating it" behavior has been carried forward ever since, but you can suppress it by passing the OFN_NOTESTFILECREATE flag.

Comments (29)
  1. Lockwood says:

    I created a test comment to see if I had write permission to the MSDN Blog comments area.

    I cannot delete the test comment, however.

  2. Joshua says:

    The documentation used to read "set this flag if operating on a create no modify network share" as though I the programmer were psychic.

  3. RRR says:

    So, if it's useless, why not suppress it by default or, even better, deprecate the damned thing?

  4. GWO says:

    "Suppose the server is running Windows for Workgroups (which has a 64-character maximum path name limit)"

    512 Bits should be enough for everyone…

  5. Dan Bugglin says:

    @Lockwood Fortunately, you were able to modify the comment to have the content you were going to put in the new comment anyway.

    @steveg By NOT passing the flag your program can be (mostly) sure that you will be able to write to the file.  By not passing it, you have to take some responsibility there, although the dialog may still do some other checks I suppose.

    @RRR Legacy program support, yay.  Also, if it ain't broke, don't fix it.

  6. ErikF says:

    @RRR: It's not useless because you can still have conditions where a file can't be created for writing (write-only media, lost network connectivity, etc.) The documentation discusses those conditions but they seem to be worded as afterthoughts; see msdn.microsoft.com/…/ms646839(v=vs.85).aspx as an example.

    Whether the function should do this is a separate question of course, as you could still be unable to write to the file even after you've been told that everything's good. (Moral of the story: don't assume anything when programming!)

  7. Adam Rosenfield says:

    I'm sure there's probably some legacy program somewhere that relies on this behavior of creating and deleting the test file, and that program will break if the default behavior were changed to behave as if OFN_NOTESTFILECREATE were always specified.

  8. Anon says:


    Nothing in the Windows UI is ever deprecated or removed unless the existence of it can be shown to positively affect workflow.

  9. Azarien says:

    I see a racing condition where GetSaveFileName creates the file, deletes it, returns success, and suddenly your permission to create that file is revoked.

    You still have to handle all sorts of possible errors. Which makes that creation-deletion part rather pointless.

  10. Gabe says:

    If they removed the automatic check for writability, it's unlikely that any programs will break. Most likely it will be the users who complain.

    Imagine you're using a web browser and ask to download a large file. As soon as the download starts you inadvertantly tell it save it to your Apps share rather than your Home share. Then an hour later the download completes and the browser goes to copy the file from its cache to the place you specified, only you specified a read-only share.

    You can easily imagine a user saying "Why couldn't it tell me that I picked an invalid location BEFORE spending an hour downloading it? Stupid computer!", and obviously somebody who frequently makes that mistake will suffer most from not doing the test.

  11. Karellen says:

    @Gabe: Huh. My browsers save downloads to the directory you tell them to save in. ISTR that some add an extra ".part" extension initially so that indexers and document viewers don't bother trying to access an incomplete file, but others just use the actual file name.

    On the other hand, if you're spending an hour downloading the file to one place before saving it to another, the "quota fills up"/"permissions get revoked" window for race conditions increases significantly.

  12. alegr1 says:

    >Then an hour later the download completes and the browser goes to copy the file from its cache to the place you specified, only you specified a read-only share.

    Thanks goodness IE doesn't do that stupidity anymore. Who ever thought that's a good idea? But even that fix didn't hold me from giving up on IE.

  13. Jonathan says:

    I suppose the idea was that if the check fails, the user is back in the dialog when he can choose another folder. Yes, you could achieve that with application code even without the check:

    ..while(true) {

    ….string fileName = GetSaveFileName(…);

    ….if (MySave(fileName)) break;


    However, having the check inside GetSaveFileName() means that it saves its state, and also simplifies the application code:


    A good application developer should still use the former because of race/other conditions mentioned above, but I suppose this improves the user's experience in applications developed by less-than-good developers.

  14. steveg says:

    "But you *can* suppress it". Is that "can" or "should"?

  15. Jaime says:

    This remind me of a bug in Excel 5. For some reason we had a folder on a NetWare file server configured to allow writes, but not renames. Users kept complaining that they couldn't find their spreadsheets. Upon investigation, we found a bunch of randomly named files that turned out to be the missing spreadsheets. It seems that Excel was performing a "Save As" by saving with a random file name and then renaming the file after the save was complete. Apparently, there was no error checking on the rename step, presumably because the Excel team hadn't considered the case where a file could be created but not renamed.

  16. Karellen says:

    Yeah, I think I'm with ErikF, when I still don't see the *point* of this.

    Why not just let the user pick a filename, and let the application handle the error if it can't write the file? Given that the app needs to do this anyway, e.g. if the permissions change between the save dialog doing its dance and the application actually starting to write, or if there's only 1Mb left on the disk/in the user's quota, and they try to write a 5Mb file, or if the network goes down part-way through, or… if there's any one of a bunch of other errors that pop up.

    I can't see how this behaviour saves an application developer any work at all. So why bother?

  17. Ray says:

    @Jaime: Excel 2003 still does this and I'm guessing it's still part of Excel 2013.


  18. Killer{R} says:

    Absolutely useless feature. Application cannot rely on fact that save dialog succeed. Fact that comdlg could create its test file doesn't mean automatically that application will succeed too in saving its file, cause except permissions there're numerous reasons why this operation can fail: disk space can be near-to-exceed, so test file will be created but application's file will not, another application can create same file at same moment, administrator can change permissions at same moment, server can go shutdown etc. So in any case application need to have functionality to detect and report errors itself, so creating this test file from save dialog's code absolutely redundant and can gives troubles than benefits.

  19. a=a says:

    >Why does the common file save dialog create a temporary file and then delete it?

    Because that's the way it was programmed!

  20. ErikF says:

    @Mirinth: IMO, for normal uses of files the easiest way to deal with permissions is still to ignore them and handle errors as they occur; there's usually very little difference as far as my programs are concerned between permissions and the multitude of other reasons for failure.

  21. Mirinth says:

    I think the race condition is distracting from the real problem:

    "…and MS-DOS didn't have a way to query security attributes because, well, the file systems of the day didn't have security attributes to query in the first place."

    DOS programs *never* checked for permissions because they *couldn't* check for permissions. Then all of a sudden Windows 3.1 threw them into a world of permissions, and all the programs that weren't written by psychic programers suddenly had nasty bugs lurking in them.

    It isn't a perfect solution, but it makes the problem window a lot smaller, so it's still worthwhile.

  22. 640k says:

    The dialog magic and any subsequent write isn't perfomed in a transaction. Useless feature, which cannot guarantee anything at all.

  23. Mirinth says:

    @ErikF: I agree, but throwing servers into the mix added new error scenarios, and I doubt the programmers thought to check for ones that didn't exist yet.

    A well written program would have had a default case for unknown response codes, but then what do you do in your unknown response code handler? The code might be a new kind of success, or a notice that something was only partially done and needs to be either completed or undone to put the system back in a consistent state. How do you handle the unknown case when doing nothing isn't an option? I don't think you can.

    There's also the problem of telling the user that something went wrong. When you get an unknown error, the best you can do is tell the user that something went wrong, you have no idea how to handle it, and maybe give them the unexpected data so they can try to figure it out for themselves. But now you've got a user who's upset because the program they need to do their job isn't working, who can't fix it because they can't figure out what happened, and who can't even figure out what happened without a call to tech support. Most of them probably don't have internet access either, so no searching Google for help from other people who've already dealt with the problem.

    Windows knows about the error situations though, so it could try to detect and prevent them and make the old programs more likely to keep working in their new environment. I still don't know if it's the *ideal* solution, especially considering that race condition, but it was better than letting even the well written programs serve up generic error messages on a regular basis.

    Especially when your business model is centered on keeping old programs running at nearly any cost so users will keep buying your new operating system even if they don't see an immediate advantage yet.

  24. @Mirinth says:

    You highly overcomplicate this case. You let the common dialog give you the filename. Then you call CreateFile. Any return code other tban 0 is an error, and you have to show the user the text that GetLastError & FormatErrorMessage will return.

    Easy enough, if you ask me.

  25. Gabe says:

    Wow, it seems that lots of people here are incapable of looking at this problem through user-colored glasses. Or maybe they're just the sort of people who think condoms are useless because they're not 100% effective — if they can fail, you need some alternate form of birth control anyway, so why bother?

    You could make a similar argument about airlines checking passports on international flights. An airline will probably not let you board a flight without a valid passport because it's unlikely the destination country will let you in. Of course, even with a valid passport the country may not let you in, but is that a reason for the airline checks to be useless?

    The whole point of this feature is to fail fast. Would you rather have the program close the "Save" dialog box, generate the file to write, attempt to create the file, put up an error message, and then show the "Save" dialog again? Or would you prefer that it just tell you immediately that it's not going to work?

  26. @Gabe says:

    Ent against tbe current design (fail fast), but would work for any possible case.

  27. disk editor next? says:

    GetSaveFileName shouldn't touch or interact the file system in this way. It should only be a convenient way of creating a full path string in a gui. It is, and should be, a fancy editbox. Not a file system manager or low level inspection tool.

  28. Mirinth says:

    "You highly overcomplicate this case. You let the common dialog give you the filename. Then you call CreateFile. Any return code other tban 0 is an error, and you have to show the user the text that GetLastError & FormatErrorMessage will return."

    I forgot about GetLastError, and didn't even know about FormatErrorMessage. Shows how much I use C… You're right, that does simplify things a lot as long as Windows will provide the appropriate error message, and that's certainly doable.

    @Gabe: That's about what I was trying to say (I think you said it better though). As nice as it would be if every program was well written, a lot of them aren't. And the ones that aren't will cause undue trouble for the user. Windows can't fix the problem for everyone everywhere, but it can solve it for a lot of people, so it's still worthwhile even if it doesn't always work.

    Users can't see your code. They don't care if your program is well written or not. It can be written as frighteningly badly as possible and still be popular as long as it works.

    [Um, GetLastError did not exist in 16-bit Windows 3.1. -Raymond]
  29. Joshua says:

    [Um, GetLastError did not exist in 16-bit Windows 3.1. -Raymond]

    It was called WSAGetLastError then.

Comments are closed.