Получить текущий рабочий каталог для cmd.exe - PullRequest
16 голосов
/ 20 октября 2008

Как я могу получить текущий рабочий каталог cmd.exe?

Это кажется возможным. Например, используя ProcessExplorer, выберите CMD.exe, щелкните правой кнопкой мыши, выберите свойства, вкладку «Изображение», «Текущий каталог» отобразит каталог, заданный с помощью команд CD или CHDIR.

Я посмотрел на классы .NET Process и ProcessStartInfo (ProcessStartInfo.WorkingDirectory всегда возвращает "") и не могу найти способ определить это. Ничто в PInvoke также не выделяется.

В качестве примера я хочу программно сказать что-то вроде: Process.GetCurrentWorkingDirectory (processID), где processID - это идентификатор процесса Windows другого запущенного процесса.

Есть ли какое-либо решение, WinAPI или .NET?

[Update]

Причина задать этот вопрос:

Некоторое время я использовал «Панель обозревателя командной строки», и это замечательно, за исключением того, что если я «CD» в новый каталог, текущее окно проводника также не меняется. (т.е. синхронизация только 1 путь от проводника до командной строки). Я хочу сделать это 2 способа.

Ответы [ 6 ]

6 голосов
/ 20 октября 2008

Не проверено, возможный подход:

Создайте DLL с помощью DllMain, которая использует GetThreadStartInformation (), чтобы найти адрес буфера, а затем использует GetCurrentDirectory, чтобы заполнить его. Это должно быть хорошо, потому что обе эти функции находятся в kernel32, который всегда присутствует. Вам понадобится какая-то структура, чтобы возвращать успех / неудачу.

  1. Получить дескриптор процесса cmd.exe.
  2. Выделите немного памяти там (VirtualAllocEx)
  3. Положите путь к вашей DLL в памяти. (WriteProcessMemory)
  4. Загрузите вашу dll в адресное пространство cmd.exe. (CreateRemoteThread с точкой входа LoadLibrary, аргумент - это память, выделенная вами ранее.)
  5. WaitForSingleObject, за которым следует GetExitCodeThread (), дает HMODULE вашей DLL в процессе cmd.exe.
  6. ReadProcessMemory для получения текущего каталога.
  7. Выгрузите вашу dll из адресного пространства cmd.exe. CreateRemote Поток с точкой входа FreeLibrary, аргументом является HMODULE.
  8. WaitForSingleObject для ожидания выгрузки DLL.

Широкий эскиз: детали оставлены в качестве упражнения! Риски: Распределяет память в адресном пространстве cmd.exe, меняет ее состояние. Необходимо соблюдать осторожность с функциями, вызываемыми в DllMain.

5 голосов
/ 20 октября 2008

Возможно, эта запись в форуме на форуме 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 " Чтение строк среды удаленного процесса " также может быть полезна.

5 голосов
/ 20 октября 2008

Вы имеете в виду переменную% CD% в командном файле?

Как это:

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

Попробуйте echo% CD% в командной строке. :)

Ну, так как это то, что вам нужно, здесь есть функция PowerShell , чтобы сделать это:

$(get-location)

Надеюсь, это поможет.

Я нашел все это из здесь .

2 голосов
/ 20 октября 2008

ОБНОВЛЕНИЕ: Это не решение, см. Комментарии к этому ответу: "Как сказал Джанм .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);
                }


            }

        }
    }
}

Здесь вывод на моей машине (я открыл четыре командной строки):

альтернативный текст http://img236.imageshack.us/img236/3547/processworkingdirvn4.png

1 голос
/ 05 марта 2009

Попробуйте это простое свойство среды:

Environment.CurrentDirectory ()

0 голосов
/ 14 января 2009

См. мой ответ на аналогичный вопрос (самостоятельно). Я написал утилиту командной строки и оболочку C # для чтения переменных среды процесса. На мой вопрос (получение текущего dir для java) я просто прочитал каталог catalina_base.

Я не уверен, относится ли это непосредственно к cmd.exe. Утилита, представленная в статье Code Project, не работает с cmd.exe.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...