获取cmd.exe的当前工作目录

时间:2008-10-20 09:59:48

标签: .net winapi directory cmd

如何检索cmd.exe的当前工作目录?

这似乎有可能。例如,使用ProcessExplorer,选择CMD.exe,右键单击,属性,图像选项卡,“当前目录”使用CD或CHDIR命令关联目录集。

我查看了.NET Process和ProcessStartInfo类(ProcessStartInfo.WorkingDirectory总是返回“”),似乎无法找到确定这一点的方法。 PInvoke的任何内容都不突出。

作为一个例子,我希望以编程方式能够说出类似:Process.GetCurrentWorkingDirectory(processID),​​其中processID是另一个正在运行的进程的Windows进程ID。

是否有任何解决方案,WinAPI或.NET?

[更新]

提出这个问题的原因:

我已经使用了“命令提示符浏览器栏”一段时间了,除非我将“CD”发送到新目录,否则当前的Explorer窗口也不会更改。 (即,从资源管理器到命令提示符只有1路同步)。我正在寻找这种方式。

6 个答案:

答案 0 :(得分:6)

未经测试,可能的方法:

使用DllMain创建一个DLL,该DLL使用GetThreadStartInformation()来查找缓冲区的地址,然后使用GetCurrentDirectory填充它。这应该没问题,因为这两个函数都在kernel32中,它始终存在。你需要在那里有一些结构才能返回成功/失败。

  1. 获取cmd.exe进程的句柄。
  2. 在那里分配一些内存(VirtualAllocEx)
  3. 将DLL的路径放入内存中。 (WriteProcessMemory的)
  4. 将dll加载到cmd.exe地址空间。 (带有入口点LoadLibrary的CreateRemoteThread,参数是您之前分配的内存。)
  5. WaitForSingleObject后跟GetExitCodeThread(),在cmd.exe进程中为您提供DLL的HMODULE。
  6. ReadProcessMemory获取当前目录。
  7. 从cmd.exe地址空间卸载您的dll。 CreateRemote Thread,入口点为FreeLibrary,参数为HMODULE。
  8. WaitForSingleObject等待DLL卸载。
  9. 广泛的草图:作为练习留下的细节!风险:在cmd.exe地址空间中分配内存,更改其状态。必须注意DllMain中调用的函数。

答案 1 :(得分:5)

您的意思是批处理文件中的%CD%变量吗?

像这样:

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

在命令提示符中尝试 echo%CD%。 :)

这就是你需要的,这里有一个 PowerShell 功能:

$(get-location)

希望这有帮助。

我从here找到了所有内容。

答案 2 :(得分:5)

也许这个forum entry on the Sysinternals Forum包含解决方案的提示。在GetProcessStrings函数中查找:

// 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.

此CodeProject文章“Read Environment Strings of Remote process”也可能有用。

答案 3 :(得分:2)

  

更新:这是解决方案,请参阅此答案的评论:“正如Janm所说   .Modules [0] .FileName(或   MainModuile.FileName)给出了   运行的可执行文件的位置   那个过程。我正在寻找   当前的工作目录(可以是   使用CD或CHDIR更改   命令)。“

您可以使用 System.Diagnostics命名空间。这里以C#控制台应用程序为例。从文件名中,您可以轻松提取路径信息(System.IO.Path ...)。

您确保拥有权限(以管理员身份运行)来执行此操作。

希望这会有所帮助。这是工作代码(已测试):

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);
                }


            }

        }
    }
}

这是我机器上的输出(我打开了四个命令行):

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

答案 4 :(得分:1)

尝试这个简单的环境属性:

Environment.CurrentDirectory()

答案 5 :(得分:0)

请参阅my answer一个类似的问题(由我自己)。我编写了一个命令行实用程序和C#包装器来读取进程环境变量。对于我的问题(获取java的当前目录),我只需阅读catalina_base目录。

我不确定这是否直接适用于cmd.exe。代码项目文章中提供的实用程序无法使用cmd.exe。