Skip to content

Commit 9e5c509

Browse files
authored
Refresh drives list when mounting/unmounting ISO file (#2406)
1 parent a2f2596 commit 9e5c509

File tree

8 files changed

+329
-103
lines changed

8 files changed

+329
-103
lines changed

Common/DeviceEvent.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace Files.Common
6+
{
7+
public enum DeviceEvent
8+
{
9+
Added,
10+
Removed,
11+
Inserted,
12+
Ejected
13+
}
14+
}

Files.Launcher/DeviceWatcher.cs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
using Files.Common;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Management;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using Windows.ApplicationModel.AppService;
9+
using Windows.Foundation.Collections;
10+
11+
namespace FilesFullTrust
12+
{
13+
public class DeviceWatcher : IDisposable
14+
{
15+
private ManagementEventWatcher insertWatcher, removeWatcher, modifyWatcher;
16+
private AppServiceConnection connection;
17+
18+
private const string WpdGuid = "{6ac27878-a6fa-4155-ba85-f98f491d4f33}";
19+
20+
public DeviceWatcher(AppServiceConnection connection)
21+
{
22+
this.connection = connection;
23+
}
24+
25+
public void Start()
26+
{
27+
WqlEventQuery insertQuery = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_LogicalDisk'");
28+
insertWatcher = new ManagementEventWatcher(insertQuery);
29+
insertWatcher.EventArrived += new EventArrivedEventHandler(DeviceInsertedEvent);
30+
insertWatcher.Start();
31+
32+
WqlEventQuery modifyQuery = new WqlEventQuery("SELECT * FROM __InstanceModificationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_LogicalDisk' and TargetInstance.DriveType = 5");
33+
modifyWatcher = new ManagementEventWatcher(modifyQuery);
34+
modifyWatcher.EventArrived += new EventArrivedEventHandler(DeviceModifiedEvent);
35+
modifyWatcher.Start();
36+
37+
WqlEventQuery removeQuery = new WqlEventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_LogicalDisk'");
38+
removeWatcher = new ManagementEventWatcher(removeQuery);
39+
removeWatcher.EventArrived += new EventArrivedEventHandler(DeviceRemovedEvent);
40+
removeWatcher.Start();
41+
}
42+
43+
private async void DeviceModifiedEvent(object sender, EventArrivedEventArgs e)
44+
{
45+
ManagementBaseObject obj = (ManagementBaseObject)e.NewEvent["TargetInstance"];
46+
var deviceName = (string)obj.Properties["Name"].Value;
47+
var deviceId = (string)obj.Properties["DeviceID"].Value;
48+
var volumeName = (string)obj.Properties["VolumeName"].Value;
49+
var eventType = volumeName != null ? DeviceEvent.Inserted : DeviceEvent.Ejected;
50+
System.Diagnostics.Debug.WriteLine($"Drive modify event: {deviceName}, {deviceId}, {eventType}");
51+
await SendEvent(deviceName, deviceId, eventType);
52+
}
53+
54+
private async void DeviceRemovedEvent(object sender, EventArrivedEventArgs e)
55+
{
56+
ManagementBaseObject obj = (ManagementBaseObject)e.NewEvent["TargetInstance"];
57+
var deviceName = (string)obj.Properties["Name"].Value;
58+
var deviceId = (string)obj.Properties["DeviceID"].Value;
59+
System.Diagnostics.Debug.WriteLine($"Drive removed event: {deviceName}, {deviceId}");
60+
await SendEvent(deviceName, deviceId, DeviceEvent.Removed);
61+
}
62+
63+
private async void DeviceInsertedEvent(object sender, EventArrivedEventArgs e)
64+
{
65+
ManagementBaseObject obj = (ManagementBaseObject)e.NewEvent["TargetInstance"];
66+
var deviceName = (string)obj.Properties["Name"].Value;
67+
var deviceId = (string)obj.Properties["DeviceID"].Value;
68+
System.Diagnostics.Debug.WriteLine($"Drive added event: {deviceName}, {deviceId}");
69+
await SendEvent(deviceName, deviceId, DeviceEvent.Added);
70+
}
71+
72+
private async Task SendEvent(string deviceName, string deviceId, DeviceEvent eventType)
73+
{
74+
if (connection != null)
75+
{
76+
await connection.SendMessageAsync(new ValueSet()
77+
{
78+
{ "DeviceID", deviceId },
79+
{ "EventType", (int)eventType }
80+
});
81+
}
82+
}
83+
84+
public void Dispose()
85+
{
86+
insertWatcher?.Dispose();
87+
removeWatcher?.Dispose();
88+
modifyWatcher?.Dispose();
89+
insertWatcher = null;
90+
removeWatcher = null;
91+
modifyWatcher = null;
92+
}
93+
}
94+
}

Files.Launcher/Files.Launcher.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
</Reference>
117117
<Reference Include="System" />
118118
<Reference Include="System.Core" />
119+
<Reference Include="System.Management" />
119120
<Reference Include="System.Runtime" />
120121
<Reference Include="System.Runtime.InteropServices" />
121122
<Reference Include="System.Threading.Thread" />
@@ -130,6 +131,7 @@
130131
</Reference>
131132
</ItemGroup>
132133
<ItemGroup>
134+
<Compile Include="DeviceWatcher.cs" />
133135
<Compile Include="Program.cs" />
134136
<Compile Include="Properties\AssemblyInfo.cs" />
135137
<Compile Include="QuickLook.cs" />

Files.Launcher/Program.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ private static void Main(string[] args)
5959

6060
// Create filesystem watcher to monitor recycle bin folder(s)
6161
// SHChangeNotifyRegister only works if recycle bin is open in explorer :(
62-
watchers = new List<FileSystemWatcher>();
62+
binWatchers = new List<FileSystemWatcher>();
6363
var sid = System.Security.Principal.WindowsIdentity.GetCurrent().User.ToString();
6464
foreach (var drive in DriveInfo.GetDrives())
6565
{
@@ -77,28 +77,35 @@ private static void Main(string[] args)
7777
watcher.Created += Watcher_Changed;
7878
watcher.Deleted += Watcher_Changed;
7979
watcher.EnableRaisingEvents = true;
80-
watchers.Add(watcher);
80+
binWatchers.Add(watcher);
8181
}
8282

8383
// Preload context menu for better performace
8484
// We query the context menu for the app's local folder
8585
var preloadPath = ApplicationData.Current.LocalFolder.Path;
8686
using var _ = Win32API.ContextMenu.GetContextMenuForFiles(new string[] { preloadPath }, Shell32.CMF.CMF_NORMAL | Shell32.CMF.CMF_SYNCCASCADEMENU, FilterMenuItems(false));
8787

88-
// Connect to app service and wait until the connection gets closed
88+
// Initialize app service
8989
appServiceExit = new AutoResetEvent(false);
9090
InitializeAppServiceConnection();
91+
92+
// Initialize device watcher
93+
deviceWatcher = new DeviceWatcher(connection);
94+
deviceWatcher.Start();
95+
96+
// Wait until the connection gets closed
9197
appServiceExit.WaitOne();
9298
}
9399
finally
94100
{
95101
connection?.Dispose();
96-
foreach (var watcher in watchers)
102+
foreach (var watcher in binWatchers)
97103
{
98104
watcher.Dispose();
99105
}
100106
handleTable?.Dispose();
101107
recycler?.Dispose();
108+
deviceWatcher?.Dispose();
102109
appServiceExit?.Dispose();
103110
mutex?.ReleaseMutex();
104111
}
@@ -141,7 +148,8 @@ private static async void Watcher_Changed(object sender, FileSystemEventArgs e)
141148
private static AutoResetEvent appServiceExit;
142149
private static ShellFolder recycler;
143150
private static Win32API.DisposableDictionary handleTable;
144-
private static IList<FileSystemWatcher> watchers;
151+
private static IList<FileSystemWatcher> binWatchers;
152+
private static DeviceWatcher deviceWatcher;
145153

