Подтвердить что ты не робот

IOException: процесс не может получить доступ к файлу "путь к файлу", поскольку он используется другим процессом

У меня есть код и когда он выполняется, он выдает IOException, говоря, что

Процесс не может получить доступ к файлу 'filename', потому что он используется другой процесс

Что это значит и что я могу сделать с ним?

4b9b3361

Ответ 1

В чем причина?

Сообщение об ошибке довольно ясно: вы пытаетесь получить доступ к файлу, и он недоступен, потому что другой процесс (или даже тот же процесс) что-то делает с ним (и он не позволял использовать общий доступ).

Отладка

Это может быть довольно легко решить (или довольно трудно понять), в зависимости от вашего конкретного сценария. Посмотрим на некоторые.

Ваш процесс доступен только для доступа к этому файлу
Вы уверены, что другой процесс - это ваш собственный процесс. Если вы знаете, что вы открываете этот файл в другой части вашей программы, то прежде всего вам нужно проверить, правильно ли вы закрываете дескриптор файла после каждого использования. Вот пример кода с этой ошибкой:

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

К счастью, FileStream реализует IDisposable, поэтому легко обернуть весь ваш код внутри инструкции using:

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

Этот шаблон также гарантирует, что файл не останется открытым в случае исключений (может быть, причина в том, что файл используется: что-то пошло не так, и никто его не закрыл, см. этот пост для примера).

Если все кажется прекрасным (вы уверены, что всегда закрываете каждый файл, который вы открываете, даже в случае исключений), и у вас есть несколько рабочих потоков, тогда у вас есть два варианта: переработайте свой код для сериализации доступа к файлам (не всегда выполнимый и не всегда требуется) или применить шаблон повтора. Это довольно распространенный шаблон для операций ввода-вывода: вы пытаетесь что-то сделать, а в случае ошибки вы ждете и повторите попытку (спросите себя, почему, например, Windows Shell требует времени, чтобы сообщить вам, что файл используется и не может быть удалена?). В С# это довольно легко реализовать (см. Также более подробные примеры дискового ввода-вывода, сети и доступ к базе данных).

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);
    }
}

Обратите внимание на общую ошибку, которую мы часто видим в StackOverflow:

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

В этом случае ReadAllText() будет терпеть неудачу, потому что файл используется (File.Open() в строке перед). Чтобы открыть файл заранее, это не только лишний, но и неправильный. То же самое относится ко всем функциям File, которые не возвращают дескриптор файла, с которым вы работаете: File.ReadAllText(), File.WriteAllText(), File.ReadAllLines(), File.WriteAllLines() и другие (например, функции File.AppendAllXyz()) будут все открывают и закрывают файл самостоятельно.

Ваш процесс не является единственным для доступа к этому файлу
Если ваш процесс не является единственным для доступа к этому файлу, то взаимодействие может быть сложнее. Шаблон повторения поможет (если файл не должен открываться кем-либо другим, но он есть, то вам нужна утилита, например Process Explorer, чтобы проверить, кто что делает).

Способы избежать

Когда это применимо, всегда используйте с помощью операторов для открытия файлов. Как сказано в предыдущем абзаце, он будет активно помогать вам избежать многих распространенных ошибок (см. этот пост для примера на , как не использовать его).

Если возможно, попробуйте решить, кому принадлежит доступ к определенному файлу, и централизовать доступ с помощью нескольких известных методов. Если, например, у вас есть файл данных, в котором ваша программа читает и записывает, тогда вы должны вставить весь код ввода/вывода внутри одного класса. Это облегчит отладку (потому что вы всегда можете поставить точку останова и посмотреть, кто что делает), а также будет точкой синхронизации (если требуется) для множественного доступа.

Не забывайте, что операции ввода-вывода всегда могут быть провалены, например:

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

Если кто-то удалит файл после File.Exists(), но до File.Delete(), то он выкинет IOException в том месте, где вы можете ошибочно чувствовать себя в безопасности.

Когда это возможно, примените шаблон повтора, и если вы используете FileSystemWatcher, подумайте о переносе действия (потому что вы получите уведомление, но приложение все еще может работать исключительно с этим файлом).

