Skip to content

Commit c4fa834

Browse files
authored
Show which process is locking a file (#8809)
1 parent 135e7a7 commit c4fa834

File tree

11 files changed

+514
-253
lines changed

11 files changed

+514
-253
lines changed

src/Files.Launcher/Helpers/FileUtils.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ static extern int RmGetList(uint dwSessionHandle,
8080
/// http://wyupdate.googlecode.com/svn-history/r401/trunk/frmFilesInUse.cs (no copyright in code at time of viewing)
8181
///
8282
/// </remarks>
83-
static public List<Process> WhoIsLocking(string path)
83+
public static List<Process> WhoIsLocking(string[] resources)
8484
{
8585
string key = Guid.NewGuid().ToString();
8686
List<Process> processes = new List<Process>();
@@ -94,8 +94,6 @@ static public List<Process> WhoIsLocking(string path)
9494
uint pnProcInfo = 0;
9595
uint lpdwRebootReasons = RmRebootReasonNone;
9696

97-
string[] resources = new string[] { path }; // Just checking on one resource.
98-
9997
res = RmRegisterResources(handle, (uint)resources.Length, resources, 0, null, 0, null);
10098

10199
if (res != 0) throw new Exception("Could not register resource.");

src/Files.Launcher/MessageHandlers/FileOperationsHandler.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,31 @@ await Win32API.StartSTATask(() =>
610610
}
611611
break;
612612

613+
case "CheckFileInUse":
614+
{
615+
var fileToCheckPath = ((string)message["filepath"]).Split('|');
616+
var processes = SafetyExtensions.IgnoreExceptions(() => FileUtils.WhoIsLocking(fileToCheckPath), Program.Logger);
617+
if (processes != null)
618+
{
619+
var win32proc = processes.Select(x => new Win32Process()
620+
{
621+
Name = x.ProcessName,
622+
Pid = x.Id,
623+
FileName = x.MainModule?.FileName
624+
}).ToList();
625+
processes.ForEach(x => x.Dispose());
626+
await Win32API.SendMessageAsync(connection, new ValueSet() {
627+
{ "Processes", JsonConvert.SerializeObject(win32proc) }
628+
}, message.Get("RequestID", (string)null));
629+
}
630+
else
631+
{
632+
await Win32API.SendMessageAsync(connection, new ValueSet(),
633+
message.Get("RequestID", (string)null));
634+
}
635+
}
636+
break;
637+
613638
case "ParseLink":
614639
try
615640
{
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
namespace Files.Shared.Enums
2+
{
3+
public struct CopyEngineResult
4+
{
5+
// https://github.com/RickStrahl/DeleteFiles/blob/master/DeleteFiles/ZetaLongPaths/Native/FileOperations/Interop/CopyEngineResult.cs
6+
// Ok
7+
public const int S_OK = 0;
8+
public const int COPYENGINE_S_DONT_PROCESS_CHILDREN = 2555912;
9+
public const int COPYENGINE_E_USER_CANCELLED = -2144927744;
10+
// Access denied
11+
public const int COPYENGINE_E_ACCESS_DENIED_SRC = -2144927711;
12+
public const int COPYENGINE_E_ACCESS_DENIED_DEST = -2144927710;
13+
public const int COPYENGINE_E_REQUIRES_ELEVATION = -2144927742;
14+
// Path too long
15+
public const int COPYENGINE_E_PATH_TOO_DEEP_SRC = -2144927715;
16+
public const int COPYENGINE_E_PATH_TOO_DEEP_DEST = -2144927714;
17+
public const int COPYENGINE_E_RECYCLE_PATH_TOO_LONG = -2144927688;
18+
public const int COPYENGINE_E_NEWFILE_NAME_TOO_LONG = -2144927685;
19+
public const int COPYENGINE_E_NEWFOLDER_NAME_TOO_LONG = -2144927684;
20+
// Not found
21+
public const int COPYENGINE_E_RECYCLE_BIN_NOT_FOUND = -2144927686;
22+
public const int COPYENGINE_E_PATH_NOT_FOUND_SRC = -2144927709;
23+
public const int COPYENGINE_E_PATH_NOT_FOUND_DEST = -2144927708;
24+
public const int COPYENGINE_E_NET_DISCONNECT_DEST = -2144927706;
25+
public const int COPYENGINE_E_NET_DISCONNECT_SRC = -2144927707;
26+
public const int COPYENGINE_E_CANT_REACH_SOURCE = -2144927691;
27+
// File in use
28+
public const int COPYENGINE_E_SHARING_VIOLATION_SRC = -2144927705;
29+
public const int COPYENGINE_E_SHARING_VIOLATION_DEST = -2144927704;
30+
// Already exists
31+
public const int COPYENGINE_E_ALREADY_EXISTS_NORMAL = -2144927703;
32+
public const int COPYENGINE_E_ALREADY_EXISTS_READONLY = -2144927702;
33+
public const int COPYENGINE_E_ALREADY_EXISTS_SYSTEM = -2144927701;
34+
public const int COPYENGINE_E_ALREADY_EXISTS_FOLDER = -2144927700;
35+
// File too big
36+
//public const int COPYENGINE_E_FILE_TOO_LARGE = -2144927731;
37+
//public const int COPYENGINE_E_REMOVABLE_FULL = -2144927730;
38+
//public const int COPYENGINE_E_DISK_FULL = -2144927694;
39+
//public const int COPYENGINE_E_DISK_FULL_CLEAN = -2144927693;
40+
//public const int COPYENGINE_E_RECYCLE_SIZE_TOO_BIG = -2144927689;
41+
// Invalid path
42+
public const int COPYENGINE_E_FILE_IS_FLD_DEST = -2144927732;
43+
public const int COPYENGINE_E_FLD_IS_FILE_DEST = -2144927733;
44+
//public const int COPYENGINE_E_INVALID_FILES_SRC = -2144927717;
45+
//public const int COPYENGINE_E_INVALID_FILES_DEST = -2144927716;
46+
//public const int COPYENGINE_E_SAME_FILE = -2144927741;
47+
//public const int COPYENGINE_E_DEST_SAME_TREE = -2144927734;
48+
//public const int COPYENGINE_E_DEST_SUBTREE = -2144927735;
49+
50+
public static FileSystemStatusCode Convert(int? hres)
51+
{
52+
return hres switch
53+
{
54+
CopyEngineResult.S_OK => FileSystemStatusCode.Success,
55+
CopyEngineResult.COPYENGINE_E_ACCESS_DENIED_SRC => FileSystemStatusCode.Unauthorized,
56+
CopyEngineResult.COPYENGINE_E_ACCESS_DENIED_DEST => FileSystemStatusCode.Unauthorized,
57+
CopyEngineResult.COPYENGINE_E_REQUIRES_ELEVATION => FileSystemStatusCode.Unauthorized,
58+
CopyEngineResult.COPYENGINE_E_RECYCLE_PATH_TOO_LONG => FileSystemStatusCode.NameTooLong,
59+
CopyEngineResult.COPYENGINE_E_NEWFILE_NAME_TOO_LONG => FileSystemStatusCode.NameTooLong,
60+
CopyEngineResult.COPYENGINE_E_NEWFOLDER_NAME_TOO_LONG => FileSystemStatusCode.NameTooLong,
61+
CopyEngineResult.COPYENGINE_E_PATH_TOO_DEEP_SRC => FileSystemStatusCode.NameTooLong,
62+
CopyEngineResult.COPYENGINE_E_PATH_TOO_DEEP_DEST => FileSystemStatusCode.NameTooLong,
63+
CopyEngineResult.COPYENGINE_E_PATH_NOT_FOUND_SRC => FileSystemStatusCode.NotFound,
64+
CopyEngineResult.COPYENGINE_E_PATH_NOT_FOUND_DEST => FileSystemStatusCode.NotFound,
65+
CopyEngineResult.COPYENGINE_E_NET_DISCONNECT_DEST => FileSystemStatusCode.NotFound,
66+
CopyEngineResult.COPYENGINE_E_NET_DISCONNECT_SRC => FileSystemStatusCode.NotFound,
67+
CopyEngineResult.COPYENGINE_E_CANT_REACH_SOURCE => FileSystemStatusCode.NotFound,
68+
CopyEngineResult.COPYENGINE_E_RECYCLE_BIN_NOT_FOUND => FileSystemStatusCode.NotFound,
69+
CopyEngineResult.COPYENGINE_E_ALREADY_EXISTS_NORMAL => FileSystemStatusCode.AlreadyExists,
70+
CopyEngineResult.COPYENGINE_E_ALREADY_EXISTS_READONLY => FileSystemStatusCode.AlreadyExists,
71+
CopyEngineResult.COPYENGINE_E_ALREADY_EXISTS_SYSTEM => FileSystemStatusCode.AlreadyExists,
72+
CopyEngineResult.COPYENGINE_E_ALREADY_EXISTS_FOLDER => FileSystemStatusCode.AlreadyExists,
73+
CopyEngineResult.COPYENGINE_E_FILE_IS_FLD_DEST => FileSystemStatusCode.NotAFile,
74+
CopyEngineResult.COPYENGINE_E_FLD_IS_FILE_DEST => FileSystemStatusCode.NotAFolder,
75+
CopyEngineResult.COPYENGINE_E_SHARING_VIOLATION_SRC => FileSystemStatusCode.InUse,
76+
CopyEngineResult.COPYENGINE_E_SHARING_VIOLATION_DEST => FileSystemStatusCode.InUse,
77+
null => FileSystemStatusCode.Generic,
78+
_ => FileSystemStatusCode.Generic
79+
};
80+
}
81+
}
82+
}

src/Files.Shared/Win32Process.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace Files.Shared
6+
{
7+
public class Win32Process
8+
{
9+
public string Name { get; set; }
10+
public int Pid { get; set; }
11+
public string FileName { get; set; }
12+
}
13+
}

src/Files.Uwp/Extensions/ShellNewEntryExtensions.cs

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -70,30 +70,7 @@ public static async Task<FilesystemResult<BaseStorageFile>> Create(this ShellNew
7070
{
7171
FilesystemResult<BaseStorageFile> createdFile = null;
7272
var fileName = Path.GetFileName(filePath);
73-
if (!fileName.EndsWith(shellEntry.Extension, StringComparison.Ordinal))
74-
{
75-
fileName += shellEntry.Extension;
76-
}
77-
if (shellEntry.Command != null)
78-
{
79-
var args = CommandLine.CommandLineParser.SplitArguments(shellEntry.Command);
80-
if (args.Any())
81-
{
82-
var connection = await AppServiceConnectionHelper.Instance;
83-
if (connection != null)
84-
{
85-
_ = await connection.SendMessageForResponseAsync(new ValueSet()
86-
{
87-
{ "Arguments", "LaunchApp" },
88-
{ "WorkingDirectory", PathNormalization.GetParentDir(filePath) },
89-
{ "Application", args[0].Replace("\"", "", StringComparison.Ordinal) },
90-
{ "Parameters", string.Join(" ", args.Skip(1)).Replace("%1", filePath) }
91-
});
92-
}
93-
}
94-
createdFile = new FilesystemResult<BaseStorageFile>(null, Shared.Enums.FileSystemStatusCode.Success);
95-
}
96-
else if (shellEntry.Template == null)
73+
if (shellEntry.Template == null)
9774
{
9875
createdFile = await FilesystemTasks.Wrap(() => parentFolder.CreateFileAsync(fileName, CreationCollisionOption.GenerateUniqueName).AsTask());
9976
}

0 commit comments

Comments
 (0)