146154
private static async void InitializeAppServiceConnection()
147155
{

Files/Filesystem/DriveItem.cs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,34 @@ public class DriveItem : ObservableObject, INavigationControlItem
1616
{
1717
public string Glyph { get; set; }
1818
public string Path { get; set; }
19+
public string DeviceID { get; set; }
1920
public StorageFolder Root { get; set; }
2021
public NavigationControlItemType ItemType { get; set; } = NavigationControlItemType.Drive;
21-
public ByteSize MaxSpace { get; set; }
22-
public ByteSize FreeSpace { get; set; }
23-
public ByteSize SpaceUsed { get; set; }
2422
public Visibility ItemVisibility { get; set; } = Visibility.Visible;
2523
public bool IsRemovable { get; set; }
2624

25+
private ByteSize maxSpace;
26+
private ByteSize freeSpace;
27+
private ByteSize spaceUsed;
28+
29+
public ByteSize MaxSpace
30+
{
31+
get => maxSpace;
32+
set => SetProperty(ref maxSpace, value);
33+
}
34+
35+
public ByteSize FreeSpace
36+
{
37+
get => freeSpace;
38+
set => SetProperty(ref freeSpace, value);
39+
}
40+
41+
public ByteSize SpaceUsed
42+
{
43+
get => spaceUsed;
44+
set => SetProperty(ref spaceUsed, value);
45+
}
46+
2747
private DriveType type;
2848

2949
public DriveType Type
@@ -57,22 +77,22 @@ public DriveItem()
5777
ItemType = NavigationControlItemType.OneDrive;
5878
}
5979

60-
public DriveItem(StorageFolder root, DriveType type)
80+
public DriveItem(StorageFolder root, string deviceId, DriveType type)
6181
{
6282
Text = root.DisplayName;
6383
Type = type;
6484
Path = string.IsNullOrEmpty(root.Path) ? $"\\\\?\\{root.Name}\\" : root.Path;
85+
DeviceID = deviceId;
6586
Root = root;
6687
IsRemovable = (Type == DriveType.Removable || Type == DriveType.CDRom);
6788

68-
CoreApplication.MainView.ExecuteOnUIThreadAsync(() => GetDriveItemProperties());
89+
CoreApplication.MainView.ExecuteOnUIThreadAsync(() => UpdatePropertiesAsync());
6990
}
7091

71-
public async Task UpdateAsync()
92+
public async Task UpdateLabelAsync()
7293
{
7394
try
7495
{
75-
// Delay is needed to apply the new name
7696
var properties = await Root.Properties.RetrievePropertiesAsync(new[] { "System.ItemNameDisplay" })
7797
.AsTask().WithTimeoutAsync(TimeSpan.FromSeconds(5));
7898
Text = (string)properties["System.ItemNameDisplay"];
@@ -82,7 +102,7 @@ public async Task UpdateAsync()
82102
}
83103
}
84104

85-
private async void GetDriveItemProperties()
105+
public async Task UpdatePropertiesAsync()
86106
{
87107
try
88108
{
@@ -101,6 +121,7 @@ private async void GetDriveItemProperties()
101121
catch (NullReferenceException)
102122
{
103123
SpaceText = "DriveCapacityUnknown".GetLocalized();
124+
SpaceUsed = ByteSize.FromBytes(0);
104125
}
105126
}
106127

0 commit comments

Comments
 (0)