Estoy buscando una forma de eliminar un archivo que está bloqueado por otro proceso usando C#. Sospecho que el método debe ser capaz de encontrar qué proceso está bloqueando el archivo (quizás siguiendo los identificadores, aunque no estoy seguro de cómo hacerlo en C#) y luego cerrar ese proceso antes de poder completar el archivo eliminar usando File.Delete()
.¿Cómo elimino un archivo que está bloqueado por otro proceso en C#?
Respuesta
matar a otros procesos no es una cosa sana a hacer. Si su escenario implica algo así como la desinstalación, puede usar el MoveFileEx
API function para marcar el archivo para su eliminación en el próximo reinicio.
Si parece que realmente necesita eliminar un archivo en uso por otro proceso, le recomiendo volver a considerar el problema real antes de considerar cualquier solución.
Tenga en cuenta esta observación de MSDN: 'MOVEFILE_DELAY_UNTIL_REBOOT' -" ... Este valor se puede usar solo si el proceso está en el contexto de un usuario que pertenece al grupo de administradores o al Cuenta LocalSystem ... " –
Puede utilizar este programa, Handle, para encontrar qué proceso tiene el bloqueo en su archivo. Es una herramienta de línea de comandos, así que supongo que usas el resultado de eso ... No estoy seguro de encontrarlo programáticamente.
Si la eliminación del archivo puede esperar, se podría especificar que para su eliminación cuando el equipo se inicia inmediatamente superior:
inicio
REGEDT32 (W2K)
oREGEDIT (WXP)
y vaya a:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager
W2K y WXP
W2K:
Edición Agregar valor ...
Tipo de datos:REG_MULTI_SZ
Valor Nombre:PendingFileRenameOperations
OKWXP:
Editar
Nueva
Valor de cadena múltiple
entrar
PendingFileRenameOperations
En el área Datos, ingrese
"\??\" + filename
para eliminar. Los LFN pueden ingresarse sin estar incrustados entre comillas. Para eliminarC:\Long Directory Name\Long File Name.exe
, introduzca los siguientes datos:\??\C:\Long Directory Name\Long File Name.exe
A continuación, pulse OK .
El "nombre de archivo de destino" es una cadena nula (cero).Se entra de la siguiente manera:
W2K:
Editar
binario
seleccione Formato de datos: Hex
clic en el extremo de la cadena hexadecimal
ingrese 0000 (cuatro ceros)
OKWXP:
Haga clic en el valor
elegir la opción "Modificar datos binarios"
clic al final del hexagonal st
anillo ingrese 0000 (cuatro ceros)
OK
Cerrar
REGEDT32/REGEDIT
y reiniciar el sistema para eliminar el archivo.
(robados Desvergonzadamente de some random forum, por el bien de la posteridad.)
Si quieres hacerlo programáticamente. No estoy seguro ... y realmente recomendaría no hacerlo. Si acaba de solucionar las cosas en su propia máquina, SysInternals Process Explorer puede ayudarle a
ejecutarlo, utiliza el Encuentra la manija de mando (creo que es ya sea en el hallazgo o manipular menú), y buscar el nombre de su archivo . Una vez que se encuentra el (los) mango (s), puede cerrarlos a la fuerza.
Puede eliminar el archivo, y así sucesivamente.
Cuidado, hacer esto puede hacer que el programa que posee las asas a comportarse de forma extraña, como usted ha acabado de jalar la alfombra proverbiales de debajo de ella, pero funciona bien cuando se está depurando su propio código errante, o cuando Visual Studio/Windows Explorer es una porquería y no libera manejadores de archivos a pesar de que les dijiste que cerraran el archivo hace siglos ... suspiro :-)
Oh, un gran pirateo que empleé hace años, es que Windows ganó Te dejo borrar archivos, pero te deja mover ellos.
Pseudo-clase-de-código:
mv %WINDIR%\System32\mfc42.dll %WINDIR\System32\mfc42.dll.old
Install new mfc42.dll
Tell user to save work and restart applications
Cuando las aplicaciones renovadas (Tenga en cuenta que no era necesario reiniciar la máquina), cargaron el nuevo mfc42.dll
, y todo estaba bien. Eso, junto con PendingFileOperations
para eliminar el anterior la próxima vez que se reinició todo el sistema, funcionó bastante bien.
El método típico es el siguiente. Has dicho que quieres hacer esto en C# así que aquí va ...
- Si no sabe qué proceso tiene el archivo bloqueado, deberá examinar la lista de identificadores de cada proceso y consultar cada identificador para determinar si identifica el archivo bloqueado. Hacer esto en C# probablemente requiera que P/Invoke o un C++/CLI intermediario llame a las API nativas que necesitará.
- Una vez que haya descubierto qué proceso (es) tiene el archivo bloqueado, tendrá que inyectar con seguridad una pequeña DLL nativa en el proceso (también puede inyectar una DLL administrada, pero esto es más complicado, como entonces tiene que iniciarse o conectarse al tiempo de ejecución de .NET).
- Eso bootstrap DLL se cierra el mango usando CloseHandle, etc.
En esencia: la manera de desbloquear un archivo "bloqueado" es inyectar un archivo DLL en el espacio de direcciones del proceso infractor y cerrar por sí mismo. Puedes hacerlo usando código nativo o administrado. No importa qué, vas a necesitar una pequeña cantidad de código nativo o al menos P/Invocar en el mismo.
enlaces útiles:
buena suerte!
Esto parece prometedor. Una forma de matar el identificador de archivo ....
http://www.timstall.com/2009/02/killing-file-handles-but-not-process.html
Consejo de utilización Orion Edwards he descargado los Sysinternals Process Explorer que a su vez me permitió descubrir que el archivo que estaba teniendo dificultades eliminación fue, de hecho, no se celebró por el objeto Excel.Applications
, pensé, pero más bien el hecho de que mi código C# envíe el código de correo había creado un objeto Adjunto que dejaba abierto un asa a este archivo.
Una vez que vi esto, simplemente llamé al método de eliminación del objeto Attachment, y se soltó el identificador.
El explorador Sysinternals me permitió descubrir esto usado junto con el depurador Visual Studio 2005.
¡Recomiendo esta herramienta!
Este fue exactamente mi problema también. Gracias +1 – Fandango68
Puede utilizar el código que se proporciona la ruta completa del archivo a, y ha de devolver un List<Processes>
de nada bloqueo ese archivo:
using System.Runtime.InteropServices;
using System.Diagnostics;
static public class FileUtil
{
[StructLayout(LayoutKind.Sequential)]
struct RM_UNIQUE_PROCESS
{
public int dwProcessId;
public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime;
}
const int RmRebootReasonNone = 0;
const int CCH_RM_MAX_APP_NAME = 255;
const int CCH_RM_MAX_SVC_NAME = 63;
enum RM_APP_TYPE
{
RmUnknownApp = 0,
RmMainWindow = 1,
RmOtherWindow = 2,
RmService = 3,
RmExplorer = 4,
RmConsole = 5,
RmCritical = 1000
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct RM_PROCESS_INFO
{
public RM_UNIQUE_PROCESS Process;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_APP_NAME + 1)]
public string strAppName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_SVC_NAME + 1)]
public string strServiceShortName;
public RM_APP_TYPE ApplicationType;
public uint AppStatus;
public uint TSSessionId;
[MarshalAs(UnmanagedType.Bool)]
public bool bRestartable;
}
[DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
static extern int RmRegisterResources(uint pSessionHandle,
UInt32 nFiles,
string[] rgsFilenames,
UInt32 nApplications,
[In] RM_UNIQUE_PROCESS[] rgApplications,
UInt32 nServices,
string[] rgsServiceNames);
[DllImport("rstrtmgr.dll", CharSet = CharSet.Auto)]
static extern int RmStartSession(out uint pSessionHandle, int dwSessionFlags, string strSessionKey);
[DllImport("rstrtmgr.dll")]
static extern int RmEndSession(uint pSessionHandle);
[DllImport("rstrtmgr.dll")]
static extern int RmGetList(uint dwSessionHandle,
out uint pnProcInfoNeeded,
ref uint pnProcInfo,
[In, Out] RM_PROCESS_INFO[] rgAffectedApps,
ref uint lpdwRebootReasons);
/// <summary>
/// Find out what process(es) have a lock on the specified file.
/// </summary>
/// <param name="path">Path of the file.</param>
/// <returns>Processes locking the file</returns>
/// <remarks>See also:
/// http://msdn.microsoft.com/en-us/library/windows/desktop/aa373661(v=vs.85).aspx
/// http://wyupdate.googlecode.com/svn-history/r401/trunk/frmFilesInUse.cs (no copyright in code at time of viewing)
///
/// </remarks>
static public List<Process> WhoIsLocking(string path)
{
uint handle;
string key = Guid.NewGuid().ToString();
List<Process> processes = new List<Process>();
int res = RmStartSession(out handle, 0, key);
if (res != 0) throw new Exception("Could not begin restart session. Unable to determine file locker.");
try
{
const int ERROR_MORE_DATA = 234;
uint pnProcInfoNeeded = 0,
pnProcInfo = 0,
lpdwRebootReasons = RmRebootReasonNone;
string[] resources = new string[] { path }; // Just checking on one resource.
res = RmRegisterResources(handle, (uint)resources.Length, resources, 0, null, 0, null);
if (res != 0) throw new Exception("Could not register resource.");
//Note: there's a race condition here -- the first call to RmGetList() returns
// the total number of process. However, when we call RmGetList() again to get
// the actual processes this number may have increased.
res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, null, ref lpdwRebootReasons);
if (res == ERROR_MORE_DATA)
{
// Create an array to store the process results
RM_PROCESS_INFO[] processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded];
pnProcInfo = pnProcInfoNeeded;
// Get the list
res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, ref lpdwRebootReasons);
if (res == 0)
{
processes = new List<Process>((int)pnProcInfo);
// Enumerate all of the results and add them to the
// list to be returned
for (int i = 0; i < pnProcInfo; i++)
{
try
{
processes.Add(Process.GetProcessById(processInfo[i].Process.dwProcessId));
}
// catch the error -- in case the process is no longer running
catch (ArgumentException) { }
}
}
else throw new Exception("Could not list processes locking resource.");
}
else if (res != 0) throw new Exception("Could not list processes locking resource. Failed to get size of result.");
}
finally
{
RmEndSession(handle);
}
return processes;
}
}
A continuación, iterar la lista de procesos y cerca de ellos y eliminar los archivos :
string[] files = Directory.GetFiles(target_dir);
List<Process> lstProcs = new List<Process>();
foreach (string file in files)
{
lstProcs = ProcessHandler.WhoIsLocking(file);
if (lstProcs.Count > 0) // deal with the file lock
{
foreach (Process p in lstProcs)
{
if (p.MachineName == ".")
ProcessHandler.localProcessKill(p.ProcessName);
else
ProcessHandler.remoteProcessKill(p.MachineName, txtUserName.Text, txtPassword.Password, p.ProcessName);
}
File.Delete(file);
}
else
File.Delete(file);
}
Y dependiendo de si el archivo está en el equipo local:
public static void localProcessKill(string processName)
{
foreach (Process p in Process.GetProcessesByName(processName))
{
p.Kill();
}
}
o un equipo de red:
public static void remoteProcessKill(string computerName, string fullUserName, string pword, string processName)
{
var connectoptions = new ConnectionOptions();
connectoptions.Username = fullUserName; // @"YourDomainName\UserName";
connectoptions.Password = pword;
ManagementScope scope = new ManagementScope(@"\\" + computerName + @"\root\cimv2", connectoptions);
// WMI query
var query = new SelectQuery("select * from Win32_process where name = '" + processName + "'");
using (var searcher = new ManagementObjectSearcher(scope, query))
{
foreach (ManagementObject process in searcher.Get())
{
process.InvokeMethod("Terminate", null);
process.Dispose();
}
}
}
Referencias:
How do I find out which process is locking a file using .NET?
- 1. ¿Archivo bloqueado por qué proceso?
- 2. C# File.Delete, archivo que está siendo utilizado por otro proceso
- 3. ¿Cómo puedo desbloquear un archivo que está bloqueado por un proceso en .NET
- 4. archivo está siendo utilizado por otro proceso
- 5. ¿Cómo verificar si un archivo ya está abierto por otro proceso en C?
- 6. .NET - TextWriterTraceListener, el archivo está en uso por otro proceso
- 7. de archivo usado por otro proceso
- 8. Cómo esperar a que finalice un proceso para ejecutar otro proceso en el archivo por lotes
- 9. E/S Java: Asegurar que un archivo no esté bloqueado por otro proceso antes de cualquier operación de r/w
- 10. C Excepción archivo #: no tiene acceso al archivo porque está siendo utilizado por otro proceso
- 11. Compruebe si un archivo está bloqueado en Java
- 12. En Java, ¿hay alguna manera de leer un archivo cuando ese archivo está bloqueado por otro hilo?
- 13. ¿Cómo comprobar si un archivo está abierto por otro proceso (Java/Linux)?
- 14. Proceso de Python bloqueado por urllib2
- 15. Lectura de un archivo utilizado por otro proceso
- 16. Comprueba si un archivo no está abierto (no usado por otro proceso) en Python
- 17. ¿Cómo verificar en línea de comandos si un archivo o directorio determinado está bloqueado (utilizado por cualquier proceso)?
- 18. El proceso no tiene acceso al archivo porque está siendo utilizado por otro proceso
- 19. ¿Cómo detectar que Windows está bloqueado?
- 20. proceso no puede acceder al archivo "MyFile.log" porque está siendo utilizado por otro proceso
- 21. Cómo cerrar otro proceso de C#
- 22. ¿Es posible que un proceso Java en un jvm mate/detenga otro proceso java en otro jvm?
- 23. ¿Cómo puedo determinar si un archivo está bloqueado con VBS?
- 24. ¿Cómo copio un archivo o carpeta que está bloqueado bajo Windows programáticamente?
- 25. El proceso no puede acceder al archivo porque lo está utilizando otro proceso
- 26. ¿Cómo saber qué proceso está usando un archivo dado?
- 27. Lectura de un archivo de registro que está bloqueado por otra aplicación
- 28. Cómo comprobar si el archivo está siendo utilizado por otro proceso - Powershell
- 29. ¿Cómo puedo averiguar si un objeto está bloqueado? C#
- 30. ¿Cómo matar un proceso C#?
Relacionados - http://stackoverflow.com/questions/1760481/closing-open-files-using -c-sharp/41902677 # 41902677 – vapcguy