16

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

这似乎是可能的。例如使用 ProcessExplorer,选择 CMD.exe,右键单击,属性,图像选项卡,“当前目录”反映使用 CD 或 CHDIR 命令设置的目录。

我查看了 .NET Process 和 ProcessStartInfo 类(ProcessStartInfo.WorkingDirectory 总是返回“”),但似乎找不到确定这一点的方法。PInvoke也没有什么特别突出的。

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

有没有解决方案,WinAPI 或 .NET?

[更新]

问这个问题的原因:

我已经使用“命令提示符资源管理器栏”有一段时间了,它很棒,除非我“CD”到一个新目录,当前的资源管理器窗口也不会改变。(即同步只是从资源管理器到命令提示符的一种方式)。我正在寻找这两种方式。

4

6 回答 6

6

未经测试,一种可能的方法:

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

  1. 获取 cmd.exe 进程的句柄。
  2. 在那里分配一些内存(VirtualAllocEx)
  3. 将 DLL 的路径放在内存中。(写进程内存)
  4. 将您的 dll 加载到 cmd.exe 地址空间中。(CreateRemoteThread 的入口点为 LoadLibrary,参数是您之前分配的内存。)
  5. WaitForSingleObject 后跟 GetExitCodeThread(),在 cmd.exe 进程中为您提供 DLL 的 HMODULE。
  6. ReadProcessMemory 获取当前目录。
  7. 从 cmd.exe 地址空间中卸载您的 dll。CreateRemote Thread,入口点为 FreeLibrary,参数为 HMODULE。
  8. WaitForSingleObject 等待 DLL 卸载。

粗略的草图:细节留作练习!风险:在 cmd.exe 地址空间分配内存,改变其状态。必须小心在 DllMain 中调用的函数。

于 2008-10-20T10:55:37.437 回答
5

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

像这样:

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

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

好吧,这正是您所需要的,这里有一个PowerShell函数可以做到这一点:

$(get-location)

希望这可以帮助。

我从这里找到了这一切。

于 2008-10-20T10:04:57.710 回答
5

也许Sysinternals 论坛上的这个论坛条目包含解决方案的提示。在 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 文章“读取远程进程的环境字符串”也很有用。

于 2008-10-20T17:56:35.387 回答
2

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

您可以使用System.Diagnostics Namespace。这里以 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);
                }


            }

        }
    }
}

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

替代文字 http://img236.imageshack.us/img236/3547/processworkingdirvn4.png

于 2008-10-20T14:55:36.517 回答
1

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

Environment.CurrentDirectory()

于 2009-03-05T07:44:46.540 回答
0

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

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

于 2009-01-14T08:17:11.673 回答