Tengo una aplicación C# y deseo copiar un archivo a una nueva ubicación. Algunas veces necesito sobrescribir un archivo existente. cuando esto sucede, recibo una System.IO.IOException. Deseo recuperarme de una violación de Compartir, pero ¿cómo puedo determinar que se haya devuelto IOException porque el archivo de destino está en uso en lugar de otro motivo? Podría buscar el "El proceso no puede acceder al archivo porque lo está usando otro proceso". mensaje ... Pero no me gusta esa idea.¿Cómo puedo determinar si se lanza una IOException debido a una infracción de uso compartido?
Respuesta
Este article explica cómo obtener la excepción HRESULT para que pueda determinar la causa del error.
Busque los códigos de error explícitos que se puede tratar, por ejemplo:
catch (Exception u) { if (((SocketException) u) .ErrorCode == 10035) ...
Echa un vistazo aquí: http://msdn.microsoft.com/en-us/library/ms681391(VS.85).aspx
de códigos de error, por ejemplo:
ERROR_SHARING_VIOLATION - 32 - 0x20
ERROR_ACCESS_DENIED = 5 - 0x5
ERROR_FILE_NOT_FOUND - 2 - 0x2
¿Cómo se logrará el lanzamiento de IOException a SocketException? –
solo un ejemplo ... no pensé que arrojaría a nadie – cookre
Esta fue la solución que se me ocurrió.
private void RobustMoveFile(System.IO.DirectoryInfo destinationDirectory, System.IO.FileInfo sourceFile, Boolean retryMove)
{
try
{
string DestinationFile = Path.Combine(destinationDirectory.FullName, sourceFile.Name);
if (File.Exists(DestinationFile))
sourceFile.Replace(DestinationFile, DestinationFile + "Back", true);
else
{
sourceFile.CopyTo(DestinationFile, true);
sourceFile.Delete();
}
}
catch (System.IO.IOException IOEx)
{
int HResult = System.Runtime.InteropServices.Marshal.GetHRForException(IOEx);
const int SharingViolation = 32;
if ((HResult & 0xFFFF) == SharingViolation && retryMove)
RobustMoveFile(destinationDirectory, sourceFile, false);
throw;
}
}
No es necesario verificar la existencia del archivo de destino, ya que otro proceso puede crearlo/eliminarlo entre las operaciones de verificación y reemplazo/Copiar a. Simplemente cambie su lógica de que siempre crea el archivo de detinación sin importar qué, y si esto falla, recupere o vuelva a intentarlo. –
Como han indicado otras respuestas, debe obtener el resultado HR del error y verificarlo. Un HResult de 32 es una violación de compartir.
En .NET 4.5, la IOException
tiene un público HResult
propiedad, por lo que sólo puede hacer lo siguiente:
try
{
// do file IO here
}
catch (IOException e)
{
if (e.HResult == 32) // 32 = Sharing violation
{
// Recovery logic goes here
}
else
{
throw; // didn't need to catch this
}
}
En versiones anteriores de .NET, sin embargo, es necesario obtener la HResult
llamando Marshal.GetHRForException(Exception)
, por lo que el código similar sería:
try
{
// do file IO here
}
catch (IOException e)
{
int HResult = System.Runtime.InteropServices.Marshal.GetHRForException(e)
if (HResult == 32) // 32 = Sharing violation
{
// Recovery logic goes here
}
else
{
throw; // Or do whatever else here
}
}
el sin publicar C# 6.0 voluntad, según A C# 6.0 Language Preview, le permiten usar esta sintaxis para coger solamente un intercambio de violación:
try
{
// do file IO here
}
catch (IOException e)
if (e.HResult == 32) // 32 = Sharing violation
{
// Recovery logic goes here
}
¿estás seguro de que esto es del todo correcto?experimentando con esto, creo que necesita bitwise y (&&) HResult con 0x000000000000FFFF. Entonces desea verificar (0xFFFF && e.HResult) == 32 – Greylander
@Greylander Creo que tiene razón sobre el requisito de hacer el bitwise y, pero el operador es "&", no "&&". Este último es el cortocircuito lógico "y". BTW [aquí hay una referencia] (https://msdn.microsoft.com/en-us/library/ms680746.aspx) para convertir un error W32 a HRESULT. Por lo tanto, el propósito de la bit a bit es hacer lo contrario. – ricovox
- 1. ¿Qué debo hacer si se lanza una IOException?
- 2. JUnit Regla TemporaryFolder lanza arbitrariamente una IOException
- 3. ¿Cómo puedo saber si se lanzó una excepción SQL debido a una violación de clave externa?
- 4. ¿Cómo puedo determinar si una URL redirige?
- 5. cómo lanzar una IOException?
- 6. ¿Se eliminan los recursos incluso si se lanza una excepción en un bloque de uso?
- 7. ¿Cómo puedo verificar si se lanza un objeto?
- 8. Exactamente cómo se desencadena una excepción de infracción de acceso
- 9. ¿Cómo puedo determinar si una casilla de verificación está marcada?
- 10. ¿Cómo puedo determinar si una URL redirecciona en PHP?
- 11. ¿Cómo puedo determinar si una imagen ha sido retocada?
- 12. ¿Cómo puedo determinar si una matriz está vacía en PHP?
- 13. ¿Cómo puedo determinar si una función genera un gráfico
- 14. Cómo determinar si una dirección IP pertenece a un país
- 15. ¿Qué sucede si se lanza una excepción durante finalize()
- 16. ¿Cómo determinar si una secuencia es bitónica?
- 17. se arrastra usando Nutch ... Muestra una IOException
- 18. ¿Puedo determinar si una función de PowerShell se está ejecutando como parte de una canalización?
- 19. Cómo determinar si una aplicación web se está ejecutando actualmente
- 20. cómo determinar si una imagen es explícita
- 21. ¿Cómo determinar si se está manejando una excepción .NET?
- 22. ¿Cómo puedo determinar el acceso a una instancia de MemberInfo?
- 23. Cómo rastrear el uso de la aplicación en Android? ¿Cómo detectar cuándo se lanza una actividad?
- 24. ¿Cómo puedo determinar qué celda de una JTable se seleccionó?
- 25. ¿Cómo determinar si Type es una estructura?
- 26. ¿Cómo puedo determinar si se muestra un botón de retroceso?
- 27. ¿Cómo puedo determinar si se difiere un objeto jQuery?
- 28. ¿Cómo puedo determinar a qué compañía pertenece una dirección IP?
- 29. ¿Cómo puedo determinar si se gestiona un proceso en C#?
- 30. Cómo determinar si una cadena contiene una subcadena específica
estaba a punto de mostrar que :) –
No, IOException utiliza el COR_E_IO HRESULT que tiene la constante valor 0x80131620 [ver Clase IOException] (https://msdn.microsoft.com/en-us/library/system.io.ioexception (v = vs.110) .aspx). – tibx
pero, de hecho, parece que la propiedad HResult de la clase IOException tiene el verdadero motivo de error HRSEULT ... – tibx