Расширенные сценарии
Это не всегда так просто, поэтому вам может потребоваться предоставить доступ к кому-то другому. Если, например, вы читаете с самого начала и записываете до конца, у вас есть как минимум два варианта.

1) используют один и тот же FileStream с надлежащими функциями синхронизации (поскольку он не является потокобезопасным). См. this и для примера.

2) используйте перечисление FileShare, чтобы указать ОС, чтобы другие процессы (или другие части вашего собственного процесса) могли одновременно обращаться к одному и тому же файлу.

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

В этом примере я показал, как открыть файл для записи и поделиться для чтения; обратите внимание, что при чтении и записи перекрывается, это приводит к undefined или неверным данным. Это ситуация, которая должна решаться при чтении. Также обратите внимание, что это не делает доступ к потоку stream потокобезопасным, поэтому этот объект нельзя обменивать несколькими потоками, если доступ не синхронизирован каким-либо образом (см. Предыдущие ссылки). Доступны другие варианты совместного доступа, и они открывают более сложные сценарии. Подробнее см. MSDN.

В общем случае процессы N могут считывать из одного и того же файла все вместе, но только один должен писать, в контролируемом сценарии вы можете даже разрешать одновременные записи, но это не может быть обобщено в нескольких текстовых абзацах внутри этого ответа.

Можно ли разблокировать файл, используемый другим процессом? Это не всегда безопасно и не так просто, но да, это возможно.

Ответ 2

Использование FileShare исправило мою проблему открытия файла, даже если он открывается другим процессом.

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

Ответ 3

Возникла проблема при загрузке изображения и не удалось удалить его и найти решение. gl hf

//C# .NET
var image = Image.FromFile(filePath);

image.Dispose(); // this removes all resources

//later...

File.Delete(filePath); //now works

Ответ 4

Я получил эту ошибку, потому что я делал File.Move до пути к файлу без имени файла, вам нужно указать полный путь в пункте назначения.

Ответ 5

У меня был следующий сценарий, который вызывал ту же ошибку:

  • Загрузка файлов на сервер
  • Затем избавиться от старых файлов после их загрузки

Большинство файлов были маленькими по размеру, однако некоторые из них были большими, поэтому попытка удалить те, которые привели к невозможности доступа к ошибке файла.

Было нелегко найти, однако, решение было так же просто, как "Ожидание" "для выполнения задачи":

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

Ответ 6

Как указывалось в других ответах в этом потоке, для устранения этой ошибки вам необходимо тщательно проверить код, чтобы понять, где файл заблокирован.

В моем случае я отправлял файл в виде вложения электронной почты перед выполнением операции перемещения.

Таким образом, файл был заблокирован на пару секунд, пока клиент SMTP не завершил отправку электронной почты.

Решение, которое я принял, состояло в том, чтобы перенести файл первым, а затем отправить электронное письмо. Это решило проблему для меня.

Другое возможное решение, как было указано ранее Хадсоном, было бы уничтожить объект после использования.

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
            }
} 

Ответ 7

Ошибка указывает, что другой процесс пытается получить доступ к файлу. Возможно, вы или кто-то еще открываете его, пока вы пытаетесь написать ему. "Чтение" или "Копировать" обычно не вызывает этого, но запись на него или вызов delete на нем будут.

Есть некоторые основные вещи, чтобы избежать этого, как упомянули другие ответы:

  1. В операциях FileStream поместите его в using блок с помощью режима доступа FileShare.ReadWrite.

Ex.

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

