1414#include " Dialogs.h"
1515#include " Main.h"
1616#include < unrar/dll.hpp>
17+ #include < algorithm>
1718#include < optional>
1819#include < memory>
1920#include < filesystem>
@@ -237,7 +238,7 @@ static void GetArchiveFilesInDirectory(const SString& directory, std::vector<Man
237238}
238239
239240/* *
240- * @brief Terminates every process locking a file with the user's consent.
241+ * @brief Tries to clear file locks by terminating other processes with the user's consent.
241242 * @param absolutePath The path to the file to check
242243 * @param displayName Name of the file in the user prompt
243244 * @return True if the file is not locked (anymore), false otherwise
@@ -246,9 +247,27 @@ static bool TerminateFileLockingProcesses(const SString& absolutePath, const SSt
246247{
247248 WString filePath (absolutePath);
248249 std::vector<DWORD> processIds = GetProcessListUsingFile (filePath);
250+ const DWORD currentProcessId = GetCurrentProcessId ();
251+
252+ const auto RemoveCurrentProcessId = [&]() {
253+ const auto newEnd = std::remove (processIds.begin (), processIds.end (), currentProcessId);
254+ const bool removedCurrentProcess = newEnd != processIds.end ();
255+ processIds.erase (newEnd, processIds.end ());
256+ return removedCurrentProcess;
257+ };
258+
259+ const auto FailOnCurrentProcessLock = [&]() {
260+ AddReportLog (5055 , SString (" TerminateFileLockingProcesses: current process %lu is locking '%s'" , currentProcessId, absolutePath.c_str ()));
261+ return false ;
262+ };
249263
250264 while (true )
251265 {
266+ const bool currentProcessLocksFile = RemoveCurrentProcessId ();
267+
268+ if (currentProcessLocksFile)
269+ return FailOnCurrentProcessLock ();
270+
252271 if (processIds.empty ())
253272 return true ;
254273
@@ -274,6 +293,10 @@ static bool TerminateFileLockingProcesses(const SString& absolutePath, const SSt
274293 " MTA: San Andreas" , MB_CANCELTRYCONTINUE | MB_ICONQUESTION | MB_TOPMOST);
275294
276295 processIds = GetProcessListUsingFile (filePath);
296+ const bool currentProcessLocksFileAfterPrompt = RemoveCurrentProcessId ();
297+
298+ if (currentProcessLocksFileAfterPrompt)
299+ return FailOnCurrentProcessLock ();
277300
278301 if (processIds.empty ())
279302 return true ;
@@ -644,7 +667,8 @@ static int RunInstall()
644667 if (files.empty ())
645668 return 0 ;
646669
647- // Check if any executable or library is locked by any process and terminate it with the user's consent.
670+ // Binary replacements can fail after backup work has started, so clear blocking locks before
671+ // any file copy starts.
648672 for (const InstallableFile& file : files)
649673 {
650674 if (file.relativePath .EndsWithI (" .exe" ) || file.relativePath .EndsWithI (" .dll" ))
0 commit comments