Skip to content

Fix pnputil empty rows, unknown size display and GetFinalPathName - #483

Merged
lostindark merged 3 commits into
lostindark:masterfrom
indep-arg:pr/small-fixes
Oct 27, 2026
Merged

lostindark merged 3 commits into
lostindark:masterfrom
indep-arg:pr/small-fixes

Conversation

@indep-arg

Copy link
Copy Markdown
Contributor

Three unrelated small bugs, one commit each:

  • pnputil parsing: before adding an entry, the parser compared it with default(DriverStoreEntry). That's null for a class, so the check was always true and two blank lines in a row added an empty row. Added a test that fails without the fix.
  • Unknown size: with the PnpUtil backend, a package whose folder can't be found has size -1. It was shown as "1 KB" (anything under 1024 bytes was) and subtracted from the selected total. It's now shown blank and left out of the total, and 0 shows as "0 KB".
  • GetFinalPathName: used when Rapr.exe is a symlink, like the one WinGet puts in its Links folder. It checked result < 0, but the API returns 0 on failure and the needed size when the buffer is too small. It also turned \\?\UNC\server\share into UNC\server\share. Added a test for the prefix handling.

The check before adding a parsed entry compared it with
default(DriverStoreEntry). DriverStoreEntry is a class, so that is null
and the check was always true: two blank lines in a row added an empty
row to the list. Check for a published name instead, as the end of the
method already does.
When the PnpUtil backend can't find a package's folder its size is -1.
GetBytesReadable printed that as "1 KB" (anything under 1024 bytes did),
and the selected-drivers total subtracted it. Show nothing for an unknown
size, "0 KB" for zero, and leave unknown sizes out of the total.
GetApplicationFolder resolves the real path when Rapr.exe is a symlink,
e.g. the one WinGet creates in its Links folder. The helper treated a
negative return value as failure, but GetFinalPathNameByHandle returns 0
on failure and the required size when the buffer is too small, so
neither case was handled. Stripping the \\?\ prefix also turned
\\?\UNC\server\share into UNC\server\share instead of \\server\share.
@lostindark
lostindark merged commit eb42fa9 into lostindark:master Oct 27, 2026
2 checks passed
@indep-arg

Copy link
Copy Markdown
Contributor Author

@lostindark Heads up: the master CI run after #483 didn't fail on a test. The test host crashed with an OutOfMemoryException after 72 tests had passed, and the same commit passed all 109 on AppVeyor. Looks like a flaky crash on the runner; a re-run should go through.

indep-arg added a commit to indep-arg/DriverStoreExplorer that referenced this pull request Oct 27, 2026
Since lostindark#483 was merged, the GitHub Actions test step crashed twice with
the test host dying inside a WinForms window callback
(NativeWindow.Callback -> WndProcException -> OnThreadException), once
with an OutOfMemoryException and once with an AccessViolationException.
No test failed; the same commit passes all tests on AppVeyor.

DSEFormTests is the only class that creates controls and pumps window
messages, and it ran in parallel with the other test classes. Mark it
DoNotParallelize so it runs after them on its own.
@indep-arg

Copy link
Copy Markdown
Contributor Author

fix ci here: #486

lostindark pushed a commit that referenced this pull request Oct 27, 2026
* Set the GitHub request headers once

GetLatestVersionInfo added the Accept and User-Agent headers to the
shared HttpClient on every call, so each time the About box checked for
updates the headers grew another copy. Set them when the client is
created.

* Fail the update download on an HTTP error status

DownloadAsync didn't check the response status, so a 404 or 500 page
was written to the update zip and only failed later as a hash mismatch
or a broken archive. Throw on a non-success status instead.

* Don't redirect winget's stderr without reading it

RunCommandAsync redirected stderr but only read stdout. If winget wrote
more to stderr than the pipe buffer holds, it would block and
WaitForExit would never return. Stderr isn't used, so stop redirecting
it.

* Replace Newtonsoft.Json with DataContractJsonSerializer

Newtonsoft.Json was only used to read three fields from the GitHub
release response, but it is embedded in Rapr.exe and adds about 700 KB.
Read the response with DataContractJsonSerializer, which is part of .NET
Framework. The parsing moves into ParseLatestRelease so it can be tested
without network access. Behavior is unchanged.

* Pick the update zip by name instead of the first release asset

The update check used assets[0]. That only works while the release has a
single asset; adding anything else (a checksum file, symbols) could make
the updater download the wrong file. Look for the
DriverStoreExplorer-*.zip that release.yml uploads.

* Refuse to install an update that has no SHA-256 digest

The downloaded zip was only checked when GitHub's release response
included a digest for it; without one, it was installed unchecked. Since
the app runs elevated, stop before downloading when there is no digest.
Releases published since GitHub added asset digests always have one.

* Run the WinForms tests on their own

Since #483 was merged, the GitHub Actions test step crashed twice with
the test host dying inside a WinForms window callback
(NativeWindow.Callback -> WndProcException -> OnThreadException), once
with an OutOfMemoryException and once with an AccessViolationException.
No test failed; the same commit passes all tests on AppVeyor.

DSEFormTests is the only class that creates controls and pumps window
messages, and it ran in parallel with the other test classes. Mark it
DoNotParallelize so it runs after them on its own.
@indep-arg
indep-arg deleted the pr/small-fixes branch October 28, 2026 01:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants