2009-12-23 28 views
8

Veo que el estándar C no tiene forma de saber si un archivo ya está abierto en otro proceso. Entonces, la respuesta debe contener varios ejemplos para cada plataforma. Sin embargo, necesito esa comprobación para Visual C++/Windows.¿Cómo verificar si un archivo ya está abierto por otro proceso en C?

+0

¿Por qué quiere saber si un archivo está abierto por otro proceso? Además, ¿desea saber si el archivo está abierto por un proceso específico (es decir, conocido), o simplemente abierto por cualquier otro proceso? –

+0

Solo si otro proceso ya tiene acceso al mismo tiempo. Si el archivo está en uso, podría dañar algunas cosas al proceder. – winlin

+0

No me interesa el proceso de "qué" está accediendo a la información. Esta pregunta está aquí porque nadie más parece responder esta pregunta en otras plataformas, pero podría ser necesario saberlo. Así que por favor, mantenlo corto, y no digas "volver a pensar" sobre el problema. Piensa en el explorador, es como si antes de eliminar el archivo verificara si algún otro proceso está accediendo a él. – winlin

Respuesta

7

No hay forma de saberlo, a menos que el otro proceso prohíba explícitamente el acceso al archivo. En MSVC, lo haría con _fsopen(), especificando _SH_DENYRD para el argumento shflag. La noción de estar interesado en si se abre un archivo que no está bloqueado de otro modo es muy defectuoso en un sistema operativo multitarea. Se podría abrir un microsegundo después de haber encontrado que no lo era. Esa es también la razón por la que Windows no tiene una función IsFileLocked().

Si necesita acceso sincronizado a los archivos, deberá agregar esto con un mutex con nombre, use CreateMutex().

+0

Gracias. Para Windows, esto funciona y realmente ayudó a mi problema. El resto es para otras personas que buscan una respuesta para otras plataformas. – winlin

1

Cualquier comprobación de este tipo sería intrínsecamente picante. Otro proceso siempre podría abrir el archivo entre el punto donde hizo el cheque y el punto donde accedió al archivo.

3

Obtener la información de open_files es DIFÍCIL, es como tirar los dientes, y si no tiene una necesidad inmediata no debería pedir "varios ejemplos para cada plataforma" por el gusto de hacerlo. Sólo mi opinión, por supuesto.

Linux y muchos sistemas Unix tienen una utilidad de sistema llamada lsof que encuentra los manejadores de archivos abiertos y esas cosas. La forma en que lo hace es accediendo al /dev/kmem, que es un pseudo archivo que contiene una copia de la memoria del kernel "en vivo", es decir, el almacenamiento de trabajo del kernel del sistema operativo. Naturalmente, hay tablas de archivos abiertos, y la estructura de la memoria es de código abierto y está documentada, por lo que es solo cuestión de mucho trabajo para que lsof ingrese allí, encuentre la información y la formatee para el usuario.

La documentación para las entrañas profundas de Windows, por otro lado, es prácticamente inexistente, y no estoy al tanto de que las estructuras de datos estén de alguna manera expuestas al exterior. No soy experto en Windows, pero a menos que la API de Windows ofrezca explícitamente este tipo de información, es posible que simplemente no esté disponible.

Lo que esté disponible probablemente esté siendo utilizado por las utilidades SysInternals de Mark Russinovich; el primero que me viene a la mente es FileMon. Verlos puede darte algunas pistas. Actualización: Me acaban de informar que SysInternals Handles.exe está aún más cerca de lo que desea.

Si logras resolver eso, bien; de lo contrario, podría interesarle la captura de operaciones de apertura/cierre de archivos a medida que suceden: la API de Windows ofrece una gran cantidad de llamados ganchos: http://msdn.microsoft.com/en-us/library/ms997537.aspx. Los enganches le permiten solicitar una notificación cuando suceden ciertas cosas en el sistema. Creo que hay uno que le dirá cuando un programa – systemwide – abre un archivo. Para que pueda crear su propia lista de archivos abiertos mientras escucha sus ganchos. No estoy seguro, pero sospecho que esto puede ser lo que hace FileMon.

Se puede acceder a la API de Windows, incluidas las funciones de enlace, desde C. Los enganches de todo el sistema requerirán que cree una DLL para cargar junto con su programa.

Espero que estas sugerencias lo ayuden a comenzar.

+1

Es posible hacer esto en Windows. La herramienta Sysinternals handle.exe lo hace, por ejemplo. http://technet.microsoft.com/en-us/sysinternals/bb896655.aspx –

