IOException: Il processo non può accedere al file ‘percorso del file perché è utilizzato da un altro processo

Ho un po ‘ di codice e quando si esegue, si lancia una IOException, dicendo che

Il processo non può accedere al file ‘nome file perché è utilizzato da
un altro processo

Questo cosa significa, e cosa posso fare?

  • Vedere questa domanda come trovare l’altro processo che utilizza il file.

 

8 Replies
  1. 241

    Qual è la causa?

    Il messaggio di errore è abbastanza chiaro: si sta tentando di accedere a un file, e non è accessibile a causa di un altro processo (o anche lo stesso processo) è di fare qualcosa con esso (e non permette la condivisione).

    Debug

    Può essere abbastanza facile da risolvere (o abbastanza difficile da comprendere), a seconda dello scenario. Vediamo alcune.

    Il processo è l’unico ad accedere a quel file

    Sei sicuro che i altri processo è stato il tuo percorso. Se sai di aprire il file in un’altra parte del programma, quindi prima di tutto è necessario verificare la corretta chiudere l’handle di file dopo ogni utilizzo. Ecco un esempio di codice con questo bug:

    var stream = new FileStream(path, FileAccess.Read);
    var reader = new StreamReader(stream);
    //Read data from this file, when I'm done I don't need it any more
    File.Delete(path); //IOException: file is in use

    Fortunatamente FileStream implementa IDisposable, quindi è facile da avvolgere tutto il codice all’interno di un using istruzione:

    using (var stream = File.Open("myfile.txt", FileMode.Open)) {
        //Use stream
    }
    
    //Here stream is not accessible and it has been closed (also if
    //an exception is thrown and stack unrolled

    Questo motivo anche garantire che il file non essere lasciata aperta, in caso di eccezioni (potrebbe essere il motivo per cui il file è in uso: qualcosa è andato storto, e nessuno chiusa; vedi questo post per un esempio).

    Se tutto sembra a posto (sei sicuro di chiudere sempre ogni file aperto, anche in caso di eccezioni) e si dispone di più di lavoro thread, quindi si hanno due opzioni: rielaborare il tuo codice per la serializzazione di accesso ai file (non sempre fattibile e non sempre voluto) o applicare un riprova modello. E ‘ un bel modello comune per le operazioni di I/O: si tenta di fare qualcosa e in caso di errore di aspettare e riprovare (non ti chiedi perché, per esempio, la Shell di Windows richiede un certo tempo per informare che un file è in uso e non può essere eliminato?). In C# è abbastanza facile da implementare (vedi anche meglio di esempi I/O del disco, networking e accesso al database).

    private const int NumberOfRetries = 3;
    private const int DelayOnRetry = 1000;
    
    for (int i=1; i <= NumberOfRetries; ++i) {
        try {
            //Do stuff with file
            break; //When done we can break loop
        }
        catch (IOException e) when (i <= NumberOfRetries) {
            //You may check error code to filter some exceptions, not every error
            //can be recovered.
            Thread.Sleep(DelayOnRetry);
        }
    }

    Siete pregati di notare un errore comune, ci vediamo molto spesso su StackOverflow:

    var stream = File.Open(path, FileOpen.Read);
    var content = File.ReadAllText(path);

    In questo caso ReadAllText() avrà esito negativo perché il file è in uso (File.Open() in prima linea). Per aprire i file in anticipo non solo è inutile ma anche sbagliato. Lo stesso vale per tutti File funzioni che non restituiscono un gestire il file che si sta lavorando con: File.ReadAllText(), File.WriteAllText(), File.ReadAllLines(), File.WriteAllLines() e altri (come File.AppendAllXyz() funzioni) saranno tutti di aprire e chiudere il file da soli.

    Il processo non è l’unico ad accedere a quel file

    Se il processo non è l’unico ad accedere a quel file, l’interazione può essere più difficile. Un riprova modello sarà di aiuto (se il file non dovrebbe essere aperta da chiunque altro, ma lo è, allora avete bisogno di un programma come Process Explorer per controllare che fa cosa).

    Modi per evitare

    Quando applicabile, utilizzare sempre utilizzando istruzioni per aprire i file. Come detto nel paragrafo precedente, ti attivamente aiuterà a evitare molti errori comuni (vedi questo post per un esempio come non usarlo).

    Se possibile, provare a decidere chi possiede l’accesso a un file specifico e centralizzare l’accesso attraverso alcuni metodi ben noti. Se, per esempio, si dispone di un file di dati in cui il programma legge e scrive, allora si dovrebbe box I/O codice all’interno di una singola classe. Questo renderà più facile eseguire il debug (perché si può sempre mettere un punto di interruzione e vedere chi fa cosa) e, inoltre, sarà un punto di sincronizzazione (se necessario) per l’accesso multiplo.

    Non dimenticare operazioni di I/O può sempre fallire, un esempio è questo:

    if (File.Exists(path))
        File.Delete(path);

    Se qualcuno di eliminare il file dopo File.Exists() ma prima di File.Delete(), poi butto un IOException in un posto dove si potrebbe erroneamente sentire al sicuro.

    Quando è possibile, applicare un riprova modello, e se si utilizza FileSystemWatcher, prendere in considerazione il rinvio azione (perché si otterrà notificato, ma un’applicazione che può essere ancora lavorando esclusivamente con il file).

    Scenari avanzati

    Non è sempre così facile, così si può avere bisogno di condividere l’accesso con qualcun altro. Se, per esempio, stai leggendo dall’inizio e la scrittura alla fine, si dispone di almeno due opzioni.

    1) condividono la stessa FileStream con una corretta sincronizzazione funzioni (perché non è thread-safe). Vedere questo e questo post per un esempio.

    2) utilizzare FileShare enumerazione di istruire OS per consentire ad altri processi (o altre parti del proprio processo) per accedere stesso file contemporaneamente.

    using (var stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.Read))
    {
    }

    In questo esempio ho mostrato come aprire un file per la scrittura e la condivisione per la lettura; si prega di notare che durante la lettura e la scrittura di sovrapposizioni, il risultato è indefinito o di dati non validi. È una situazione che deve essere maneggiato durante la lettura. Inoltre, si noti che non consentono l’accesso alle stream thread-safe, questo oggetto non può essere condivisa con più thread, a meno che l’accesso è sincronizzato in qualche modo (vedi link precedenti). Altre opzioni di condivisione sono disponibili, e si aprono scenari più complessi. Si prega di fare riferimento a MSDN per ulteriori dettagli.

    In generale N processi in grado di leggere dal file stesso tutti insieme, ma solo uno dovrebbe scrivere, in uno scenario controllato si può anche attivare concorrenti scritti, ma questo non può essere generalizzato in pochi paragrafi di testo all’interno di questa risposta.

    È possibile sbloccare un file utilizzato da un altro processo? Non è sempre sicuro e non è così facile, ma sì, è possibile.

    • Non so che cosa è sbagliato con il mio codice, io uso l’uso di blocchi, ma c’è ancora un errore dicendo che il file è in uso quando cerco di eliminarlo.
    • È possibile postare una domanda che…
    • No, voglio capire leggendo altre Domande
    • No, in Realtà ho un timer di controllo facendo che, accanto al timer, se mi chiama di nuovo la funzione verrà generata un’eccezione. fondamentalmente sono decifrare un file in un altro file di testo, dopo di che eliminare il file appena creato, che getta l’eccezione relativa alla cancellazione!
    • Perché creare un file contenuti nel codice, quindi eliminarlo? Sembra strano per creare il file, in primo luogo, quindi. Siccome non postare il codice, non sappiamo di che cosa si sta facendo. Ma quando si crea il file, se lo si fa con File.Create(path), si dovrebbe aggiungere .Close() alla fine prima di scrivere. Ci sono delle trappole come che, oltre a using istruzioni per la scrittura dei file, quindi l’eliminazione dopo di loro. Dovresti postare il codice in questione, per come la creazione di & l’eliminazione di file. Ma probabilmente cade in linea con qualcosa di cui sopra.
    • Il mio codice utilizza Directory.SetCreationTimeUTC() ma fallisce quando Esplora File è aperto, sostenendo che la directory è utilizzato da un altro processo. Come posso gestire questa situazione?
    • Direi che è necessario attendere fino a che la cartella è stata chiusa, se non un paio di secondi cosa, allora tutto diventerà presto complesso (mantenere uno sfondo di coda con le operazioni in sospeso? File system watcher? Polling?) È possibile postare una domanda con più dettagli per un ad-hoc per la risposta

  2. 18

    Utilizzando FileShare risolto il mio problema di apertura del file, anche se è aperto da un altro processo.

    using (var stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.ReadWrite))
    {
    }
  3. 7

    Avuto un problema durante il caricamento di un’immagine e non riuscivo a cancellarlo e a trovare una soluzione. gl hf

    //C# .NET
    var image = Image.FromFile(filePath);
    
    image.Dispose(); //this removes all resources
    
    //later...
    
    File.Delete(filePath); //now works
    • Se si elimina un file, è necessario eliminare l’immagine in oggetto.
    • Bello, ho guardato per questa soluzione. Ho avuto anche un problema con l’Immagine.FromFile funzione.
    • np
  4. 3

    Ho ottenuto questo errore perché stavo facendo File.Spostare il percorso di un file senza un nome di file, è necessario specificare il percorso completo della destinazione.

    • E non solo, senza un nome di file sia. Illegale (destinazione) nome file, nel mio caso “…\file.” – darò questo stesso stupido errore e puntare nella direzione sbagliata per mezza giornata!
  5. 1

    Ho avuto il seguente scenario che è stata la causa dell’errore stesso:

    • Caricare file sul server
    • Poi sbarazzarsi del vecchio file dopo che sono stati caricati

    La maggior parte dei file sono di piccole dimensioni, tuttavia, alcuni erano grandi, e quindi si tenta di eliminare chi ha provocato il non possono accedere al file errore.

    Non era facile da trovare, tuttavia, la soluzione era così semplice come In attesa “per il completamento dell’attività di esecuzione”:

    using (var wc = new WebClient())
    {
       var tskResult = wc.UploadFileTaskAsync(_address, _fileName);
       tskResult.Wait(); 
    }
  6. 0

    Altre risposte in questo thread hanno sottolineato, per risolvere questo errore è necessario ispezionare attentamente il codice, per capire dove il file è sempre bloccato.

    Nel mio caso, mi è stato di inviare il file come allegato e-mail prima di effettuare l’operazione di spostamento.

    In modo che il file ha bloccato per un paio di secondi fino a quando il client SMTP termine di invio della e-mail.

    La soluzione che ho adottato è stato di spostare il file di prima, e quindi inviare l’e-mail. Questo ha risolto il problema per me.

    Un’altra soluzione possibile, come sottolineato in precedenza da Hudson, sarebbe stato per smaltire l’oggetto dopo l’uso.

    public static SendEmail()
    {
               MailMessage mMailMessage = new MailMessage();
               //setup other email stuff
    
                if (File.Exists(attachmentPath))
                {
                    Attachment attachment = new Attachment(attachmentPath);
                    mMailMessage.Attachments.Add(attachment);
                    attachment.Dispose(); //disposing the Attachment object
                }
    } 
    • Se un file è in uso File.Move() non lavoro & dà lo stesso errore. Se solo l’aggiunta di un file a un messaggio e-mail non credo errori quando in uso durante il Attachments.Add() operazione perché questo è solo un operazione di copia. Se per qualche motivo si potrebbe copiare una directory Temp, allegare la copia, & eliminare il file copiato in seguito. Ma non credo, se l’OP vuole modificare un file & utilizzare, che questo tipo di soluzione (che non mostra il codice, solo il collegamento di parte) avrebbe funzionato. .Dispose() è sempre una buona idea, ma qui non rilevante, a meno che il file è aperto in un precedente op.
  7. 0

    L’errore indica un altro processo sta tentando di accedere al file. Forse tu o qualcun altro ha aperto mentre si sta tentando di scrivere. “Leggere” o “Copia” di solito non causa questo, ma la scrittura o la chiamata di eliminare avrebbe.

    Ci sono alcune cose di base per evitare questo, come altre risposte hanno detto:

    1. In FileStream operazioni, inserire in un using blocco con un FileShare.ReadWrite modalità di accesso.

      Per esempio:

      using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.ReadWrite))
      {
      }

      Nota che FileAccess.ReadWrite non è possibile se si utilizza FileMode.Append.

    2. Mi sono imbattuto in questo problema quando stavo usando un flusso di input per fare un File.SaveAs quando il file è in uso. Nel mio caso ho trovato, in effetti non ho bisogno di salvare di nuovo il file di sistema, così ho finito solo la rimozione, ma probabilmente ho potuto ho cercato di creare un FileStream in un using dichiarazione con FileAccess.ReadWrite, come il codice di cui sopra.

    3. Salvare i dati come file diverso e tornare indietro per cancellare il vecchio quando si trova ad essere non più in uso, quindi rinominare quello che ha salvato con successo il nome originale è un’opzione. Come test per il file utilizzato è realizzato attraverso l’

      List<Process> lstProcs = ProcessHandler.WhoIsLocking(file);

      riga di codice riportato di seguito, e potrebbe essere fatto in un servizio di Windows, in un ciclo, se si dispone di un particolare file che si desidera guardare e eliminare regolarmente quando si vuole sostituire. Se non hanno sempre lo stesso file, un file di testo o tabella di database può essere aggiornato che il servizio controlla sempre la presenza di nomi di file, e quindi esegue il check per i processi & successivamente si esegue il processo di uccisioni e di eliminazione su di esso, come ho descritto nell’opzione successiva. Si noti che avrete bisogno di un account nome utente e una password che dispone di privilegi di Amministratore sul computer, naturalmente, per effettuare la cancellazione e la conclusione dei processi.

    4. Quando non sai se un file è in uso quando si sta cercando di salvarla, è possibile chiudere tutti i processi che potrebbero essere, come in Word, se si tratta di un documento di Word, davanti a salvare.

      Se è locale, si può fare questo:

      ProcessHandler.localProcessKill("winword.exe");

      Se è remoto, si può fare questo:

      ProcessHandler.remoteProcessKill(computerName, txtUserName, txtPassword, "winword.exe");

      dove txtUserName è in forma di DOMAIN\user.

    5. Diciamo che non so il nome del processo che blocca il file. Quindi, si può fare questo:

      List<Process> lstProcs = new List<Process>();
      lstProcs = ProcessHandler.WhoIsLocking(file);
      
      foreach (Process p in lstProcs)
      {
          if (p.MachineName == ".")
              ProcessHandler.localProcessKill(p.ProcessName);
          else
              ProcessHandler.remoteProcessKill(p.MachineName, txtUserName, txtPassword, p.ProcessName);
      }

      Nota che file deve essere il percorso UNC: \\computer\share\yourdoc.docx in ordine per il Process per capire che cosa il computer è acceso e p.MachineName per essere valido.

      Sotto è la classe di queste funzioni, che richiede l’aggiunta di un riferimento a System.Management. Il codice è stato originariamente scritto da Eric J.:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      using System.Runtime.InteropServices;
      using System.Diagnostics;
      using System.Management;
      
      namespace MyProject
      {
          public static class ProcessHandler
          {
              [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;
              }
      
              public static void remoteProcessKill(string computerName, string userName, string pword, string processName)
              {
                  var connectoptions = new ConnectionOptions();
                  connectoptions.Username = 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();
                      }
                  }            
              }
      
              public static void localProcessKill(string processName)
              {
                  foreach (Process p in Process.GetProcessesByName(processName))
                  {
                      p.Kill();
                  }
              }
      
              [DllImport("kernel32.dll")]
              public static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, int dwFlags);
      
              public const int MOVEFILE_DELAY_UNTIL_REBOOT = 0x4;
      
          }
      }
  8. -1

    Si può anche fare in questo modo,

    prima volta che l’ho usato per fare, come un filo.il sonno, ma si è sbagliato.

    if (System.IO.File.Exists(filePath))
                            {
                                System.GC.Collect();
                                System.GC.WaitForPendingFinalizers();
                                //System.Threading.Thread.Sleep(100);
                                System.IO.File.Delete(filePath);
                                //System.Threading.Thread.Sleep(20);
                            }
                            using (FileStream FS = new FileStream(filePath, FileMode.Create))
                            {
                                ObjModel.CategoryImage.CopyTo(FS);
                            }

Lascia un commento