Обратите внимание, что FileAccess.ReadWrite невозможен, если вы используете FileMode.Append.

  1. Я столкнулся с этой проблемой, когда я использовал входной поток для File.SaveAs файла File.SaveAs когда файл использовался. В моем случае я обнаружил, что мне фактически не нужно было сохранять его обратно в файловую систему вообще, поэтому я просто удалил это, но я, возможно, попытался создать FileStream в операторе using с FileAccess.ReadWrite, как код выше.

  2. Сохранение ваших данных в виде другого файла и возврат к удалению старого, когда оно больше не используется, переименование того, которое было успешно сохранено на имя исходного, является опцией. Как вы проверяете используемый файл, выполняется через List<Process> lstProcs = ProcessHandler.WhoIsLocking(file); строка в моем коде ниже и может быть выполнена в службе Windows в цикле, если у вас есть определенный файл, который вы хотите регулярно смотреть и удалять, когда хотите его заменить. Если у вас не всегда есть один и тот же файл, может быть обновлен текстовый файл или таблица базы данных, которая всегда проверяет имена файлов, а затем выполняет проверку процессов и затем выполняет процесс убивает и удаляет на нем, как я описываю в следующем варианте. Обратите внимание, что вам потребуется имя пользователя и пароль учетной записи с правами администратора на данном компьютере, конечно, для выполнения удаления и завершения процессов.

    4а. Когда вы не знаете, будет ли файл использоваться, когда вы пытаетесь его сохранить, вы можете закрыть все процессы, которые могут его использовать, например Word, если это документ Word, перед сохранением.

Если это локально, вы можете сделать это:

ProcessHandler.localProcessKill("winword.exe");

Если он удален, вы можете сделать это:

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

где txtUserName находится в форме DOMAIN\user.

4b. Скажем, вы не знаете имя процесса, которое блокирует файл... вы можете сделать это:

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);
}

Обратите внимание, что file должен быть UNC-путём: \\computer\share\yourdoc.docx чтобы Process мог определить, на каком компьютере он и p.MachineName будет действительным. Ниже приведен класс, который использует эти функции, что требует добавления ссылки на System.Management:

    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 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. В операциях FileStream поместите его в блок using с режимом доступа FileShare.ReadWrite.

    Например:

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

    Обратите внимание, что FileAccess.ReadWrite невозможен, если вы используете FileMode.Append.

  2. Я столкнулся с этой проблемой, когда я использовал поток ввода, чтобы сделать File.SaveAs когда файл использовался. В моем случае я обнаружил, что мне вообще не нужно было сохранять его обратно в файловую систему, поэтому я просто удалил его, но, возможно, я мог попытаться создать FileStream в операторе using с FileAccess.ReadWrite, очень похоже на код выше.

  3. Сохраните ваши данные в другом файле и вернитесь, чтобы удалить старый, если он больше не используется, а затем переименовать тот, который успешно сохранен, в имя исходного. Как вы проверяете файл, который используется, осуществляется с помощью

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

    строка в моем коде ниже, и может быть сделано в службе Windows, в цикле, если у вас есть определенный файл, который вы хотите регулярно просматривать и удалять, когда вы хотите заменить его. Если у вас не всегда один и тот же файл, можно обновить текстовый файл или таблицу базы данных, чтобы служба всегда проверяла имена файлов, а затем выполняла эту проверку для процессов и впоследствии выполняла уничтожение и удаление процессов, как я описываю в следующем варианте. Обратите внимание, что вам понадобится имя пользователя и пароль учетной записи, которые имеют права администратора на данном компьютере, конечно, для выполнения удаления и завершения процессов.

  4. Если вы не знаете, будет ли файл использоваться при попытке сохранить его, вы можете закрыть все процессы, которые могут его использовать, например, Word, если это документ Word, до сохранения.

    Если это локально, вы можете сделать это:

    ProcessHandler.localProcessKill("winword.exe");
    

    Если он удаленный, вы можете сделать это:

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

    где txtUserName находится в форме DOMAIN\user.

  5. Допустим, вы не знаете имя процесса, который блокирует файл. Затем вы можете сделать это:

    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);
    }
    

    Обратите внимание, что file должен иметь UNC-путь: \\computer\share\yourdoc.docx чтобы Process мог определить, на каком компьютере он работает, и p.MachineName чтобы быть действительным.

    Ниже приведен класс, используемый этими функциями, который требует добавления ссылки на System.Management. Код был изначально написан Эриком Дж.:

    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 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;
    
        }
    }
    

Ответ 9

Это будет самый простой способ,

if (System.IO.File.Exists(filePath))
    {
     System.IO.File.Delete(filePath);
     System.Threading.Thread.Sleep(20);
    }

Thread.sleep поможет отлично работать, иначе это повлияет на следующий шаг, если мы будем копировать или записывать файл.

Ответ 10

Вы также можете сделать это,

первый раз я делал как thread.sleep, но это было неправильно.

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);
                        }