Получить текущий рабочий каталог для cmd.exe

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

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

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

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

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

[Обновление]

Причина для ответа на этот вопрос:

Я использовал "Панель команд командной строки" некоторое время, и это здорово, за исключением случаев, когда я "CD" в новый каталог, текущее окно проводника также не изменяется. (т.е. Sync - всего лишь один путь от проводника до командной строки). Я ищу, чтобы сделать этот путь 2.

Ответы

Ответ 1

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

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

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

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

Ответ 2

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

Вот так:

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

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

Ну, вот что вам нужно: здесь есть PowerShell:

$(get-location)

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

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

Ответ 3

Возможно, эта запись форума на форуме 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 running on.

Эта статья CodeProject " Read Environment Strings of Remote process" также может быть полезна.

Ответ 4

UPDATE: Это решение не, см. комментарии к этому ответу: "Как сказал Джанм .Modules [0].FileName(или MainModuile.FileName) дает местоположение исполняемого файла, запущенного в этот процесс. Я ищу, чтобы найти текущий рабочий каталог (который может быть изменено с помощью CD или CHDIR команды)".

Вы можете использовать пространство имен System.Diagnostics. Вот пример как консольное приложение С#. Из имени файла вы можете легко извлечь информацию о пути (System.IO.Path...).

Для этого вы должны иметь разрешения (запускать как admin).

Надеюсь, это поможет. Вот рабочий код (протестирован):

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

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

Environment.CurrentDirectory()

Ответ 6

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

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

Ответ 7

string workingDirectory = Environment.SystemDirectory;