2008-10-20 117 views
15

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

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

我已经看过.NET Process和ProcessStartInfo类(ProcessStartInfo.WorkingDirectory总是返回“”),并且似乎无法找到确定此方法的方法。 PInvoke也没有什么突出的。

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

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

[更新]

原因提出这个问题:

我用“命令提示符浏览器栏”了一段时间,这是除非我“CD”大到一个新的目录,当前资源管理器窗口不会更改。 (即同步只是从资源管理器到命令提示符的一种方式)。我正在寻找这2种方法。

+0

你所要求的听起来可疑。除非你正在测试(QA)或调试,否则一个进程不应该干扰另一个进程。将它用于“生产”或商业软件是不好的,因为它需要特权。你的产品不会得到。那么,你想完成什么? – jim 2008-10-20 12:23:49

+0

公平的问题。没什么可疑的。我已经使用了“命令提示符浏览器栏”一段时间,除非我“CD”到新目录,否则当前浏览器窗口不会改变,这很棒。(即同步只是从资源管理器到命令提示符的一种方式)。我正在寻找这2种方法。 – Ash 2008-10-21 00:40:10

+0

我需要这个用于测试目的 - 我想杀死一个Java Tomcat进程,并将其用作区别于其他方式的一种方法。 – ripper234 2009-01-13 17:27:01

回答

5

未经检验的,一种可能的方法:

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

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

宽泛的草图:详细信息作为excercise!风险:在cmd.exe地址空间中分配内存,更改其状态。必须注意DllMain中调用的函数。

+0

感谢您的详细回复。它看起来比说看GetProcessStrings()更复杂一点,但如果不行的话,我可能会放弃它。 – Ash 2008-10-21 00:44:28

5

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

像这样:

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

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

好,因为这是你所需要的,这里有一个PowerShell的功能来做到这一点:

$(get-location) 

希望这有助于。

我发现这一切都是从here

+0

我正在寻找编程方式能够说类似于:Process.GetCurrentWorkingDirectory(processID)其中processID是一个Windows进程ID。 – Ash 2008-10-20 10:14:15

2

UPDATE:这是不该溶液中,使用注释的此答案:“作为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

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”可能是有用的。

0

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

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

1

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

Environment.CurrentDirectory()