Why does the common file dialog change the current directory?


When you change folders in a common file dialog, the common file dialog calls Set­Current­Directory to match the directory you are viewing. (Don't make me bring back the Nitpicker's Corner.)

Okay, the first reaction to this is, "What? I didn't know it did that!" This is the other shoe dropping in the story of the curse of the current directory.

Now the question is, "Why does it do this?"

Actually, you know the answer to this already. Many programs require that the current directory match the directory containing the document being opened.

Now, it turns out, there's a way for you to say, "No, I'm not one of those lame-o programs. I can handle current directory being different from the document directory. Don't change the current directory when using a common file dialog." You do this by passing the OFN_NO­CHANGE­DIR flag. (If your program uses the IFile­Dialog interface, then NO­CHANGE­DIR is always enabled. Hooray for progress.)

But now that you know about this second curse, you can actually use it as a counter-curse against the first one.

If you determine that a program is holding a directory open, and you suspect that it is the victim of the curse of the current directory, you can go to that program and open a common file dialog. (For example, Save As.) From that dialog, navigate to some other directory you don't plan on removing, say, the root of the drive, or your desktop. Then cancel the dialog.

Since the common file dialog changes the current directory, you have effectively injected a Set­Current­Directory call into the target process, thereby changing it from the directory you want to remove. Note, however, that this trick works only if the application in question omits the OFN_NO­CHANGE­DIR flag when it calls Get­Save­File­Name.

In Explorer, you can easily call up a common file dialog by typing Win+R then clicking Browse, and in versions of Windows up through Windows XP, Explorer didn't pass the OFN_NO­CHANGE­DIR flag.

