| File: FileLockOwnerFinder.cs | Web Access |
| Project: Microsoft.DotNet.Cli.Utils.csproj (Microsoft.DotNet.Cli.Utils) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. namespace Microsoft.DotNet.Cli.Utils; /// <summary> /// Identifies a process that is reported as holding a file lock. /// </summary> internal sealed record FileLockOwner(int ProcessId, string ProcessName); internal static partial class FileLockOwnerFinder { /// <summary> /// Finds a file lock owner so contention diagnostics can identify the process the user is waiting for. /// </summary> /// <remarks> /// Discovery is best-effort and platform-specific. Unsupported platforms, access restrictions, and process /// lifetime races return <see langword="null"/> rather than affecting the operation that encountered contention. /// </remarks> internal static FileLockOwner? TryGetFileLockOwner(string filePath) { if (string.IsNullOrWhiteSpace(filePath)) { return null; } try { #if TARGET_WINDOWS if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return TryGetWindowsFileLockOwner(filePath); } #endif #if NET if (OperatingSystem.IsLinux()) { return TryGetLinuxFileLockOwner(filePath); } if (OperatingSystem.IsMacOS()) { return TryGetMacOSFileLockOwner(filePath); } #endif } catch (Exception) { // Lock owner discovery is diagnostic only and must not affect the operation. } return null; } /// <summary> /// Bounds and sanitizes an OS-provided process name before including it in terminal output. /// </summary> /// <remarks>Control characters are replaced and names are limited to 256 characters.</remarks> private static string SanitizeProcessName(string processName) => string.Concat(processName.Take(256).Select(character => char.IsControl(character) ? '?' : character)); }