Cuando abro un archivo, quiero saber si está siendo utilizado por otro proceso para poder realizar un manejo especial; cualquier otra IOException que burbujeará. La propiedad Mensaje de IOException contiene "El proceso no puede acceder al archivo 'foo' porque lo está utilizando otro proceso", pero esto no es adecuado para la detección programática. ¿Cuál es la manera más segura y más robusta de detectar un archivo que está siendo utilizado por otro proceso?Cómo saber si una IOException atrapada es causada por el archivo que está siendo utilizado por otro proceso, sin recurrir al análisis de la propiedad de mensaje de la excepción
Respuesta
Esta versión particular de IOException
se produce cuando el código de error devuelto desde la función nativa de Win32 es ERROR_SHARING_VIOLATION
(Documentation). Tiene el valor numérico de 0x20
pero se almacena como 0x80070020
en la propiedad HRESULT
de la excepción (que es el resultado de llamar MakeHRFromErrorCode).
Así que la forma programática de comprobar que existe una violación de distribución está comprobando la propiedad HResult
en el IOException
para el valor 0x80070020
.
public static bool IsSharingViolation(this IOException ex) {
return 0x80070020 == Marshal.GetHRForException(ex);
}
Sin embargo, me pregunto qué es exactamente lo que quiere hacer en el caso de que se haya producido como resultado de una infracción de uso compartido. En el momento en que se lanza la excepción, el otro proceso podría salir y, por lo tanto, eliminar la violación.
¿Por qué no utilizar 'ex.HResult' directamente en lugar de' Marshal.GetHRForException'? –
@Anders porque la propiedad HResult tiene un nivel de accesibilidad protegido, por lo que no es accesible en general. – JaredPar
Fantástica respuesta JaredPar, gracias ... En respuesta a su pregunta; Necesito detectar este escenario porque necesito un mensaje amigable para la capa de presentación. Está bien si el conflicto puede no existir en el momento después, debido a la naturaleza de mi aplicación ... gracias de nuevo –
no tengo suficiente "representante" para comentar y espero que esto "respuesta" está bien ...
La respuesta aceptada es exactamente lo que estaba buscando y funciona perfectamente, pero la gente aquí y en similares Las preguntas han cuestionado la utilidad de verificar si un archivo está bloqueado. Es correcto que una función de utilidad para probar si un archivo está bloqueado no es de mucha utilidad porque en la siguiente declaración el estado podría haber cambiado.
Pero el patrón de intentar una operación de bloqueo y luego responder de manera diferente a los errores de bloqueo frente a los errores generales es válido y útil. Lo más obvio es esperar un poco y volver a intentar la operación. Esto se puede generalizar en una función auxiliar de esta manera:
protected static void RetryLock(Action work) {
// Retry LOCK_MAX_RETRIES times if file is locked by another process
for (int i = 1; i <= LOCK_MAX_RETRIES; i++) {
try {
work();
return;
} catch (IOException ex) {
if (i == LOCK_MAX_RETRIES || (uint) ex.HResult != 0x80070020) {
throw;
} else {
// Min should be long enough to generally allow other process to finish
// while max should be short enough such that RETRIES * MAX isn't intolerable
Misc.SleepRandom(LOCK_MIN_SLEEP_MS, LOCK_MAX_SLEEP_MS);
}
}
}
} // RetryLock
... que luego pueden ser utilizados como esto:
public string DoSomething() {
string strReturn = null;
string strPath = @"C:\Some\File\Path.txt";
// Do some initial work...
//----------------------------------------------------------------------------------------------------
// NESTED FUNCTION to do main logic, RetryLock will retry up to N times on lock failures
Action doWork = delegate {
using (FileStream objFile = File.Open(strPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) {
// Does work here if lock succeeded, else File.Open will throw ex
strReturn = new StreamReader(objFile).ReadLine();
}
}; // delegate doWork
//----------------------------------------------------------------------------------------------------
RetryLock(doWork); // Throws original ex if non-locking related or tried max times
return strReturn;
}
... de todos modos, la simple publicación en caso de que alguien con necesidades similares encuentra el patrón útil.
Si está utilizando C# 6, esta es la situación perfecta para utilizar las excepciones filtradas 'catch (IOException ex) when (i
- 1. archivo está siendo utilizado por otro proceso
- 2. C# File.Delete, archivo que está siendo utilizado por otro proceso
- 3. C Excepción archivo #: no tiene acceso al archivo porque está siendo utilizado por otro proceso
- 4. El proceso no tiene acceso al archivo porque está siendo utilizado por otro proceso
- 5. Cómo comprobar si el archivo está siendo utilizado por otro proceso - Powershell
- 6. proceso no puede acceder al archivo "MyFile.log" porque está siendo utilizado por otro proceso
- 7. El archivo es utilizado por otro proceso. ¿Cómo saber qué proceso?
- 8. Lectura de un archivo utilizado por otro proceso
- 9. de archivo usado por otro proceso
- 10. FileStream: utilizado por otro error de proceso
- 11. ¿Por qué PowerShell no puede construir mis soluciones .net? ("el archivo está siendo utilizado por otro proceso")
- 12. Aplicar certificado SSL en el administrador IIS y "El proceso no puede acceder al archivo porque está siendo utilizado por otro proceso" error
- 13. ¿Por qué la excepción .net no está atrapada?
- 14. ¿Por qué obtengo el error "el archivo es utilizado por otro proceso" cuando depuro dentro de Visual Studio?
- 15. Superación "Está siendo utilizado por otra persona o programa".
- 16. ¿Cómo ver la plantilla de proceso que está siendo utilizada por el proyecto TFS?
- 17. .NET - TextWriterTraceListener, el archivo está en uso por otro proceso
- 18. El nombre ya está siendo utilizado por un objeto existente
- 19. El proceso no puede acceder al archivo porque lo está utilizando otro proceso
- 20. ¿Cómo se determina qué componente está siendo utilizado por matplotlib?
- 21. Dentro de un archivo por lotes, ¿cómo puedo saber si se está ejecutando un proceso?
- 22. ¿Cómo verificar si un archivo ya está abierto por otro proceso en C?
- 23. saber si un controlador está siendo utilizado en una ruta anidada en Rails 3
- 24. ¿Cómo comprobar si un archivo está abierto por otro proceso (Java/Linux)?
- 25. ¿Cómo comprobar si el archivo EXE compartido de red es utilizado por más de un usuario?
- 26. ¿Cómo saber el número de puerto utilizado por C# UdpClient?
- 27. Coldfusion: Detectando si está siendo ejecutado por el programador
- 28. Android Bluetooth: ¿conexión causada por software aborta IOException?
- 29. ¿Por qué obtengo la "Excepción no controlada tipo IOException"?
- 30. ¿La excepción lanzada en el bloque de catch será atrapada por bloques catch posteriores?
¿El tipo es realmente una IOException o es uno de los tipos derivados de IOException? –
Fuera de interés, ¿por qué necesita detectar esto programáticamente? ¿Qué planeas hacer una vez que descubras que otro proceso está usando tu archivo? –
@Mark Byers, ver mi comentario en contra de la respuesta aceptada. –