Short answer for Windows users without any programming skills
Running an executable with one (or more) directory/file name(s) passed as argument(s) to the executable via a shell context menu item opened by right clicking on a directory or file (on right side of a Windows File Explorer window) results in starting the executable with current working directory being set for this executable with
- the directory containing the clicked directory/file on no registry value
NoWorkingDirectory
present
or
- the directory
C:\Windows\System32
or more precisely %SystemRoot%\system32
with the registry value NoWorkingDirectory
present in Windows registry.
Many not good coded executables and scripts require the first variant with current working directory being set to the directory containing the directory or file to process. That is the reason why the first variant is the default.
In some cases the first variant causes an unwanted behavior like on running cmd.exe
to process a batch script which gets passed the clicked directory/file name as argument and the directory/file is referenced using its UNC path.
The second variant with NoWorkingDirectory
present in the Windows registry can be used for all really good coded executables and scripts.
Long answer for Windows users and programmers interested in details
The Windows kernel library contains the function CreateProcess which is used by explorer.exe
and most other executables capable running another executable without or with a STARTUPINFO structure to start a Windows executable. One of the parameters of function CreateProcess
is lpCurrentDirectory
– a long pointer to the string with directory path to set as current working directory for the process to create. The pointer value can be also null to instruct CreateProcess
to use the current directory of the process calling CreateProcess
as current working directory for the process to create. Most executables call CreateProcess
with a null pointer for the function parameter lpCurrentDirectory
.
The Windows File Explorer (explorer.exe
) calls CreateProcess
with the directory path of the directory containing the directory/file on which the user clicked with secondary (usually right) pointing device (often mouse) button and clicked in opened context menu on the item resulting in starting an executable with the clicked directory/file name as argument.
The registry string value NoWorkingDirectory
changes the behavior on how explorer.exe
calls CreateProcess
regarding to function parameter lpCurrentDirectory
. The current directory is always the system directory of Windows with this registry string value present, i.e. the directory %SystemRoot%\System32
which on most Windows machines expands to C:\Windows\System32
.
That can be seen as follows:
Please open a command prompt window and run the following harmless commands:
reg add "HKCU\Software\Classes\Directory\shell\NoWorkingDirectoryTest" /ve /d "No working directory test"
reg add "HKCU\Software\Classes\Directory\shell\NoWorkingDirectoryTest\command" /ve /d "cmd.exe /D /C C:\Temp\DirTest\DirTest.cmd \"%V"\""
md "C:\Temp\DirTest"
echo @echo Current directory is: ^"%^CD%^">"C:\Temp\DirTest\DirTest.cmd"
echo @echo Batch file started with: %0 %*>>"C:\Temp\DirTest\DirTest.cmd"
echo @echo Command line used is: %^CMDCMDLINE%>>"C:\Temp\DirTest\DirTest.cmd"
echo @pause>>"C:\Temp\DirTest\DirTest.cmd"
The two reg
command lines add to Windows registry:
[HKEY_CURRENT_USER\Software\Classes\Directory\shell\NoWorkingDirectoryTest]
@="No working directory test"
[HKEY_CURRENT_USER\Software\Classes\Directory\shell\NoWorkingDirectoryTest\command]
@="cmd.exe /D /C \"C:\\Temp\\DirTest\\DirTest.cmd\" \"%V\""
The command md
and the four echo
command lines create the batch file C:\Temp\DirTest\DirTest.cmd
with the following command lines:
@echo Batch file started with: %0 %*
@echo Current directory is: "%CD%"
@echo Command line used is: %CMDCMDLINE%
@pause
Now start Windows File Explorer on not already running and browse on left side in folder tree to the directory C:\Windows\System32\drivers
. Click with the right mouse button on right side on the folder etc
and left click in the opened context menu on the item No working directory test just added before to the Windows registry.
The just before created batch file is executed displaying in a console window:
Current directory is: "C:\Windows\System32\drivers"
Batch file started with: C:\Temp\DirTest\DirTest.cmd "C:\Windows\System32\drivers\etc"
Command line used is: "cmd.exe" /D /C C:\Temp\DirTest\DirTest.cmd "C:\Windows\System32\drivers\etc"
The first output line shows the current directory set by CreateProcess
on starting cmd.exe
with the four arguments according to the string passed with lpCurrentDirectory
by the parent process explorer.exe
. It can be seen that the Windows File Explorer called CreateProcess
in this case with C:\Windows\System32\drivers
as current working directory path.
The second output line shows with which arguments the batch file was started including argument 0 which is the string used to reference the batch file as added to Windows registry.
The third line outputs how cmd.exe
itself was started by explorer.exe
respectively CreateProcess
. cmd.exe
although stored in the registry without surrounding "
is enclosed in "
on being started by explorer.exe
.
The registry string value NoWorkingDirectory
does not exist at the moment. That is the reason why the current working directory for cmd.exe
is set to C:\Windows\System32\drivers
which is the current directory of explorer.exe
on right clicking on right side on the folder etc
with currently active folder in Windows File Explorer being C:\Windows\System32\drivers
.
Now right click in Windows File Explorer on left side in folder tree on the directory C:\Windows
while the currently active folder is still C:\Windows\System32\drivers
and left click in context menu on the item No working directory test.
There is one more console window opened with displaying following lines:
Current directory is: "C:\WINDOWS\system32"
Batch file started with: C:\Temp\DirTest\DirTest.cmd "C:\Windows"
Command line used is: "cmd.exe" /D /C C:\Temp\DirTest\DirTest.cmd "C:\Windows"
The second and the third line are as expected. But the current directory is neither C:\Windows\System32\drivers
nor C:\
and also not C:\Windows
. So it can be seen that starting an executable with the directory containing a directory does not always work as expected when the user right clicks in folder tree on left side on a directory or a virtual shell folder.
There can be also seen that the current working directory path is not even the real directory path of the Windows system directory as in this case would be displayed C:\Windows\System32
and not C:\WINDOWS\system32
. Please note the differences in case of some letters. The Windows system directory path really used here is a concatenation of the registry value SystemRoot
under key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
which has the string value C:\WINDOWS
concatenated with fixed string \system32
. The real directory path is C:\Windows\System32
.
A batch file or executable or any other script designed for being executed by explorer.exe
or similar programs via a context menu item should always take into account that the current directory can be a completely different directory than the directory containing the passed directory/file name(s). The process calling CreateProcess
defines which directory is the current directory for the created process.
cmd.exe
has a special behavior on being started with current directory path being a UNC path. It changes the current directory in this case to %SystemRoot%
(Windows directory) and outputs the information:
\\ComputerName\SharedFolder\Resource
CMD.EXE was started with the above path as the current directory.
UNC paths are not supported. Defaulting to Windows directory.
That is done by cmd.exe
for downwards compatibility because of many executables are not running correct on current directory path not starting with a drive letter and a colon.
It is possible to run in a command prompt window:
reg add "HKCU\Software\Microsoft\Command Processor" /v DisableUNCCheck /t REG_DWORD /d 1 /f
That disables the Universal Naming Convention (UNC) check for command sessions and cmd.exe
accepts also a current directory with a UNC path.
Okay, back to registry value NoWorkingDirectory
. Execute in a command prompt window now:
reg add "HKCU\Software\Classes\Directory\shell\NoWorkingDirectoryTest" /v NoWorkingDirectory /t REG_SZ
There is added the registry string value NoWorkingDirectory
with no value. So the registry contains now:
[HKEY_CURRENT_USER\Software\Classes\Directory\shell\NoWorkingDirectoryTest]
@="No working directory test"
"NoWorkingDirectory"=""
[HKEY_CURRENT_USER\Software\Classes\Directory\shell\NoWorkingDirectoryTest\command]
@="cmd.exe /D /C C:\\Temp\\DirTest\\DirTest.cmd \"%V\""
Please note the additional third line missing in registry output posted above.
In Windows File Explorer right click on left side on directory C:\Windows
with currently active folder being still C:\Windows\System32\drivers
and left click on context menu item No working directory test exactly as done before. The output is again as before. So there is no change for this use case.
Right click next on right side in Windows File Explorer on the directory etc
in C:\Windows\System32\drivers
and left click on context menu item No working directory test. A console window opens showing the following lines:
Current directory is: "C:\WINDOWS\system32"
Batch file started with: C:\Temp\DirTest\DirTest.cmd "C:\Windows\System32\drivers\etc"
Command line used is: "cmd.exe" /D /C C:\Temp\DirTest\DirTest.cmd "C:\Windows\System32\drivers\etc"
The first line shows the important difference with the registry string value NoWorkingDirectory
present which is now C:\WINDOWS\system32
instead of C:\Windows\system32\drives
as before. The current working directory is now always the Windows system directory defined with %SystemRoot%\system32
.
It does not matter if NoWorkingDirectory
is added to registry without a string value or with a string value like C:\Windows
. It can be even added a registry value of type DWORD
with name NoWorkingDirectory
with value 0
or 1
. The registry value type of NoWorkingDirectory
and its value does not matter for the Windows shell (explorer.exe
). It only matters if there is a registry value of name NoWorkingDirectory
present or not in Windows registry under the key being used for the shell extension.
The added registry key and the batch file can be used for more analyzes like browsing to a network resource using a UNC path or right clicking on a virtual shell folder on left side in the folder tree. There can be also created in C:\Temp\DirTest
a directory with name Development & Test(!) 100%
and pass this folder name with full path to a batch file or executable or other script and see what happens. Many batch files fail to process correct an argument string like "C:\Temp\DirTest\Development & Test(!) 100%"
because of spaces and exclamation mark and round brackets and a percent sign although being a valid directory name consisting only of ASCII characters.
The registry key and the batch file as well as the created directory used to demonstrate the behavior should be deleted finally by executing the following commands in the command prompt window after closing all console windows opened by running DirTest.cmd
:
reg delete "HKCU\Software\Classes\Directory\shell\NoWorkingDirectoryTest" /f
del C:\Temp\DirTest\DirTest.cmd
rd C:\Temp\DirTest
rd C:\Temp
Note: Many of the properties of a shortcut file with file extension .lnk
define the values passed by Explorer to CreateProcess
via its function parameters and the structure STARTUPINFO
. For example the property Start in defines the string value to which lpCurrentDirectory
finally points to on making use of the shortcut file to start an executable.
A note for programmers:
- The C# Process class is a C# wrapper class for
CreateProcess
.
- The Java class ProcessBuilder is on Windows a Java wrapper class for
CreateProcess
.
- The Python subprocess module is on Windows a Python wrapper module for
CreateProcess
.
- The Windows Command Processor command
start
supports options which are all passed to CreateProcess
by cmd.exe
on using them like the option /D
which defines the string passed to CreateProcess
using the function parameter lpCurrentDirectory
.
Every programming and scripting language with support for running an executable on Windows has a function or class which calls on Windows CreateProcess
without or with a STARTUPINFO
structure.