Comments (26)
  1. Alex Grigoriev says:

    OFN_NOCHANGEDIR didn't have effect for GetOpenFileName through XP. This, it was pointless to pass it to the function.

    Only GetSaveFileName supported it.

  2. Dan Bugglin says:

    I thought cancelling the dialog reverted the current directory… no?

  3. Henke37 says:

    Then it would have to track the previous directory. That might have disappeared since it was read. So not only is it work, it has a case where it can't work.

  4. Joshua says:

    @Alex: my testing says otherwise; however if this behavior is sometimes the case this would explain some bizarre behavior we get in the field very nicely.

  5. Yuri Khan says:

    Win+R will only affect the root explorer.exe process. People who customarily use flaky shell extensions are likely to have their folders opened in separate processes.

  6. wpfcoder says:

    In the managed world, there is something interesting.

    in the class System.Windows.Forms.FileDialog, there is a property 'RestoreDirectory', which works fine.

    but, for WPF coders, we dont like to call into the WinForms assembly, so microsoft has a new class for us:

    Microsoft.Win32.FileDialog, it has a 'RestoreDirectory' property too, BUT, as the MSDN document states: 'This property is not implemented ' !!! WHY OH WHY !!!

    [Read the fifth paragraph of my article. -Raymond]
  7. Wizou says:

    I will repeat my comment from the other post:

    When you specify OFN_NOCHANGEDIR, GetOpenFileName still changes the current directory while it is running. The only difference is that this flag restores the previous current directory when the function exits.

    This means that in a multi-thread application, you must be careful not to use relative paths in your other threads while GetOpenFileName is running.

  8. asdbsd says:

    @Dan Bugglin: Thought so too (at least that's how it felt).

    @Henke37: They don't have to change the current directory until you confirm your selection. And even if they by some chance did, they might have decided to at least try to revert it back, because your scenario is rare.

    @Yuri Khan: Can't those people just close all the explorer windows? The problem with main explorer is that it's shell.

  9. Michael Mol says:

    @Yuri in that case, it's trivial for them to close those additional windows.

  10. wpfcoder says:

    @Raymond

    NO. WPF is not a Vista/7 only framework, it runs in XP SP3 !

    And actually I discovered this while debugging, it did change the current directory in XP, and no way to prevent that behavior.

    [I stand corrected. But it seemed a reasonable guess. -Raymond]
  11. Nitpicker says:

    This is the correct behavior. Problem is with common dialogs in apps that load a hardcoded last dir like MS Paint does.

  12. pcooper says:

    I can see how the dialog might need to set the current directory when the file is actually selected to open, but why does it set the directory while browsing? I'm guessing that Windows 3.1 did something like that in its common open dialog, and this is maintaining compatibility with that for some reason.

  13. Maurits says:

    why does it set the directory while browsing?

    One potential reason… so that the user can Cancel and have subsequent incarnations of the document go back to the same directory.

  14. wpfcoder says:

    @Raymond

    Sorry. I must correct myself here. I ran into that problem long ago and now I did some new tests, my findings are different this time.

    RestoreDirectory does set the OFN_NOCHANGEDIR flag.

    The reason of my previous tests fails is that I tested using OpenFileDialog, it calls GetOpenFileName and this ignores the OFN_NOCHANGEDIR anyway.

    now the MSDN statement maybe misleading, it may intend to say something like : "you can't just set this to false and expect CurrentDirectory to change on Vista/7 because it never will, and, you can't just set this to true and expect CurrentDirectory to be reserved on XP if you are using OpenFileDialog", I dont know.

  15. John says:

    I don't understand this behavior.  If the program requires the current directory to be the same as the document directory, couldn't it just change it on its own?  I guess I just don't know the context under which the common file dialog was originally designed.  Was it an optimization to save the application developer the few extra lines of code required to set the current directory?  Was it due to some backward compatibility issues with previous Windows (or perhaps DOS) versions?

    [Older programs often assumed the current directory = the document directory. Especially the ones written before directories existed. I'm certain I wrote about this recently. Oh there, yeah, I wrote about it yesterday. -Raymond]
  16. Anonymous Coward says:

    "Why does it do this?" How about because it's the expected behaviour? For many users (at least those who came to 9x from 3.1+DOS) browsing around within the common dialogues was the equivalent of using the cd command. If the dialogue would not change the current directory the following undesired behaviour would result:

    1) If you change the current directory before running the program (using a shortcut or the cmd for example) and then use the open dialogue, it doesn't show the right directory.

    2) If you change to a different directory in an open or save dialogue, close it, and then at some later point bring up such a dialogue again, it would show the old (hence wrong) location.

    You could correct these flaws without changing the current directory, but I think it's very likely that other things would be slightly off, and you'd fix those, and then you would end up replicating pre-existing functionality.

  17. Joshua says:

    And some people wonder why other people try so hard to duplicate the open & save dialog boxes. :(

    I could write a long rambling tirade but I won't because it won't do any good anyway.

  18. John says:

    [Older programs often assumed the current directory = the document directory. Especially the ones written before directories existed. I'm certain I wrote about this recently. Oh there, yeah, I wrote about it yesterday. -Raymond]

    I understand that.  What I don't understand is that GetOpenFileName() was implemented AFTER those older programs were already written, so there was no backward compatibility to maintain.

    [Two reasons. (1) To make it easier to add common dialog support to those old applications. (2) Because it made the implementation of GetOpenFileName easier. -Raymond]
  19. 640k says:

    [Two reasons. (1) To make it easier to add common dialog support to those old applications. (2) Because it made the implementation of GetOpenFileName easier. -Raymond]

    Then why doesn't SHBrowseForFolder change current dir?

    [I leave answering this as an exercise for the reader. -Raymond]
  20. JonPotter says:

    Presumably the thousands of crucial applications still running around the world that were written before directories existed will never call SHBrowseForFolder.

  21. Christian says:

    Funny, that over in the "virtualdub.org-Blog", phaeron just covered the same topic:

    virtualdub.org/…/entry.php

    Then why doesn't SHBrowseForFolder change current dir?

    I wish it would! It's so annoying to have to repeatedly navigate to the same folder. At least the normal Open and save dialogs allow you to just paste after using copypath in a proper filemanager like Total Commander.

  22. Georg Rottensteiner says:

    @Christian:

    If your app needs to reuse the last folder it's your app that needs to say so (ie. pass the wanted start directory to GetOpen/SaveFilename and SHBrowseFolder). It is quite annoying to do for SHBrowseForFolder though.

  23. Miral says:

    The lack of a type-in-path box in the SHBrowseForFolder has long been the bane of my existence.  (Or one of them, anyway.)  It's particularly annoying because the API does support using an edit box (by passing the BIF_EDITBOX flag; IIRC BIF_NEWDIALOGSTYLE does it too) — it's just that most programs that use it fail to do so.  (I recognise that this is a failure on the part of the applications, rather than the API, and changing the default would lead to Complications, but it'd be nice if there were a global policy setting or shim I could apply that forced all apps to show the box regardless of whether the app wanted it or not.)

  24. asdbsd says:

    @JonPotter: Same is true for GetOpenFileName, isn't it?

    I suppose the answer is "it was just done this way".

  25. Richard Russell says:

    @Miral: BIF_EDITBOX is a version 4.71 or later flag only, so it's hardly surprising so few programs use it.

  26. Gabe says:

    Richard Russell: Version 4.71 was released with IE4.0, which was over 13 years ago. I find it hard to imagine that there's so much software written before IE4.0 was common.

Comments are closed.