diff --git a/Rapr/DSEForm.cs b/Rapr/DSEForm.cs index 8af08f2..fd82fd7 100644 --- a/Rapr/DSEForm.cs +++ b/Rapr/DSEForm.cs @@ -611,7 +611,17 @@ private async void ButtonAddDriver_Click(object sender, EventArgs e) string infPath = dialog.FileName; bool installDriver = this.cbAddInstall.Checked; - var infFiles = FindInfFile(infPath).ToList(); + List infFiles; + try + { + infFiles = FindInfFile(infPath).ToList(); + } + catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException || ex is SecurityException) + { + // e.g. a subfolder we can't read, or a path that is too long in a deep driver bundle. + this.ShowStatus(Status.Error, ex.Message, ex.ToString(), true); + return; + } if (infFiles.Count == 0) { @@ -766,8 +776,12 @@ private void ContextMenuStrip_Opening(object sender, CancelEventArgs e) this.ctxMenuSelect.Enabled = true; this.ctxMenuOpenDeviceProperties.Enabled = !string.IsNullOrEmpty((this.lstDriverStoreEntries.SelectedObject as DriverStoreEntry)?.DeviceId); - this.ctxMenuOpenFolder.Enabled = this.lstDriverStoreEntries.SelectedObjects.Count == 1; - this.ctxMenuCopyFolderPath.Enabled = this.lstDriverStoreEntries.SelectedObjects.Count == 1; + + // The folder is unknown when the PnpUtil backend can't match the package to the driver store. + bool hasFolder = this.lstDriverStoreEntries.SelectedObjects.Count == 1 + && !string.IsNullOrEmpty((this.lstDriverStoreEntries.SelectedObject as DriverStoreEntry)?.DriverFolderLocation); + this.ctxMenuOpenFolder.Enabled = hasFolder; + this.ctxMenuCopyFolderPath.Enabled = hasFolder; } else { @@ -1003,7 +1017,7 @@ private void ExportDriverList(IEnumerable objects) this.ShowStatus(Status.Normal, message, usePopup: true); } } - catch (Exception ex) when (ex is IOException || ex is SecurityException) + catch (Exception ex) when (ex is IOException || ex is SecurityException || ex is UnauthorizedAccessException) { this.ShowStatus(Status.Error, string.Format(Language.Export_Failed, ex), usePopup: true); } @@ -1020,6 +1034,10 @@ private void SwitchCulture(object sender, EventArgs e) { byte[] driverStoreViewState = this.lstDriverStoreEntries.SaveState(); + // SaveState/RestoreState only keep the primary sort column, so carry the secondary one over by hand. + int secondarySortColumnIndex = this.lstDriverStoreEntries.AllColumns.IndexOf(this.lstDriverStoreEntries.SecondarySortColumn); + SortOrder secondarySortOrder = this.lstDriverStoreEntries.SecondarySortOrder; + Thread.CurrentThread.CurrentCulture = ci; Thread.CurrentThread.CurrentUICulture = ci; @@ -1034,6 +1052,13 @@ private void SwitchCulture(object sender, EventArgs e) this.RightToLeftLayout = ci.TextInfo.IsRightToLeft; this.SetupListViewColumns(); this.lstDriverStoreEntries.RestoreState(driverStoreViewState); + + if (secondarySortColumnIndex >= 0) + { + this.lstDriverStoreEntries.SecondarySortColumn = this.lstDriverStoreEntries.AllColumns[secondarySortColumnIndex]; + this.lstDriverStoreEntries.SecondarySortOrder = secondarySortOrder; + } + this.lstDriverStoreEntries.RightToLeft = this.RightToLeft; this.lstDriverStoreEntries.RightToLeftLayout = this.RightToLeftLayout; this.UpdateDriverStore(this.driverStore); @@ -1131,8 +1156,17 @@ private void DSEForm_FormClosing(object sender, FormClosingEventArgs e) { Settings.Default.DriverStoreViewState = Convert.ToBase64String(this.lstDriverStoreEntries.SaveState()); - Settings.Default.WindowState = this.WindowState; - Settings.Default.WindowLocation = this.Location; + if (this.WindowState == FormWindowState.Minimized) + { + // Don't reopen minimized, and don't save the off-screen (-32000, -32000) position. + Settings.Default.WindowState = FormWindowState.Normal; + Settings.Default.WindowLocation = this.RestoreBounds.Location; + } + else + { + Settings.Default.WindowState = this.WindowState; + Settings.Default.WindowLocation = this.Location; + } if (this.WindowState == FormWindowState.Normal) { @@ -1221,6 +1255,11 @@ private void CtxMenuOpenFolder_Click(object sender, EventArgs e) if (this.lstDriverStoreEntries.SelectedObject != null) { DriverStoreEntry item = (DriverStoreEntry)this.lstDriverStoreEntries.SelectedObject; + if (string.IsNullOrEmpty(item.DriverFolderLocation)) + { + return; + } + Process.Start("explorer.exe", "/select, " + Path.Combine(item.DriverFolderLocation, item.DriverInfName)); } } @@ -1230,7 +1269,12 @@ private void CtxMenuCopyFolderPath_Click(object sender, EventArgs e) if (this.lstDriverStoreEntries.SelectedObject != null) { DriverStoreEntry item = (DriverStoreEntry)this.lstDriverStoreEntries.SelectedObject; - Clipboard.SetText(item.DriverFolderLocation); + + // Clipboard.SetText throws ArgumentNullException for an empty string. + if (!string.IsNullOrEmpty(item.DriverFolderLocation)) + { + Clipboard.SetText(item.DriverFolderLocation); + } } } @@ -1655,11 +1699,15 @@ private void UpdateSearchFilter() private IEnumerable FindInfFile(string infPath) { - // Search for *.inf files in the current directory + // Search for *.inf files in the current directory. A package folder can hold several INFs, so add them all. var infFiles = Directory.GetFiles(infPath, "*.inf", SearchOption.TopDirectoryOnly); if (infFiles.Length > 0) { - yield return infFiles[0]; + foreach (var infFile in infFiles) + { + yield return infFile; + } + yield break; } diff --git a/Rapr/MyObjectListView.cs b/Rapr/MyObjectListView.cs index 452c2bf..2986415 100644 --- a/Rapr/MyObjectListView.cs +++ b/Rapr/MyObjectListView.cs @@ -28,7 +28,7 @@ protected override void HandleColumnClick(object sender, ColumnClickEventArgs e) newPrimarySortColumn = this.PrimarySortColumn.Index; // Update secondary column when shift key is down. - if (e.Column == this.SecondarySortColumn.Index) + if (this.SecondarySortColumn != null && e.Column == this.SecondarySortColumn.Index) { // Toggle the secondary column sorting direction. this.SecondarySortOrder = (this.SecondarySortOrder == SortOrder.Descending diff --git a/Rapr/Utils/DismUtil.cs b/Rapr/Utils/DismUtil.cs index accb58b..dbf3a2c 100644 --- a/Rapr/Utils/DismUtil.cs +++ b/Rapr/Utils/DismUtil.cs @@ -94,7 +94,7 @@ public List EnumeratePackages() DriverDate = driverPackage.Date, DriverVersion = driverPackage.Version, DriverFolderLocation = Path.GetDirectoryName(driverPackage.OriginalFileName), - DriverSize = DriverStoreRepository.GetFolderSize(new DirectoryInfo(Path.GetDirectoryName(driverPackage.OriginalFileName))), + DriverSize = GetDriverFolderSize(Path.GetDirectoryName(driverPackage.OriginalFileName)), BootCritical = driverPackage.BootCritical, }; @@ -112,6 +112,20 @@ public List EnumeratePackages() : driverStoreEntries; } + private static long GetDriverFolderSize(string driverFolderLocation) + { + // One missing or unreadable folder shouldn't make the whole list fail; NativeDriverStore does the same. + try + { + return DriverStoreRepository.GetFolderSize(new DirectoryInfo(driverFolderLocation)); + } + catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException) + { + Trace.TraceWarning($"Failed to get folder size for '{driverFolderLocation}': {ex}"); + return 0; + } + } + private DismSession GetSession() { switch (this.Type)