Skip to content

Windows port — Phase 5: applications (registry + MSIX + winget)#11

Merged
ronylicha merged 6 commits into
masterfrom
feat/win-phase-5
Jun 26, 2026
Merged

Windows port — Phase 5: applications (registry + MSIX + winget)#11
ronylicha merged 6 commits into
masterfrom
feat/win-phase-5

Conversation

@ronylicha

Copy link
Copy Markdown
Member

Phase 5 of the Windows port. Applications tab on Windows: inventory from registry Uninstall keys (winreg) + MSIX/Store (Get-AppxPackage); uninstall (registry UninstallString + Remove-AppxPackage); update detection + best-effort update via winget; frontend source labels.

Security: uninstall re-resolves the command from the registry/Appx by validated id — never executes a caller-supplied command string; MSIX PFN validated (^[A-Za-z0-9._-]+$); protected/unknown refused. PowerShell by absolute System32 path; winget via Command::args (no shell concat). No windows crate, no unsafe (winreg is safe). Linux/macOS unchanged (cfg-gated). Windows runtime = manual-smoke.

@ronylicha ronylicha merged commit 1b3771a into master Jun 26, 2026
6 checks passed
@ronylicha ronylicha deleted the feat/win-phase-5 branch June 26, 2026 22:35

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5e1a0576ac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +393 to +395
const SCRIPT: &str = "Get-AppxPackage | Select-Object Name,PackageFullName,\
@{N='Version';E={$_.Version.ToString()}},InstallLocation,NonRemovable,\
@{N='SignatureKind';E={$_.SignatureKind.ToString()}} | ConvertTo-Json -Compress -Depth 3";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Filter framework packages out of MSIX inventory

On Windows profiles with Store dependency packages, this Get-AppxPackage call includes framework packages by default—Microsoft documents -PackageTypeFilter defaults to Main and Framework (https://learn.microsoft.com/en-us/powershell/module/appx/get-appxpackage). Because the script does not request only Main packages or select/check IsFramework, non-user-facing frameworks can be returned as msix entries with protected: false, so the Applications tab offers them for removal via Remove-AppxPackage; filter with -PackageTypeFilter Main or reject IsFramework entries before adding them.

Useful? React with 👍 / 👎.

Comment on lines +804 to +808
.or_else(|| {
key.get_value::<String, _>("UninstallString")
.ok()
.filter(|s| !s.trim().is_empty())
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Convert MSI install commands before using them as uninstallers

When a registry entry has no QuietUninstallString and its UninstallString is an MSI command such as MsiExec.exe /I{...}, this fallback invokes /I, which Microsoft documents as install/configure while uninstall is /X or /uninstall (https://learn.microsoft.com/en-us/windows/win32/msi/command-line-options). Those entries are common for MSI packages, so choosing Uninstall selected can open repair/change UI or exit without removing the app; normalize MSI product-code commands to /X before executing the fallback.

Useful? React with 👍 / 👎.

};
// The command string comes from the registry (written by the app's own
// installer), never from the caller. Run it via `cmd /C` as one argument.
let mut cmd = Command::new("cmd");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use the system cmd.exe path for registry uninstall

When FreeYourDisk is launched with a user-writable application/current directory, this unqualified cmd lookup can execute a local cmd.exe before the real system command processor; Microsoft documents that Windows process lookup for names without a directory searches the application and current directories before system directories (https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa). Since this path executes installer-authored uninstall commands, use an absolute System32 cmd.exe path as was done for PowerShell.

Useful? React with 👍 / 👎.

Comment on lines +980 to +981
"--name",
&app.name,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve winget upgrades by package identity

For apps whose name is also a substring of other winget packages, winget upgrade --name <name> can become ambiguous because winget's default matching is substring-based unless --exact is used (https://learn.microsoft.com/en-us/windows/package-manager/winget/upgrade). With --disable-interactivity that turns an app already badged as updatable into a failed update; parse the winget ID from the upgrade table and run --id, or otherwise use exact matching against the same winget identity.

Useful? React with 👍 / 👎.

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.

1 participant