2008-10-20 14 views
15

¿Cómo puedo recuperar el directorio de trabajo actual de cmd.exe?Obtenga el directorio actual de trabajo para cmd.exe

Esto parece posible. Por ejemplo, usando ProcessExplorer, seleccione CMD.exe, haga clic con el botón derecho, propiedades, pestaña Imagen, "Directorio actual", selecciona el directorio establecido usando los comandos CD o CHDIR.

He examinado las clases .NET Process y ProcessStartInfo (ProcessStartInfo.WorkingDirectory siempre devuelve "") y parece que no se puede encontrar una forma de determinar esto. Tampoco se destaca nada en PInvoke.

Como ejemplo, estoy buscando programáticamente poder decir algo como: Process.GetCurrentWorkingDirectory (processID) donde processID es una identificación de proceso de Windows de otro proceso en ejecución.

¿Hay alguna solución, WinAPI o .NET?

[Actualización]

Razón por hacer esta pregunta:

He utilizado el "Símbolo del sistema Barra del explorador" durante un tiempo y es genial, excepto si "CD" a un nuevo directorio, el la ventana actual de Explorer tampoco cambia. (es decir, Sync está solo a 1 camino del Explorador al indicador de comando). Estoy buscando hacer esto de 2 maneras.

+0

Lo que está pidiendo suena a pescado. Un proceso no debe interferir con otro A MENOS QUE esté probando (QA) o depurando. Usar esto para "producción" o software comercial es malo ya que requiere privilegios. Que tu producto no recibirá Entonces, ¿qué estás tratando de lograr? – jim

+0

Pregunta justa. Nada sospechoso He usado la "Barra de comandos del Explorador de comandos" durante un tiempo y es genial, excepto que si "CD" a un nuevo directorio, la ventana actual del Explorador tampoco cambia.(es decir, Sync está solo a 1 camino del Explorador al indicador de comando). Estoy buscando hacer esto de 2 maneras. – Ash

+0

Lo necesito con fines de prueba: quiero matar a un proceso de Java Tomcat, y usar esto como una forma de distinguirlo de otras maneras. – ripper234

Respuesta

5

No comprobado, un posible enfoque:

Crear una DLL con un DllMain que utiliza GetThreadStartInformation() para encontrar la dirección del buffer, y luego utiliza GetCurrentDirectory para poblarlo. Esto debería estar bien, porque ambas funciones están en kernel32, que siempre está presente. Necesitará tener alguna estructura allí para devolver el éxito/fracaso.

  1. Obtenga un control del proceso cmd.exe.
  2. Asignar memoria allí (VirtualAllocEx)
  3. Ponga la ruta a su DLL en la memoria. (WriteProcessMemory)
  4. Cargue su dll en el espacio de direcciones cmd.exe. (CreateRemoteThread con un punto de entrada de LoadLibrary, el argumento es la memoria que asignó anteriormente.)
  5. WaitForSingleObject seguido de GetExitCodeThread(), le da el HMODULE de su DLL en el proceso cmd.exe.
  6. ReadProcessMemory para obtener el directorio actual.
  7. Descargue su dll desde el espacio de direcciones cmd.exe. CreateRemote Thread con un punto de entrada de FreeLibrary, el argumento es HMODULE.
  8. WaitForSingleObject para esperar la descarga de la DLL.

Esbozo general: ¡Los detalles quedan como un ejercicio! Riesgos: Asigna memoria en el espacio de direcciones de cmd.exe, cambia su estado. Se debe tener cuidado con las funciones llamadas en DllMain.

+0

Gracias por la respuesta detallada. Parece un poco más complejo que decir mirando GetProcessStrings(), pero podría intentarlo si eso no funciona. – Ash

+0

No hay problema. El enfoque GetProcessStrings podría funcionar en el caso especial cmd.exe, pero no estoy seguro. Ver mis comentarios arriba. Mi enfoque funcionará con procesos que no modifican las variables de entorno en caso de que cambien directorios. – janm

+0

Básicamente, no debe hacer nada en DllMain() a excepción de TlsAlloc() tal vez, debido al "bloqueo del cargador". Simplemente google para "loader lock dllmain" por muchas razones por las cuales es una mala idea. –

5

¿Se refiere a la variable% CD% en un archivo por lotes?

De esta manera:

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

Trate echo% CD% en un símbolo del sistema. :)

Bueno ya que esto no es lo que necesita, aquí hay una funciónPowerShell para hacerlo:

$(get-location) 

Espero que esto ayude.

Lo encontré todo de here.

+0

Estoy buscando programáticamente ser capaz de decir algo como: Process.GetCurrentWorkingDirectory (processID) donde processID es una identificación de proceso de Windows. – Ash

2

ACTUALIZACIÓN: Esta es no la solución, véanse los comentarios a esta respuesta: "Como dijo JanM .Modules [0] .FileName (o MainModuile.FileName) da la ubicación de el ejecutable ejecutándose en ese proceso. Estoy buscando el directorio de trabajo actual (que puede ser cambiado usando los comandos CD o CHDIR ). "

usted podría utilizar espacio de nombres System.Diagnostics. Aquí un ejemplo como la aplicación de consola C#. Desde el nombre de archivo puede extraer fácilmente la información de ruta (System.IO.Path ...).

Usted se aseguraría de tener los permisos (ejecutar como administrador) para hacer esto.

Espero que esto ayude. Aquí está el código trabajo (probado):

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


      } 

     } 
    } 
} 

aquí los la salida de en mi máquina (que he abierto cuatro líneas de comando):

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

+0

¡Eso no funciona! Eso le da el directorio del módulo, no el directorio actual del proceso. En su prueba, una de las líneas debería haber sido C: \ Users \ stefan. – janm

+0

Como dijo Janm .Modules [0] .FileName (o MainModuile.FileName) da la ubicación del ejecutable que se ejecuta en ese proceso. Estoy buscando el directorio de trabajo actual (que se puede cambiar usando los comandos CD o CHDIR). – Ash

+0

D'oh! Eso sucede, si investigas y luego olvidas la pregunta principal. Me disculpo ... – splattne

5

Tal vez esto forum entry on the Sysinternals Forum contiene una pista para la solución. Busque este en la función 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. 

Este artículo CodeProject "Read Environment Strings of Remote process" podría ser útil también.

+0

Gracias, veré GetProcessStrings. Pensé que podría ser algo relacionado con eso. – Ash

+0

Posibles problemas con este enfoque: 1. Razas entre la lectura del env del proceso objetivo y el proceso objetivo que lo modifica. 2. Los números mágicos cambian entre lanzamientos de Windows. 3.% CD% parece ser especial en cmd.exe y podría no ser un envvar. p.ej. Prueba "set CD = blah"; deja de cambiar en el cd. – janm

0

Consulte my answer para una pregunta similar (por mi cuenta). Escribí una utilidad de línea de comandos y un contenedor C# para leer las variables de entorno del proceso. Para mi pregunta (obtener el directorio actual para java), simplemente leí el directorio catalina_base.

No estoy seguro de si esto se aplica directamente a cmd.exe. La utilidad provista en el artículo de Code Project no funcionó con cmd.exe.

1

Pruebe esta sencilla propiedad de entorno:

Environment.CurrentDirectory()

Cuestiones relacionadas