/
githubmirror
/
Files
Обзор
Документация
Войти
/
githubmirror
/
Files
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Files.App/Helpers/Win32/Win32Helper.Process.cs
133 строки
4 KB
0x5bfa
Code Quality: Remove manual interop definitions and add agent instructions for this (#18449)
31 май 2026, 18:26
Не верифицирован
31 май 2026, 18:26
6245529
Код
Авторство
О чём код?
// Copyright (c) 2024 Files Community // Licensed under the MIT License. See the LICENSE. using Windows.Win32; using Windows.Win32.Foundation; using Windows.Win32.System.RestartManager; namespace Files.App.Helpers { /// <summary> /// Provides static helper for Win32. /// </summary> public static partial class Win32Helper { public static async Task<bool> InvokeWin32ComponentAsync(string applicationPath, IShellPage associatedInstance, string arguments = null, bool runAsAdmin = false, string workingDirectory = null) { return await InvokeWin32ComponentsAsync(applicationPath.CreateEnumerable(), associatedInstance, arguments, runAsAdmin, workingDirectory); } public static async Task<bool> InvokeWin32ComponentsAsync(IEnumerable<string> applicationPaths, IShellPage associatedInstance, string arguments = null, bool runAsAdmin = false, string workingDirectory = null) { var application = applicationPaths.FirstOrDefault(); if (string.IsNullOrEmpty(workingDirectory) && associatedInstance?.ShellViewModel != null && !associatedInstance.ShellViewModel.IsSearchResults) workingDirectory = associatedInstance.ShellViewModel.WorkingDirectory; if (runAsAdmin) { // TODO In the long run, we should consider modifying HandleApplicationLaunch to handle this correctly. try { ProcessStartInfo startInfo = new ProcessStartInfo { FileName = application, Arguments = arguments, Verb = "runas", WorkingDirectory = workingDirectory, UseShellExecute = true }; Process process = new Process { StartInfo = startInfo }; process.Start(); return true; } catch (Exception) { return false; } } else { return await LaunchHelper.LaunchAppAsync(application, arguments, workingDirectory); } } /// <summary> /// Gets process(es) that have a lock on the specified file. /// </summary> /// <param name="path">Path of the file.</param> /// <returns>Processes locking the file.</returns> /// <remarks> /// For more info, visit /// <br/> /// - <a href="https://learn.microsoft.com/ja-jp/windows/win32/api/restartmanager/nf-restartmanager-rmgetlist"/> /// <br/> /// - <a href="https://stackoverflow.com/questions/317071/how-do-i-find-out-which-process-is-locking-a-file-using-net/317209#317209"/> /// </remarks> public static List<Process> WhoIsLocking(string[] resources) { Span<char> key = stackalloc char[64]; Guid.NewGuid().TryFormat(key, out var charsWritten); key = key[..charsWritten]; List<Process> processes = []; WIN32_ERROR res = PInvoke.RmStartSession(out uint handle, key); if (res != WIN32_ERROR.NO_ERROR) throw new Exception("Could not begin restart session. Unable to determine file locker."); try { uint pnProcInfo = 0; uint lpdwRebootReasons; res = PInvoke.RmRegisterResources(handle, resources, [], []); if (res != WIN32_ERROR.NO_ERROR) 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 = PInvoke.RmGetList(handle, out uint pnProcInfoNeeded, ref pnProcInfo, [], out lpdwRebootReasons); if (res == WIN32_ERROR.ERROR_MORE_DATA) { // Create an array to store the process results var processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded]; pnProcInfo = pnProcInfoNeeded; // Get the list res = PInvoke.RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, out lpdwRebootReasons); if (res == WIN32_ERROR.NO_ERROR) { 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((int)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 != WIN32_ERROR.NO_ERROR) throw new Exception("Could not list processes locking resource. Failed to get size of result."); } finally { _ = PInvoke.RmEndSession(handle); } return processes; } } }