Question

How can I retrieve the current working directory of cmd.exe?

This seems possible. For example using ProcessExplorer, select CMD.exe, right click, properties, Image tab, "Current Directory" relects the directory set using the CD or CHDIR commands.

I've looked at the .NET Process and ProcessStartInfo classes (ProcessStartInfo.WorkingDirectory always returns "") and can't seem to find a way of determining this. Nothing at PInvoke stands out either.

As an example I'm looking to programmatically be able to say something like: Process.GetCurrentWorkingDirectory(processID) where processID is a Windows process ID of another running process.

Is there any solution, WinAPI or .NET?

[Update]

Reason for asking this question:

I've used the "Command Prompt Explorer Bar" for a while and it's great except if I "CD" to a new directory, the current Explorer window does not also change. (ie the Sync is only 1 way from Explorer to the commmand prompt). I'm looking to make this 2 way.

Was it helpful?

Solution

Untested, a possible approach:

Create a DLL with a DllMain that uses GetThreadStartInformation() to find the address of the buffer, and then uses GetCurrentDirectory to populate it. This should be OK, because both of those functions are in kernel32, which is always present. You will need to have some structure there to return success/failure.

  1. Get a handle to the cmd.exe process.
  2. Allocate some memory there (VirtualAllocEx)
  3. Put the path to your DLL in the memory. (WriteProcessMemory)
  4. Load your dll into the cmd.exe address space. (CreateRemoteThread with an entry point of LoadLibrary, the argument is the memory you allocated earlier.)
  5. WaitForSingleObject followed by GetExitCodeThread(), gives you the HMODULE of your DLL in the cmd.exe process.
  6. ReadProcessMemory to get the current directory.
  7. Unload your dll from the cmd.exe address space. CreateRemote Thread with an entry point of FreeLibrary, the argument is the HMODULE.
  8. WaitForSingleObject to wait for the DLL to unload.

Broad sketch: Details left as an excercise! Risks: Allocates memory in the cmd.exe address space, changes its state. Care must be taken with the functions called in DllMain.

OTHER TIPS

Do you mean the %CD% variable in a batch file ?

Like this:

set OLDDIR=%CD%
.. do stuff ..
chdir /d %OLDDIR% &rem restore current directory

Try echo %CD% in a command prompt. :)

Well as this is what you need, there here is a PowerShell function to do it:

$(get-location)

Hope this helps.

I found it all from here.

Maybe this forum entry on the Sysinternals Forum contains a hint to the solution. Look for this in the GetProcessStrings function:

// Get Command Line Block

// At offset 0x00020498 is the process current directory followed by

// the system PATH. After that is the process full command line, followed

// by the exe name and the windows station it's running on.

This CodeProject article "Read Environment Strings of Remote process" could be useful too.

UPDATE: This is not the solution, see the comments to this answer: "As Janm said .Modules[0].FileName (or MainModuile.FileName) gives the location of the executable running in that process. I'm looking to find the current working directory (that can be changed using the CD or CHDIR commands)."

You could use System.Diagnostics Namespace. Here an example as C# console application. From the filename you can easily extract the Path information (System.IO.Path...).

You would make sure to have the permissions (run as admin) to do this.

Hope this helps. Here is the working code (tested):

using System;
using System.Diagnostics;
using System.IO;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Process[] procList =  Process.GetProcessesByName("cmd");

            string sFileName;

            for (int i = 0; i < procList.Length; i++ )
            {
                Console.Write(procList[i].Id);
                Console.Write(" ");

                try
                {
                    sFileName = procList[i].Modules[0].FileName;
                    Console.Write("(");
                    Console.Write(Path.GetFileName(sFileName));
                    Console.Write("): ");
                    Console.WriteLine(Path.GetDirectoryName(sFileName));
                }
                catch (Exception ex)
                {
                    // catch "Access denied" etc.
                    Console.WriteLine(ex.Message);
                }


            }

        }
    }
}

Here the the output on my machine (I've opened four command lines):

alt text http://img236.imageshack.us/img236/3547/processworkingdirvn4.png

Try this simple environment property:

Environment.CurrentDirectory()

See my answer to a similar question (by myself). I wrote a command line utility and C# wrapper to read the process environment variables. For my question (getting current dir for java), I simply read the catalina_base directory.

I'm not sure if this applies directly to cmd.exe. The utility provided in the Code Project article failed to work with cmd.exe.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top