Skip to content

Commit f43c9e4

Browse files
authored
Fixed an issue that would occur when network drives were disconnected (#2205)
1 parent 2c6d6be commit f43c9e4

File tree

5 files changed

+79
-38
lines changed

5 files changed

+79
-38
lines changed

Common/Extensions.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Threading;
5+
using System.Threading.Tasks;
46

57
namespace Files.Common
68
{
@@ -48,5 +50,24 @@ public static DateTime ToDateTime(this System.Runtime.InteropServices.ComTypes.F
4850
return DateTime.FromFileTimeUtc(0xFFFFFFFF);
4951
}
5052
}
53+
54+
public static async Task WithTimeout(this Task task,
55+
TimeSpan timeout)
56+
{
57+
if (task == await Task.WhenAny(task, Task.Delay(timeout)))
58+
{
59+
await task;
60+
}
61+
}
62+
63+
public static async Task<T> WithTimeout<T>(this Task<T> task,
64+
TimeSpan timeout)
65+
{
66+
if (task == await Task.WhenAny(task, Task.Delay(timeout)))
67+
{
68+
return await task;
69+
}
70+
return default(T);
71+
}
5172
}
5273
}

Files.Launcher/Program.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ private static void Main(string[] args)
6464
foreach (var drive in DriveInfo.GetDrives())
6565
{
6666
var recycle_path = Path.Combine(drive.Name, "$Recycle.Bin", sid);
67-
if (!Directory.Exists(recycle_path))
67+
if (drive.DriveType == DriveType.Network || !Directory.Exists(recycle_path))
6868
{
6969
continue;
7070
}
@@ -83,7 +83,7 @@ private static void Main(string[] args)
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;
86-
using var _ = Win32API.ContextMenu.GetContextMenuForFiles(new string[] { preloadPath }, Shell32.CMF.CMF_NORMAL);
86+
using var _ = Win32API.ContextMenu.GetContextMenuForFiles(new string[] { preloadPath }, Shell32.CMF.CMF_NORMAL | Shell32.CMF.CMF_SYNCCASCADEMENU, FilterMenuItems(false));
8787

8888
// Connect to app service and wait until the connection gets closed
8989
appServiceExit = new AutoResetEvent(false);
@@ -324,7 +324,7 @@ private static object HandleMenuMessage(ValueSet message, Win32API.DisposableDic
324324
var showOpenMenu = (bool)message["ShowOpenMenu"];
325325
var split = filePath.Split('|').Where(x => !string.IsNullOrWhiteSpace(x));
326326
var cMenuLoad = Win32API.ContextMenu.GetContextMenuForFiles(split.ToArray(),
327-
extendedMenu ? Shell32.CMF.CMF_EXTENDEDVERBS : Shell32.CMF.CMF_NORMAL, FilterMenuItems(showOpenMenu));
327+
(extendedMenu ? Shell32.CMF.CMF_EXTENDEDVERBS : Shell32.CMF.CMF_NORMAL) | Shell32.CMF.CMF_SYNCCASCADEMENU, FilterMenuItems(showOpenMenu));
328328
table.SetValue("MENU", cMenuLoad);
329329
return cMenuLoad;
330330

Files/Filesystem/DriveItem.cs

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
using ByteSizeLib;
2+
using Files.Common;
23
using Files.Helpers;
4+
using Microsoft.Toolkit.Mvvm.ComponentModel;
35
using Microsoft.Toolkit.Uwp.Extensions;
46
using System;
7+
using System.Linq;
8+
using System.Threading;
59
using System.Threading.Tasks;
610
using Windows.Storage;
711
using Windows.UI.Xaml;
812

913
namespace Files.Filesystem
1014
{
11-
public class DriveItem : INavigationControlItem
15+
public class DriveItem : ObservableObject, INavigationControlItem
1216
{
1317
public string Glyph { get; set; }
1418
public string Text { get; set; }
@@ -18,7 +22,6 @@ public class DriveItem : INavigationControlItem
1822
public ByteSize MaxSpace { get; set; }
1923
public ByteSize FreeSpace { get; set; }
2024
public ByteSize SpaceUsed { get; set; }
21-
public string SpaceText { get; set; }
2225
public Visibility ItemVisibility { get; set; } = Visibility.Visible;
2326

2427
private DriveType _type;
@@ -33,6 +36,13 @@ public DriveType Type
3336
}
3437
}
3538

39+
private string _spaceText;
40+
public string SpaceText
41+
{
42+
get => _spaceText;
43+
set => SetProperty(ref _spaceText, value);
44+
}
45+
3646
public DriveItem()
3747
{
3848
ItemType = NavigationControlItemType.OneDrive;
@@ -44,31 +54,26 @@ public DriveItem(StorageFolder root, DriveType type)
4454
Type = type;
4555
Path = string.IsNullOrEmpty(root.Path) ? $"\\\\?\\{root.Name}\\" : root.Path;
4656
Root = root;
57+
GetDriveItemProperties();
58+
}
4759

48-
var properties = Task.Run(async () =>
60+
private async void GetDriveItemProperties()
61+
{
62+
try
4963
{
50-
return await root.Properties.RetrievePropertiesAsync(new[] { "System.FreeSpace", "System.Capacity" });
51-
}).Result;
64+
var properties = await Root.Properties.RetrievePropertiesAsync(new[] { "System.FreeSpace", "System.Capacity" })
65+
.AsTask().WithTimeout(TimeSpan.FromSeconds(5));
5266

53-
if (properties.ContainsKey("System.Capacity") && properties.ContainsKey("System.FreeSpace"))
54-
{
55-
try
56-
{
57-
MaxSpace = ByteSize.FromBytes((ulong)properties["System.Capacity"]);
58-
FreeSpace = ByteSize.FromBytes((ulong)properties["System.FreeSpace"]);
59-
60-
SpaceUsed = MaxSpace - FreeSpace;
61-
SpaceText = string.Format(
62-
"DriveFreeSpaceAndCapacity".GetLocalized(),
63-
FreeSpace.ToBinaryString().ConvertSizeAbbreviation(),
64-
MaxSpace.ToBinaryString().ConvertSizeAbbreviation());
65-
}
66-
catch (NullReferenceException)
67-
{
68-
SpaceText = "DriveCapacityUnknown".GetLocalized();
69-
}
67+
MaxSpace = ByteSize.FromBytes((ulong)properties["System.Capacity"]);
68+
FreeSpace = ByteSize.FromBytes((ulong)properties["System.FreeSpace"]);
69+
70+
SpaceUsed = MaxSpace - FreeSpace;
71+
SpaceText = string.Format(
72+
"DriveFreeSpaceAndCapacity".GetLocalized(),
73+
FreeSpace.ToBinaryString().ConvertSizeAbbreviation(),
74+
MaxSpace.ToBinaryString().ConvertSizeAbbreviation());
7075
}
71-
else
76+
catch (NullReferenceException)
7277
{
7378
SpaceText = "DriveCapacityUnknown".GetLocalized();
7479
}

Files/UserControls/SidebarControl.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979
IsRightTapEnabled="True"
8080
RightTapped="NavigationViewDriveItem_RightTapped"
8181
Tag="{x:Bind Path}"
82-
ToolTipService.ToolTip="{x:Bind SpaceText}"
82+
ToolTipService.ToolTip="{x:Bind SpaceText, Mode=OneWay}"
8383
Visibility="{x:Bind ItemVisibility}">
8484
<muxc:NavigationViewItem.Icon>
8585
<FontIcon

Files/View Models/ItemViewModel.cs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -679,8 +679,10 @@ public async void RapidAddItemsToCollectionAsync(string path)
679679
}
680680
else
681681
{
682-
await EnumerateItemsFromStandardFolder(path);
683-
WatchForDirectoryChanges(path);
682+
if (await EnumerateItemsFromStandardFolder(path))
683+
{
684+
WatchForDirectoryChanges(path);
685+
}
684686
}
685687

686688
if (FilesAndFolders.Count == 0)
@@ -783,7 +785,7 @@ public async Task EnumerateItemsFromSpecialFolder(string path)
783785
}
784786
}
785787

