2008-10-07 17 views
37

¿Cómo obtengo la lista de identificadores de archivos abiertos por id de proceso en C#?¿Cómo obtengo la lista de identificadores de archivos abiertos por proceso en C#?

Estoy interesado en profundizar y obtener los nombres de los archivos también.

Buscando el equivalente programático de lo que hace el explorador de procesos.

Lo más probable es que esto requiera interoperabilidad.

Considerando agregar una recompensa por esto, la implementación es desagradablemente complicada.

+4

cualquier solución final con el código fuente completo? – Kiquenet

Respuesta

22

Ouch esto va a ser difícil de hacer desde el código administrado.

Hay una sample on codeproject

mayoría de las cosas se puede hacer de interoperabilidad, pero se necesita un controlador para obtener el nombre de archivo de la causa que vive en el espacio de direcciones del núcleo. Process Explorer incorpora el controlador en sus recursos. Conseguir todo esto conectado desde C# y soportar 64 bits y 32, va a ser un gran dolor de cabeza.

+1

¡A quién le importa el código, eso es útil! Incluso mejor que Process Explorer, por lo que hace. – Brian

+0

¿No es una buena solución usando solo código administrado? – Kiquenet

+0

esto no es algo fácil en el código administrado, probablemente simplemente pagaría a un programa C++ si tuviera que construir algo así como @Kiquenet –

10

Puede P/INVOCAR en la función NtQuerySystemInformation para consultar todos los identificadores y luego ir desde allí. Este Google groups discussion tiene detalles.

+0

cosas buenas. Voy a ver si puedo obtener la interoperacion –

+1

cualquier codigo de muestra en C#? – Kiquenet

12

También puede ejecutar la aplicación de línea de comandos, Handle, de Mark Rusinovich, y analizar la salida.

+0

cualquier código de muestra para analizar el resultado en C#? – Kiquenet

+3

Esa es una solución horrible. –

+2

¿Por qué @bruce? alguna razón, por favor? – Kiquenet

2

Handle es un programa excelente, y el enlace al proyecto de código es bueno.

@Brian El motivo del código es que handle.exe NO se puede redistribuir. Tampoco liberan su fuente.

Parece que .Net no hará esto fácilmente ya que parece que se necesita una unidad de dispositivo incorporada para acceder a la información. Esto no se puede hacer en .NET sin una DLL no administrada. Se trata de un código de kernel relativamente profundo en comparación con la codificación .net típica. Estoy sorprendido de que WMI no exponga esto.

+0

Es compatible con x64. – ElektroStudios

6

Tener un vistazo a este archivo: http://vmccontroller.codeplex.com/SourceControl/changeset/view/47386#195318

y uso:

DetectOpenFiles.GetOpenFilesEnumerator(processID); 

Demostración:

using System; 
using System.Diagnostics; 

namespace OpenFiles 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      using (var openFiles = VmcController.Services.DetectOpenFiles.GetOpenFilesEnumerator(Process.GetCurrentProcess().Id)) 
      { 
       while (openFiles.MoveNext()) 
       { 
        Console.WriteLine(openFiles.Current); 
       } 
      } 
      Console.WriteLine(); 
      Console.ReadKey(); 
     } 
    } 
} 

Tiene la dependencia sobre el conjunto de System.EnterpriseServices

+0

cualquier muestra completa con el código fuente ?? – Kiquenet

+0

Al ejecutarlo como usted mencionó GetOpenFilesEnumerator devuelve un objeto con 2 miembros:
ERROR_ACCESS_DENIED y ERROR_INVALID_PARAMETERS – Lucian

+0

Acaba de probar y este código funciona bien. tal vez en realidad no tienes el acceso. – Mehran

0

Para verificar si algún archivo está en uso (abierto) use File Stream.

Por ejemplo:

Suponga que tiene una ruta de archivo almacenado en txtAttachPath.Text y que desea abrir ese archivo si no está ya abierto, es necesario comprobar si el archivo está abierto primero y luego abrirlo, esto es cómo hacerlo:

crear un método para comprobar si el archivo está abierto:

private bool attachedFileIsOpen(FileInfo file) 
{ 
    FileStream fs = null; 
    try 
    { 
     fs = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None); 
    } 
    catch (IOException ioe) 
    { 
    MessageBox.Show("The attachment file is already open!, can't open more than once!", "AMP Warning", MessageBoxButtons.OK, MessageBoxIcon.Information); 
    return true; 
    } 
    finally 
    { 
     if (fs != null) fs.Close(); 
    } 
    return false; 
    } 

el método comprobará si el archivo es abierto y Retrun cierto con un mensaje al usuario que el archivo es aleardy abierta, de lo contrario, devolverá falso (el archivo es no esta en uso).

Siguiente usando el método provocada por cualquier evento que elija:

FileInfo filePath = new FileInfo(txtAttachPath.Text); 
if (!txtAttachPath.Text.Equals("No Attachment") 
    && attachedFileIsOpen(filePath) == false 
    && processIsRunning("notepad") == false) 
{ 
    Process openFilebyExtension = Process.Start(txtAttachPath.Text); 
      openFilebyExtension.WaitForInputIdle(); 
      NativeWindow.FromHandle(this.Handle); 
} 

Nota algunos incorporado en los programas de Windows como la libreta permite que varias instancias del mismo archivo que se abran, por tanto, no pueden ser detectados por el método File Stream, la otra solución para él es detectar si el proceso se está ejecutando.

tendrá que añadir otro método para comprobar si hay proceso asociado al tipo de archivo que está intentando abrir ejecutando:

private bool processIsRunning(string process) 
     { 
      Process[] runningProcesses = Process.GetProcessesByName(process); 
      bool processIsRunning = false; 
      if(runningProcesses.Length == 0) 
      { 
       processIsRunning = false; 
      } 
      else 
      { 
       processIsRunning = true; 
       MessageBox.Show("The attachment file is already open!, can't open more than once!", "AMP Warning", 
        MessageBoxButtons.OK, MessageBoxIcon.Information); 
      } 
      return processIsRunning; 
     } 
Cuestiones relacionadas