+0

+1, gracias! Acabo de actualizar mi respuesta para reflejar esto. –

0

Las respuestas hasta ahora deberían indicarle que encontrar la información que ha solicitado es complicado, no portátil y, a menudo, inherentemente poco fiable. Entonces, desde mi punto de vista, la verdadera respuesta es , no hagas eso.Intenta encontrar una forma de pensar acerca de tu problema real para que esta pregunta no surja.

6

ventanas: intente abrir el archivo en modo exclusivo. Si funciona, nadie más ha abierto el archivo y no será capaz de abrir el archivo

HANDLE fh; 
fh = CreateFile(filename, GENERIC_READ, 0 /* no sharing! exclusive */, NULL, OPEN_EXISTING, 0, NULL); 
if ((fh != NULL) && (fh != INVALID_HANDLE_VALUE)) 
{ 
    // the only open file to filename should be fh. 
    // do something 
    CloseHande(fh); 
} 

MS dice: dwShareMode

El modo de uso compartido de un objeto, que se puede leer, escribir , ambos, eliminar, todo esto o ninguno (consulte la siguiente tabla).

Si este parámetro es cero y CreateFile tiene éxito, el objeto no se puede compartir y no se puede volver a abrir hasta que se cierre el controlador.

No puede solicitar un modo de uso compartido que entre en conflicto con el modo de acceso que se especifica en una solicitud abierta que tiene un descriptor abierto, porque eso daría lugar a la siguiente infracción de uso compartido: ERROR_SHARING_VIOLATION.

http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx

extensión: cómo eliminar una (no de sólo lectura) del sistema de ficheros de archivo que nadie tiene abierto para lectura/escritura?

derecho de acceso FILE_READ_ATTRIBUTES, no ELIMINAR. ELIMINAR podría causar problemas en la compartición de smb (para los servidores de MS Windows) - CreateFile se irá con un FileHandle/Device/Mup: archivo de archivo xxx aún abierto - por qué nunca y qué es este Mup. No sucederá con el derecho de acceso FILE_READ_ATTRIBUTES use FILE_FLAG_OPEN_REPARSE_POINT para eliminar el nombre del archivo. De lo contrario se elimine el objetivo de un enlace simbólico - que por lo general no es lo que quiere

HANDLE fh; 
fh = CreateFile(filename, FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE /* no RW sharing! */, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_DELETE_ON_CLOSE, NULL); 
if ((fh != NULL) && (fh != INVALID_HANDLE_VALUE)) 
{ 
    DeleteFile(filename); /* looks stupid? 
          * but FILE_FLAG_DELETE_ON_CLOSE will not work on some smb shares (e.g. samba)! 
          * FILE_SHARE_DELETE should allow this DeleteFile() and so the problem could be solved by additional DeleteFile() 
          */ 
    CloseHande(fh); /* a file, which no one has currently opened for RW is delete NOW */ 

} 

qué hacer con un archivo abierto? Si el archivo está abierto y puede desvincularse, dejará un archivo en el que los siguientes accesos darán lugar a ACCESS_DENIED. Si tiene una carpeta temoprary, entonces podría ser una buena idea cambiar el nombre (filename, tempdir/filename.delete) y eliminar tempdir/filename.delete.

0

esto no puede ser tan difícil chicos.

hacer esto:

try{ 
File fileout = new File(path + ".xls"); 
FileOutPutStream out = new FileOutPutStream(fileout); 
} 
catch(FileNotFoundException e1){ 

// if a MS Windows process is already using the file, this exception will be thrown 
} 
catch(Exception e){ 

} 
+1

Erm, bien pero no C ...? –

+0

Cierto, LOL grita perdón –

4

Para Windows, este código funciona también:

boolean isClosed(File f) { return f.renameTo(f); } 

un abierto de archivo no se puede cambiar, y un cambio de nombre de mismo nombre no causa otro error. Entonces, si el cambio de nombre tiene éxito, sin haber realmente hecho algo, usted sabe que el archivo no está abierto.

+0

Esto funciona para mí, ¡y es muy simple de implementar! Está en Java en lugar de C, que es quizás la razón por la que se ha votado negativamente. Encontré esta respuesta extremadamente útil, gracias. – Rich

+0

¿Qué biblioteca está utilizando para cambiar el nombre de acción ?, porque si intento cambiar el nombre del archivo con 'std :: rename', Windows permite cambiar el nombre del archivo aunque esté abierto. –

Cuestiones relacionadas