786-
public async Task EnumerateItemsFromStandardFolder(string path)
788+
public async Task<bool> EnumerateItemsFromStandardFolder(string path)
787789
{
788790
// Flag to use FindFirstFileExFromApp or StorageFolder enumeration
789791
bool enumFromStorageFolder = false;
@@ -796,15 +798,15 @@ public async Task EnumerateItemsFromStandardFolder(string path)
796798
{
797799
var consentDialogDisplay = new ConsentDialog();
798800
await consentDialogDisplay.ShowAsync(ContentDialogPlacement.Popup);
799-
return;
801+
return false;
800802
}
801803
catch (FileNotFoundException)
802804
{
803805
await DialogDisplayHelper.ShowDialog(
804806
"FolderNotFoundDialog/Title".GetLocalized(),
805807
"FolderNotFoundDialog/Text".GetLocalized());
806808
IsLoadingItems = false;
807-
return;
809+
return false;
808810
}
809811
catch (Exception e)
810812
{
@@ -817,7 +819,7 @@ await DialogDisplayHelper.ShowDialog(
817819
{
818820
await DialogDisplayHelper.ShowDialog("DriveUnpluggedDialog/Title".GetLocalized(), e.Message);
819821
IsLoadingItems = false;
820-
return;
822+
return false;
821823
}
822824
}
823825

@@ -873,13 +875,18 @@ await DialogDisplayHelper.ShowDialog(
873875
FileSizeBytes = 0
874876
};
875877
await EnumFromStorageFolder();
878+
return true;
876879
}
877880
else
878881
{
879-
FINDEX_INFO_LEVELS findInfoLevel = FINDEX_INFO_LEVELS.FindExInfoBasic;
880-
int additionalFlags = FIND_FIRST_EX_LARGE_FETCH;
881-
IntPtr hFile = FindFirstFileExFromApp(path + "\\*.*", findInfoLevel, out WIN32_FIND_DATA findData, FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero,
882-
additionalFlags);
882+
(IntPtr hFile, WIN32_FIND_DATA findData) = await Task.Run(() =>
883+
{
884+
FINDEX_INFO_LEVELS findInfoLevel = FINDEX_INFO_LEVELS.FindExInfoBasic;
885+
int additionalFlags = FIND_FIRST_EX_LARGE_FETCH;
886+
IntPtr hFileTsk = FindFirstFileExFromApp(path + "\\*.*", findInfoLevel, out WIN32_FIND_DATA findDataTsk, FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero,
887+
additionalFlags);
888+
return (hFileTsk, findDataTsk);
889+
}).WithTimeout(TimeSpan.FromSeconds(5));
883890

884891
DateTime itemDate = DateTime.UtcNow;
885892
try
@@ -909,9 +916,16 @@ await DialogDisplayHelper.ShowDialog(
909916
};
910917

911918
var count = 0;
912-
if (hFile.ToInt64() == -1)
919+
if (hFile == IntPtr.Zero)
920+
{
921+
await DialogDisplayHelper.ShowDialog("DriveUnpluggedDialog/Title".GetLocalized(), "");
922+
IsLoadingItems = false;
923+
return false;
924+
}
925+
else if (hFile.ToInt64() == -1)
913926
{
914927
await EnumFromStorageFolder();
928+
return false;
915929
}
916930
else
917931
{
@@ -945,6 +959,7 @@ await DialogDisplayHelper.ShowDialog(
945959
} while (FindNextFile(hFile, out findData));
946960

947961
FindClose(hFile);
962+
return true;
948963
}
949964
}
950965
}

0 commit comments

Comments
 (0)