generated from MrSphay/codex-agent-repository-kit
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5303fc536 | ||
|
|
a1819900b1 | ||
|
|
46f9f95dcf | ||
|
|
8ce78741bb | ||
|
|
63f134e55e | ||
|
|
e37a0b56c4 |
@@ -11,7 +11,7 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
MRTRUST_VERSION: 0.1.3
|
MRTRUST_VERSION: 0.1.4
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -59,7 +59,7 @@ jobs:
|
|||||||
path: dist/MrTrust-${{ env.MRTRUST_VERSION }}.zip
|
path: dist/MrTrust-${{ env.MRTRUST_VERSION }}.zip
|
||||||
|
|
||||||
- name: Attach ZIP to Gitea release
|
- name: Attach ZIP to Gitea release
|
||||||
if: github.ref == 'refs/heads/main'
|
if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch'
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.1.4
|
||||||
|
|
||||||
|
- Added a diagnostics tab for checking `.exe`, `.msi`, `.dll`, and `.cat` files.
|
||||||
|
- Added signature status, MrSphay signer matching, and Mark-of-the-Web detection.
|
||||||
|
- Added an in-app SmartScreen explanation to clarify reputation versus local certificate trust.
|
||||||
|
- Added subtle Modrinth-style hover, press, progress, and accent animations.
|
||||||
|
|
||||||
## 0.1.3
|
## 0.1.3
|
||||||
|
|
||||||
- Added Ubuntu-runner signing support through `osslsigncode` and PFX secrets.
|
- Added Ubuntu-runner signing support through `osslsigncode` and PFX secrets.
|
||||||
|
|||||||
282
README.md
282
README.md
@@ -1,134 +1,240 @@
|
|||||||
# MrTrust
|
# MrTrust
|
||||||
|
|
||||||
MrTrust is a small Windows trust-onboarding kit for MrSphay software.
|
## Brought To You By The Fine People Of MrSphay
|
||||||
|
|
||||||
It is designed for this workflow:
|
Good morning, citizen.
|
||||||
|
|
||||||
1. MrSphay creates a private code-signing certificate once.
|
Has Windows ever looked at your freshly downloaded MrSphay program and said:
|
||||||
2. MrSphay publishes only the public trust certificate with MrTrust.
|
|
||||||
3. A user runs MrTrust once and explicitly approves installing that public certificate.
|
|
||||||
4. MrSphay projects signed with the matching certificate chain are shown as trusted on that PC.
|
|
||||||
|
|
||||||
MrTrust does not bypass Microsoft Defender or SmartScreen. Windows can still scan, quarantine, or warn about suspicious files. This project only manages normal Windows certificate trust with visible user consent.
|
```text
|
||||||
|
Unknown publisher? Sounds suspicious, pal.
|
||||||
## What It Contains
|
|
||||||
|
|
||||||
- `MrTrust.exe` opens a standalone Windows interface for installing or removing trust.
|
|
||||||
- `MrTrust.ps1` and `scripts/` are source and maintainer tools for building, signing, and local development.
|
|
||||||
- `scripts/New-MrTrustCertificate.ps1` creates a local root certificate and a code-signing certificate for the publisher.
|
|
||||||
- `scripts/Install-MrTrust.ps1` installs the public trust certificate for the current user or the local machine.
|
|
||||||
- `scripts/Uninstall-MrTrust.ps1` removes the MrTrust certificate again.
|
|
||||||
- `scripts/Sign-MrTrustProject.ps1` signs `.exe`, `.msi`, `.ps1`, and other Authenticode-compatible files.
|
|
||||||
- `scripts/Sign-MrTrustProjectLinux.sh` signs Windows PE/MSI/CAT artifacts on Ubuntu Gitea runners with `osslsigncode`.
|
|
||||||
- `scripts/New-MrTrustRelease.ps1` builds a distributable ZIP package.
|
|
||||||
- `docs/integration-prompt.md` is a prompt you can paste into other Windows projects.
|
|
||||||
- `docs/agent-target-integration.md` is the autonomous target-project integration runbook for agents.
|
|
||||||
- `mrtrust.integration.json` is the machine-readable integration contract.
|
|
||||||
- `MrTrust.exe` is standalone for normal users. It embeds the public certificates and runtime scripts.
|
|
||||||
|
|
||||||
## Quick Start For MrSphay
|
|
||||||
|
|
||||||
Create the certificates:
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
.\scripts\New-MrTrustCertificate.ps1
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This writes:
|
Then step right up to **MrTrust**, the cheerful little trust-onboarding utility that helps your PC recognize signed MrSphay software without poking holes in Windows security.
|
||||||
|
|
||||||
- public certificates to `assets\certificates\`
|
One click. One confirmation. A brighter tomorrow for properly signed applications.
|
||||||
- private signing material to `private\`
|
|
||||||
|
|
||||||
The `private\` directory is ignored by git. Do not publish `.pfx` files or passwords.
|
MrTrust installs public certificates only after you say so. It does not disable Microsoft Defender, SmartScreen, UAC, firewall rules, company policies, common sense, or the big red security lever nobody should touch.
|
||||||
|
|
||||||
Install the public trust certificate on your own PC:
|
## Download Your Complimentary Trust Appliance
|
||||||
|
|
||||||
```powershell
|
Latest release page:
|
||||||
.\MrTrust.ps1 install
|
|
||||||
|
```text
|
||||||
|
https://git.wilkensxl.de/MrSphay/MrTrust/releases
|
||||||
```
|
```
|
||||||
|
|
||||||
Open the GUI:
|
Download the newest:
|
||||||
|
|
||||||
```powershell
|
```text
|
||||||
.\MrTrust.ps1 gui
|
MrTrust-<version>.zip
|
||||||
```
|
```
|
||||||
|
|
||||||
Sign another project build:
|
Extract it, then run:
|
||||||
|
|
||||||
```powershell
|
```text
|
||||||
.\MrTrust.ps1 sign `
|
MrTrust.exe
|
||||||
-Path "C:\Path\To\App.exe" `
|
|
||||||
-PfxPath ".\private\MrSphay-CodeSigning.pfx"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Remove the trust certificate:
|
That is the normal user version. It is standalone and carries the public MrSphay certificates it needs.
|
||||||
|
|
||||||
```powershell
|
## Operating Your Trust-O-Matic 3000
|
||||||
.\MrTrust.ps1 uninstall
|
|
||||||
```
|
|
||||||
|
|
||||||
Build a user-facing ZIP release:
|
Inside the friendly GUI:
|
||||||
|
|
||||||
```powershell
|
- `Install trust` tells Windows to trust MrSphay public signing certificates.
|
||||||
.\scripts\New-MrTrustRelease.ps1 -Version 0.1.3
|
- `Remove trust` politely takes that trust back out again.
|
||||||
```
|
- `Refresh` checks whether your PC is currently feeling cooperative.
|
||||||
|
|
||||||
The Gitea workflow `.gitea/workflows/build.yml` builds the Windows launcher EXE on an `ubuntu-latest` runner with .NET Windows cross-targeting, then uploads the ZIP as an artifact.
|
Default installation scope:
|
||||||
|
|
||||||
## User Installation
|
|
||||||
|
|
||||||
For normal users, distribute `MrTrust.exe`. The executable embeds the public certificate files and opens the GUI by default.
|
|
||||||
|
|
||||||
By default, MrTrust installs trust only for the current Windows user:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Root certificate -> Cert:\CurrentUser\Root
|
Root certificate -> Cert:\CurrentUser\Root
|
||||||
Code-signing certificate -> Cert:\CurrentUser\TrustedPublisher
|
Code-signing certificate -> Cert:\CurrentUser\TrustedPublisher
|
||||||
```
|
```
|
||||||
|
|
||||||
For all users on the machine, run PowerShell as Administrator:
|
That means the trust applies only to the current Windows user.
|
||||||
|
|
||||||
```powershell
|
For all users on the PC, run `MrTrust.exe` as Administrator and choose the all-users option. Please operate administrator privileges responsibly. The future depends on it.
|
||||||
.\MrTrust.exe
|
|
||||||
|
## How The Magic Works
|
||||||
|
|
||||||
|
There is no magic. That is how you know it is working.
|
||||||
|
|
||||||
|
The approved flow:
|
||||||
|
|
||||||
|
1. A MrSphay app is signed during its release build.
|
||||||
|
2. You run `MrTrust.exe`.
|
||||||
|
3. You review the certificate details.
|
||||||
|
4. You confirm the trust installation.
|
||||||
|
5. Windows can validate signed MrSphay apps on that PC.
|
||||||
|
|
||||||
|
If the app is not signed, MrTrust cannot help it. Even the finest paperwork cannot identify a person who never showed up.
|
||||||
|
|
||||||
|
## Safety Notice From The Department Of Not Breaking Windows
|
||||||
|
|
||||||
|
MrTrust does not:
|
||||||
|
|
||||||
|
- make unsigned programs trusted
|
||||||
|
- bypass Defender
|
||||||
|
- bypass SmartScreen
|
||||||
|
- remove UAC prompts
|
||||||
|
- silently install certificates
|
||||||
|
- install private signing keys on user machines
|
||||||
|
- make sketchy software less sketchy
|
||||||
|
|
||||||
|
Windows may still scan, block, warn, quarantine, or ask questions. MrTrust only handles normal certificate trust.
|
||||||
|
|
||||||
|
## Public Certificate Values
|
||||||
|
|
||||||
|
These values are public and safe to use in documentation, agent prompts, and integration metadata:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Publisher:
|
||||||
|
MrSphay
|
||||||
|
|
||||||
|
Root certificate thumbprint:
|
||||||
|
39F7458E6E2C1126E93E6A1F228196006B174DF2
|
||||||
|
|
||||||
|
Code-signing certificate thumbprint:
|
||||||
|
A024A89200469F099EC4A172B4F96F6428AFD41B
|
||||||
```
|
```
|
||||||
|
|
||||||
Then choose the all-users option in the GUI.
|
They are also stored here:
|
||||||
|
|
||||||
## Using This Repo With Other Agents
|
```text
|
||||||
|
assets/certificates/thumbprints.txt
|
||||||
|
mrtrust.integration.json
|
||||||
|
```
|
||||||
|
|
||||||
Yes. Give another agent this repository URL, the target Windows project, and `docs/integration-prompt.md`.
|
## For The Workshop Crew
|
||||||
|
|
||||||
For autonomous work, the agent should read these files in order:
|
Local maintainer commands:
|
||||||
|
|
||||||
1. `mrtrust.integration.json`
|
```powershell
|
||||||
2. `docs/agent-target-integration.md`
|
.\MrTrust.ps1 gui
|
||||||
3. `docs/integration-prompt.md`
|
.\MrTrust.ps1 install
|
||||||
|
.\MrTrust.ps1 uninstall
|
||||||
|
```
|
||||||
|
|
||||||
The agent's job is to modify the target project, not this repository:
|
Create or refresh local certificates:
|
||||||
|
|
||||||
- expose a visible "Open MrTrust" or trust setup path for users
|
```powershell
|
||||||
- link to or bundle the standalone `MrTrust.exe`
|
.\scripts\New-MrTrustCertificate.ps1
|
||||||
- sign Windows release artifacts with the MrSphay code-signing certificate
|
```
|
||||||
- keep trust installation explicit, reversible, and user-confirmed
|
|
||||||
- keep private signing material out of the target repository and release artifacts
|
|
||||||
|
|
||||||
Both sides have to be wired:
|
Build a release ZIP locally:
|
||||||
|
|
||||||
- MrTrust side: users install the public trust certificates once.
|
```powershell
|
||||||
- Target project side: release artifacts are signed with the MrSphay code-signing certificate.
|
.\scripts\New-MrTrustRelease.ps1 -Version 0.1.4
|
||||||
- Installer side, optional: the target app can offer "Open MrTrust" or bundle `MrTrust.exe`, but it must not silently change trust.
|
```
|
||||||
|
|
||||||
If the target project is not signed, MrTrust cannot make it trusted.
|
Sign an artifact locally on Windows:
|
||||||
|
|
||||||
## Important Limits
|
```powershell
|
||||||
|
.\MrTrust.ps1 sign `
|
||||||
|
-Path "C:\Path\To\App.exe" `
|
||||||
|
-CertificateThumbprint A024A89200469F099EC4A172B4F96F6428AFD41B
|
||||||
|
```
|
||||||
|
|
||||||
- This only helps for programs signed with the matching MrSphay certificate chain.
|
Private signing material belongs only in:
|
||||||
- It does not make unsigned programs trusted.
|
|
||||||
- It does not disable Defender, SmartScreen, UAC, or enterprise policies.
|
|
||||||
- Public distribution without warnings is still best handled with a recognized commercial code-signing certificate.
|
|
||||||
|
|
||||||
## Recommended Project Integration
|
```text
|
||||||
|
private/
|
||||||
|
Bitwarden
|
||||||
|
Gitea repository secrets
|
||||||
|
```
|
||||||
|
|
||||||
Use `docs/integration-prompt.md` in another Windows project. The prompt tells Codex or another assistant to add a visible trust check, a link or bundled copy of the standalone `MrTrust.exe`, and a signing step without hiding security changes from the user.
|
Never commit `.pfx` files, private keys, passwords, or Base64-encoded signing material. That is not trust. That is handing out the vault keys at the snack counter.
|
||||||
|
|
||||||
For agents that can inspect files autonomously, `docs/agent-target-integration.md` gives the decision tree, installer patterns, signing commands, and completion checklist.
|
## Gitea Secrets For Other Projects
|
||||||
|
|
||||||
|
For another project to sign Windows release artifacts on an Ubuntu Gitea runner, add these secrets to that target repository:
|
||||||
|
|
||||||
|
```text
|
||||||
|
MRTRUST_CODESIGN_PFX_BASE64
|
||||||
|
MRTRUST_CODESIGN_PFX_PASSWORD
|
||||||
|
```
|
||||||
|
|
||||||
|
Optional timestamp override:
|
||||||
|
|
||||||
|
```text
|
||||||
|
MRTRUST_TIMESTAMP_URL
|
||||||
|
```
|
||||||
|
|
||||||
|
The first two values are private signing credentials. Keep them in Bitwarden and Gitea Secrets only.
|
||||||
|
|
||||||
|
Ubuntu helper script:
|
||||||
|
|
||||||
|
```text
|
||||||
|
scripts/Sign-MrTrustProjectLinux.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
It signs supported Windows artifacts with `osslsigncode`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
.exe
|
||||||
|
.msi
|
||||||
|
.dll
|
||||||
|
.cat
|
||||||
|
```
|
||||||
|
|
||||||
|
PowerShell scripts should be signed on Windows, not Ubuntu.
|
||||||
|
|
||||||
|
## Installing MrTrust Into Another Project
|
||||||
|
|
||||||
|
Give your coding agent this repository:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://git.wilkensxl.de/MrSphay/MrTrust
|
||||||
|
```
|
||||||
|
|
||||||
|
Tell it to read:
|
||||||
|
|
||||||
|
```text
|
||||||
|
mrtrust.integration.json
|
||||||
|
docs/agent-target-integration.md
|
||||||
|
docs/integration-prompt.md
|
||||||
|
```
|
||||||
|
|
||||||
|
The target project should end up with:
|
||||||
|
|
||||||
|
- signed Windows release artifacts
|
||||||
|
- a visible optional MrTrust setup path
|
||||||
|
- a link to or bundled copy of `MrTrust.exe`
|
||||||
|
- documentation for installing and removing trust
|
||||||
|
- no committed private signing material
|
||||||
|
|
||||||
|
Remember the two-part handshake:
|
||||||
|
|
||||||
|
- MrTrust side: the user installs public trust certificates once.
|
||||||
|
- Target project side: the app is signed with the MrSphay code-signing certificate.
|
||||||
|
|
||||||
|
No signature, no trust. No trust, no victory parade.
|
||||||
|
|
||||||
|
## Current Build
|
||||||
|
|
||||||
|
The Gitea workflow builds `MrTrust.exe` on `ubuntu-latest` with .NET Windows cross-targeting.
|
||||||
|
|
||||||
|
On pushes to `main`, it:
|
||||||
|
|
||||||
|
1. builds the standalone Windows executable
|
||||||
|
2. packages `MrTrust-0.1.4.zip`
|
||||||
|
3. uploads the workflow artifact
|
||||||
|
4. attaches the ZIP to the Gitea release
|
||||||
|
|
||||||
|
Manual `workflow_dispatch` runs build artifacts but do not attach release assets. This prevents duplicate release uploads, which are bad for morale and paperwork.
|
||||||
|
|
||||||
|
## Final Safety Reminder
|
||||||
|
|
||||||
|
MrTrust is intentionally visible and reversible:
|
||||||
|
|
||||||
|
- the GUI shows the trust state
|
||||||
|
- installation requires confirmation
|
||||||
|
- removal is available in the same tool
|
||||||
|
- public certificates are embedded in the executable
|
||||||
|
- private signing material is never needed on user machines
|
||||||
|
|
||||||
|
For broad public distribution without SmartScreen reputation delays, a recognized commercial code-signing certificate is still the cleanest option.
|
||||||
|
|
||||||
|
Thank you for choosing MrTrust. Stay signed, stay verified, and keep your release pipeline tidy.
|
||||||
|
|||||||
@@ -10,6 +10,25 @@ $script:RootPath = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyComman
|
|||||||
$script:RootCertificatePath = Join-Path $script:RootPath "assets\certificates\MrSphay-LocalTrust-Root.cer"
|
$script:RootCertificatePath = Join-Path $script:RootPath "assets\certificates\MrSphay-LocalTrust-Root.cer"
|
||||||
$script:PublisherCertificatePath = Join-Path $script:RootPath "assets\certificates\MrSphay-CodeSigning.cer"
|
$script:PublisherCertificatePath = Join-Path $script:RootPath "assets\certificates\MrSphay-CodeSigning.cer"
|
||||||
$script:IconPath = Join-Path $script:RootPath "assets\MrTrust.ico"
|
$script:IconPath = Join-Path $script:RootPath "assets\MrTrust.ico"
|
||||||
|
$script:SelectedFilePath = $null
|
||||||
|
$script:CurrentAccent = 0
|
||||||
|
|
||||||
|
$colors = @{
|
||||||
|
Background = [Drawing.Color]::FromArgb(15, 20, 20)
|
||||||
|
Shell = [Drawing.Color]::FromArgb(20, 27, 27)
|
||||||
|
Panel = [Drawing.Color]::FromArgb(27, 36, 35)
|
||||||
|
PanelAlt = [Drawing.Color]::FromArgb(34, 45, 43)
|
||||||
|
PanelSelected = [Drawing.Color]::FromArgb(31, 64, 49)
|
||||||
|
Border = [Drawing.Color]::FromArgb(53, 66, 64)
|
||||||
|
Text = [Drawing.Color]::FromArgb(239, 244, 241)
|
||||||
|
Muted = [Drawing.Color]::FromArgb(157, 172, 166)
|
||||||
|
Green = [Drawing.Color]::FromArgb(0, 175, 91)
|
||||||
|
GreenHover = [Drawing.Color]::FromArgb(0, 199, 104)
|
||||||
|
GreenSoft = [Drawing.Color]::FromArgb(34, 76, 52)
|
||||||
|
Orange = [Drawing.Color]::FromArgb(242, 153, 74)
|
||||||
|
Red = [Drawing.Color]::FromArgb(235, 87, 87)
|
||||||
|
Blue = [Drawing.Color]::FromArgb(82, 166, 255)
|
||||||
|
}
|
||||||
|
|
||||||
function Test-IsAdministrator {
|
function Test-IsAdministrator {
|
||||||
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
|
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||||
@@ -28,12 +47,7 @@ function Get-MrTrustCertificate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Get-TrustScope {
|
function Get-TrustScope {
|
||||||
if ($script:AllUsersCheckBox.Checked) {
|
if ($script:AllUsersCheckBox.Checked) { "LocalMachine" } else { "CurrentUser" }
|
||||||
"LocalMachine"
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
"CurrentUser"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-StorePath {
|
function Get-StorePath {
|
||||||
@@ -56,14 +70,153 @@ function Test-CertificateInstalled {
|
|||||||
@(Get-ChildItem -Path $storePath | Where-Object Thumbprint -eq $Certificate.Thumbprint).Count -gt 0
|
@(Get-ChildItem -Path $storePath | Where-Object Thumbprint -eq $Certificate.Thumbprint).Count -gt 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function Set-StatusText {
|
function Set-Busy {
|
||||||
param([Parameter(Mandatory)][string]$Text)
|
param([bool]$Busy)
|
||||||
|
|
||||||
$script:StatusLabel.Text = $Text
|
$script:ProgressBar.Visible = $Busy
|
||||||
|
if ($Busy) {
|
||||||
|
$script:ProgressBar.Style = "Marquee"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Refresh-MrTrustStatus {
|
function Set-StatusText {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)][string]$Text,
|
||||||
|
[Parameter(Mandatory)][Drawing.Color]$Color
|
||||||
|
)
|
||||||
|
|
||||||
|
$script:StatusLabel.Text = $Text
|
||||||
|
$script:StatusPill.BackColor = $Color
|
||||||
|
}
|
||||||
|
|
||||||
|
function Add-AnimatedButton {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)][Windows.Forms.Button]$Button,
|
||||||
|
[Parameter(Mandatory)][Drawing.Color]$Normal,
|
||||||
|
[Parameter(Mandatory)][Drawing.Color]$Hover
|
||||||
|
)
|
||||||
|
|
||||||
|
$normalColor = $Normal
|
||||||
|
$hoverColor = $Hover
|
||||||
|
$textColor = $colors.Text
|
||||||
|
$borderColor = $colors.Border
|
||||||
|
|
||||||
|
$Button.FlatStyle = "Flat"
|
||||||
|
$Button.FlatAppearance.BorderColor = $borderColor
|
||||||
|
$Button.FlatAppearance.BorderSize = 1
|
||||||
|
$Button.BackColor = $normalColor
|
||||||
|
$Button.ForeColor = $textColor
|
||||||
|
$Button.Cursor = [Windows.Forms.Cursors]::Hand
|
||||||
|
$Button.Add_MouseEnter({ param($sender, $eventArgs) $sender.BackColor = $hoverColor }.GetNewClosure())
|
||||||
|
$Button.Add_MouseLeave({ param($sender, $eventArgs) $sender.BackColor = $normalColor }.GetNewClosure())
|
||||||
|
}
|
||||||
|
|
||||||
|
function New-Label {
|
||||||
|
param(
|
||||||
|
[string]$Text,
|
||||||
|
[int]$X,
|
||||||
|
[int]$Y,
|
||||||
|
[int]$Width = 220,
|
||||||
|
[int]$Height = 24,
|
||||||
|
[Drawing.Color]$Color = $colors.Muted,
|
||||||
|
[Drawing.Font]$Font = $null
|
||||||
|
)
|
||||||
|
|
||||||
|
$label = [Windows.Forms.Label]::new()
|
||||||
|
$label.Text = $Text
|
||||||
|
$label.Location = [Drawing.Point]::new($X, $Y)
|
||||||
|
$label.Size = [Drawing.Size]::new($Width, $Height)
|
||||||
|
$label.ForeColor = $Color
|
||||||
|
if ($Font) { $label.Font = $Font }
|
||||||
|
$label
|
||||||
|
}
|
||||||
|
|
||||||
|
function New-Card {
|
||||||
|
param(
|
||||||
|
[int]$X,
|
||||||
|
[int]$Y,
|
||||||
|
[int]$Width,
|
||||||
|
[int]$Height,
|
||||||
|
[Drawing.Color]$BackColor = $colors.Panel
|
||||||
|
)
|
||||||
|
|
||||||
|
$panel = [Windows.Forms.Panel]::new()
|
||||||
|
$panel.Location = [Drawing.Point]::new($X, $Y)
|
||||||
|
$panel.Size = [Drawing.Size]::new($Width, $Height)
|
||||||
|
$panel.BackColor = $BackColor
|
||||||
|
$panel.BorderStyle = "FixedSingle"
|
||||||
|
$panel.Anchor = "Top,Left,Right"
|
||||||
|
$panel
|
||||||
|
}
|
||||||
|
|
||||||
|
function New-PageTitle {
|
||||||
|
param(
|
||||||
|
[string]$Title,
|
||||||
|
[string]$Description
|
||||||
|
)
|
||||||
|
|
||||||
|
$titleLabel = New-Label -Text $Title -X 0 -Y 0 -Width 760 -Height 34 -Color $colors.Text -Font ([Drawing.Font]::new("Segoe UI", 15, [Drawing.FontStyle]::Bold))
|
||||||
|
$descriptionLabel = New-Label -Text $Description -X 1 -Y 38 -Width 850 -Height 24 -Color $colors.Muted
|
||||||
|
[pscustomobject]@{
|
||||||
|
Title = $titleLabel
|
||||||
|
Description = $descriptionLabel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function New-NavButton {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)][string]$Key,
|
||||||
|
[Parameter(Mandatory)][string]$Text,
|
||||||
|
[Parameter(Mandatory)][int]$Y
|
||||||
|
)
|
||||||
|
|
||||||
|
$button = [Windows.Forms.Button]::new()
|
||||||
|
$button.Text = $Text
|
||||||
|
$button.Tag = $Key
|
||||||
|
$button.Size = [Drawing.Size]::new(174, 44)
|
||||||
|
$button.Location = [Drawing.Point]::new(22, $Y)
|
||||||
|
$button.TextAlign = "MiddleLeft"
|
||||||
|
$button.Padding = [Windows.Forms.Padding]::new(14, 0, 0, 0)
|
||||||
|
$button.Font = [Drawing.Font]::new("Segoe UI", 10, [Drawing.FontStyle]::Bold)
|
||||||
|
$button.FlatStyle = "Flat"
|
||||||
|
$button.FlatAppearance.BorderSize = 1
|
||||||
|
$button.FlatAppearance.BorderColor = $colors.Shell
|
||||||
|
$button.BackColor = $colors.Shell
|
||||||
|
$button.ForeColor = $colors.Muted
|
||||||
|
$button.Cursor = [Windows.Forms.Cursors]::Hand
|
||||||
|
$button.Add_MouseEnter({ param($sender, $eventArgs) if ($script:ActivePage -ne $sender.Tag) { $sender.BackColor = $colors.PanelAlt } }.GetNewClosure())
|
||||||
|
$button.Add_MouseLeave({ param($sender, $eventArgs) if ($script:ActivePage -ne $sender.Tag) { $sender.BackColor = $colors.Shell } }.GetNewClosure())
|
||||||
|
$button.Add_Click({ param($sender, $eventArgs) Show-MrTrustPage -Key $sender.Tag })
|
||||||
|
$button
|
||||||
|
}
|
||||||
|
|
||||||
|
function Show-MrTrustPage {
|
||||||
|
param([Parameter(Mandatory)][string]$Key)
|
||||||
|
|
||||||
|
$script:ActivePage = $Key
|
||||||
|
|
||||||
|
foreach ($pageKey in $script:Pages.Keys) {
|
||||||
|
$script:Pages[$pageKey].Visible = $pageKey -eq $Key
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($buttonKey in $script:NavButtons.Keys) {
|
||||||
|
$button = $script:NavButtons[$buttonKey]
|
||||||
|
if ($buttonKey -eq $Key) {
|
||||||
|
$button.BackColor = $colors.PanelSelected
|
||||||
|
$button.FlatAppearance.BorderColor = $colors.Green
|
||||||
|
$button.ForeColor = $colors.Text
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$button.BackColor = $colors.Shell
|
||||||
|
$button.FlatAppearance.BorderColor = $colors.Shell
|
||||||
|
$button.ForeColor = $colors.Muted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Update-TrustStatus {
|
||||||
try {
|
try {
|
||||||
|
Set-Busy $true
|
||||||
$rootCertificate = Get-MrTrustCertificate -Path $script:RootCertificatePath
|
$rootCertificate = Get-MrTrustCertificate -Path $script:RootCertificatePath
|
||||||
$publisherCertificate = Get-MrTrustCertificate -Path $script:PublisherCertificatePath
|
$publisherCertificate = Get-MrTrustCertificate -Path $script:PublisherCertificatePath
|
||||||
$scope = Get-TrustScope
|
$scope = Get-TrustScope
|
||||||
@@ -74,79 +227,58 @@ function Refresh-MrTrustStatus {
|
|||||||
$script:RootThumbprintLabel.Text = $rootCertificate.Thumbprint
|
$script:RootThumbprintLabel.Text = $rootCertificate.Thumbprint
|
||||||
$script:PublisherThumbprintLabel.Text = $publisherCertificate.Thumbprint
|
$script:PublisherThumbprintLabel.Text = $publisherCertificate.Thumbprint
|
||||||
$script:ExpiryLabel.Text = $rootCertificate.NotAfter.ToString("yyyy-MM-dd")
|
$script:ExpiryLabel.Text = $rootCertificate.NotAfter.ToString("yyyy-MM-dd")
|
||||||
|
$script:ScopeValueLabel.Text = $scope
|
||||||
|
|
||||||
if ($rootInstalled -and $publisherInstalled) {
|
if ($rootInstalled -and $publisherInstalled) {
|
||||||
Set-StatusText "Trusted"
|
Set-StatusText -Text "Trusted" -Color $colors.Green
|
||||||
$script:StatusPill.BackColor = [Drawing.Color]::FromArgb(28, 185, 111)
|
$script:TrustSummaryLabel.Text = "MrSphay public trust is installed for $scope."
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Set-StatusText "Not installed"
|
Set-StatusText -Text "Not installed" -Color $colors.Orange
|
||||||
$script:StatusPill.BackColor = [Drawing.Color]::FromArgb(242, 153, 74)
|
$script:TrustSummaryLabel.Text = "Trust is not fully installed for $scope."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Set-StatusText $_.Exception.Message
|
Set-StatusText -Text "Error" -Color $colors.Red
|
||||||
$script:StatusPill.BackColor = [Drawing.Color]::FromArgb(235, 87, 87)
|
$script:TrustSummaryLabel.Text = $_.Exception.Message
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
Set-Busy $false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Install-MrTrustCertificates {
|
function Install-MrTrustCertificates {
|
||||||
$scope = Get-TrustScope
|
$scope = Get-TrustScope
|
||||||
if ($scope -eq "LocalMachine" -and -not (Test-IsAdministrator)) {
|
if ($scope -eq "LocalMachine" -and -not (Test-IsAdministrator)) {
|
||||||
[Windows.Forms.MessageBox]::Show(
|
[Windows.Forms.MessageBox]::Show("All-users trust requires running MrTrust as Administrator.", "MrTrust", "OK", "Warning") | Out-Null
|
||||||
"All-users trust requires running PowerShell as Administrator.",
|
|
||||||
"MrTrust",
|
|
||||||
[Windows.Forms.MessageBoxButtons]::OK,
|
|
||||||
[Windows.Forms.MessageBoxIcon]::Warning
|
|
||||||
) | Out-Null
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$rootCertificate = Get-MrTrustCertificate -Path $script:RootCertificatePath
|
$rootCertificate = Get-MrTrustCertificate -Path $script:RootCertificatePath
|
||||||
$publisherCertificate = Get-MrTrustCertificate -Path $script:PublisherCertificatePath
|
$publisherCertificate = Get-MrTrustCertificate -Path $script:PublisherCertificatePath
|
||||||
|
$message = "Install MrSphay trust for $scope?`r`n`r`nRoot:`r`n$($rootCertificate.Thumbprint)`r`n`r`nPublisher:`r`n$($publisherCertificate.Thumbprint)`r`n`r`nThis does not disable Defender or SmartScreen."
|
||||||
|
$result = [Windows.Forms.MessageBox]::Show($message, "Install MrTrust", "YesNo", "Warning")
|
||||||
|
if ($result -ne [Windows.Forms.DialogResult]::Yes) { return }
|
||||||
|
|
||||||
$message = "Install MrSphay trust for $scope?`r`n`r`nRoot:`r`n$($rootCertificate.Thumbprint)`r`n`r`nPublisher:`r`n$($publisherCertificate.Thumbprint)`r`n`r`nOnly continue if you trust software signed by MrSphay."
|
Set-Busy $true
|
||||||
$result = [Windows.Forms.MessageBox]::Show(
|
|
||||||
$message,
|
|
||||||
"Install MrTrust",
|
|
||||||
[Windows.Forms.MessageBoxButtons]::YesNo,
|
|
||||||
[Windows.Forms.MessageBoxIcon]::Warning
|
|
||||||
)
|
|
||||||
|
|
||||||
if ($result -ne [Windows.Forms.DialogResult]::Yes) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
Import-Certificate -FilePath $script:RootCertificatePath -CertStoreLocation (Get-StorePath -Scope $scope -Store "Root") | Out-Null
|
Import-Certificate -FilePath $script:RootCertificatePath -CertStoreLocation (Get-StorePath -Scope $scope -Store "Root") | Out-Null
|
||||||
Import-Certificate -FilePath $script:PublisherCertificatePath -CertStoreLocation (Get-StorePath -Scope $scope -Store "TrustedPublisher") | Out-Null
|
Import-Certificate -FilePath $script:PublisherCertificatePath -CertStoreLocation (Get-StorePath -Scope $scope -Store "TrustedPublisher") | Out-Null
|
||||||
Refresh-MrTrustStatus
|
Update-TrustStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
function Remove-MrTrustCertificates {
|
function Remove-MrTrustCertificates {
|
||||||
$scope = Get-TrustScope
|
$scope = Get-TrustScope
|
||||||
if ($scope -eq "LocalMachine" -and -not (Test-IsAdministrator)) {
|
if ($scope -eq "LocalMachine" -and -not (Test-IsAdministrator)) {
|
||||||
[Windows.Forms.MessageBox]::Show(
|
[Windows.Forms.MessageBox]::Show("All-users removal requires running MrTrust as Administrator.", "MrTrust", "OK", "Warning") | Out-Null
|
||||||
"All-users removal requires running PowerShell as Administrator.",
|
|
||||||
"MrTrust",
|
|
||||||
[Windows.Forms.MessageBoxButtons]::OK,
|
|
||||||
[Windows.Forms.MessageBoxIcon]::Warning
|
|
||||||
) | Out-Null
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$result = [Windows.Forms.MessageBox]::Show("Remove MrSphay trust for $scope?", "Remove MrTrust", "YesNo", "Question")
|
||||||
|
if ($result -ne [Windows.Forms.DialogResult]::Yes) { return }
|
||||||
|
|
||||||
|
Set-Busy $true
|
||||||
$rootCertificate = Get-MrTrustCertificate -Path $script:RootCertificatePath
|
$rootCertificate = Get-MrTrustCertificate -Path $script:RootCertificatePath
|
||||||
$publisherCertificate = Get-MrTrustCertificate -Path $script:PublisherCertificatePath
|
$publisherCertificate = Get-MrTrustCertificate -Path $script:PublisherCertificatePath
|
||||||
$result = [Windows.Forms.MessageBox]::Show(
|
|
||||||
"Remove MrSphay trust for $scope?",
|
|
||||||
"Remove MrTrust",
|
|
||||||
[Windows.Forms.MessageBoxButtons]::YesNo,
|
|
||||||
[Windows.Forms.MessageBoxIcon]::Question
|
|
||||||
)
|
|
||||||
|
|
||||||
if ($result -ne [Windows.Forms.DialogResult]::Yes) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
$targets = @(
|
$targets = @(
|
||||||
[pscustomobject]@{ Store = "Root"; Thumbprint = $rootCertificate.Thumbprint },
|
[pscustomobject]@{ Store = "Root"; Thumbprint = $rootCertificate.Thumbprint },
|
||||||
[pscustomobject]@{ Store = "TrustedPublisher"; Thumbprint = $publisherCertificate.Thumbprint }
|
[pscustomobject]@{ Store = "TrustedPublisher"; Thumbprint = $publisherCertificate.Thumbprint }
|
||||||
@@ -159,7 +291,86 @@ function Remove-MrTrustCertificates {
|
|||||||
Remove-Item
|
Remove-Item
|
||||||
}
|
}
|
||||||
|
|
||||||
Refresh-MrTrustStatus
|
Update-TrustStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-MarkOfTheWeb {
|
||||||
|
param([Parameter(Mandatory)][string]$Path)
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stream = Get-Content -LiteralPath $Path -Stream Zone.Identifier -ErrorAction Stop
|
||||||
|
($stream -join "`n") -match "ZoneId\s*=\s*[3-4]"
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-SmartScreenExplanation {
|
||||||
|
param(
|
||||||
|
[bool]$SignedByMrSphay,
|
||||||
|
[bool]$HasMotw
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($SignedByMrSphay -and $HasMotw) {
|
||||||
|
"Publisher trust can be valid while SmartScreen still warns because the downloaded file has Internet origin and low Microsoft reputation."
|
||||||
|
}
|
||||||
|
elseif ($SignedByMrSphay) {
|
||||||
|
"The publisher matches MrSphay. SmartScreen may still warn until Microsoft reputation builds for this exact app and publisher."
|
||||||
|
}
|
||||||
|
elseif ($HasMotw) {
|
||||||
|
"This file came from the Internet and is not signed by MrSphay. SmartScreen warnings are expected."
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
"MrTrust can only help with MrSphay-signed files. SmartScreen reputation is separate from local certificate trust."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-SelectedFile {
|
||||||
|
param([Parameter(Mandatory)][string]$Path)
|
||||||
|
|
||||||
|
Set-Busy $true
|
||||||
|
try {
|
||||||
|
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
|
||||||
|
throw "File not found: $Path"
|
||||||
|
}
|
||||||
|
|
||||||
|
$signature = Get-AuthenticodeSignature -LiteralPath $Path
|
||||||
|
$hasMotw = Test-MarkOfTheWeb -Path $Path
|
||||||
|
$signer = $signature.SignerCertificate
|
||||||
|
$signedByMrSphay = $false
|
||||||
|
if ($signer) {
|
||||||
|
$signedByMrSphay = $signer.Thumbprint -eq "A024A89200469F099EC4A172B4F96F6428AFD41B" -or $signer.Subject -like "*MrSphay*"
|
||||||
|
}
|
||||||
|
|
||||||
|
$script:FileNameLabel.Text = [IO.Path]::GetFileName($Path)
|
||||||
|
$script:FilePathLabel.Text = $Path
|
||||||
|
$script:SignatureStatusLabel.Text = "$($signature.Status)"
|
||||||
|
$script:SignerLabel.Text = if ($signer) { $signer.Subject } else { "No signer certificate" }
|
||||||
|
$script:MrSphayMatchLabel.Text = if ($signedByMrSphay) { "Yes" } else { "No" }
|
||||||
|
$script:MotwLabel.Text = if ($hasMotw) { "Yes" } else { "No" }
|
||||||
|
$script:SmartScreenLabel.Text = Get-SmartScreenExplanation -SignedByMrSphay $signedByMrSphay -HasMotw $hasMotw
|
||||||
|
|
||||||
|
if ($signedByMrSphay -and $signature.Status -eq "Valid") {
|
||||||
|
$script:FileVerdictLabel.Text = "Looks good: signed by MrSphay and locally valid."
|
||||||
|
$script:FileVerdictLabel.ForeColor = $colors.Green
|
||||||
|
}
|
||||||
|
elseif ($signedByMrSphay) {
|
||||||
|
$script:FileVerdictLabel.Text = "Signed by MrSphay, but local validation is not fully valid: $($signature.Status)"
|
||||||
|
$script:FileVerdictLabel.ForeColor = $colors.Orange
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$script:FileVerdictLabel.Text = "Not a MrSphay-signed file."
|
||||||
|
$script:FileVerdictLabel.ForeColor = $colors.Red
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$script:FileVerdictLabel.Text = $_.Exception.Message
|
||||||
|
$script:FileVerdictLabel.ForeColor = $colors.Red
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
Set-Busy $false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Windows.Forms.Application]::EnableVisualStyles()
|
[Windows.Forms.Application]::EnableVisualStyles()
|
||||||
@@ -167,9 +378,9 @@ function Remove-MrTrustCertificates {
|
|||||||
$form = [Windows.Forms.Form]::new()
|
$form = [Windows.Forms.Form]::new()
|
||||||
$form.Text = "MrTrust"
|
$form.Text = "MrTrust"
|
||||||
$form.StartPosition = "CenterScreen"
|
$form.StartPosition = "CenterScreen"
|
||||||
$form.ClientSize = [Drawing.Size]::new(900, 560)
|
$form.ClientSize = [Drawing.Size]::new(1120, 720)
|
||||||
$form.MinimumSize = [Drawing.Size]::new(860, 540)
|
$form.MinimumSize = [Drawing.Size]::new(1040, 680)
|
||||||
$form.BackColor = [Drawing.Color]::FromArgb(22, 26, 29)
|
$form.BackColor = $colors.Background
|
||||||
$form.Font = [Drawing.Font]::new("Segoe UI", 10)
|
$form.Font = [Drawing.Font]::new("Segoe UI", 10)
|
||||||
if (Test-Path -LiteralPath $script:IconPath) {
|
if (Test-Path -LiteralPath $script:IconPath) {
|
||||||
$form.Icon = [Drawing.Icon]::new($script:IconPath)
|
$form.Icon = [Drawing.Icon]::new($script:IconPath)
|
||||||
@@ -177,170 +388,285 @@ if (Test-Path -LiteralPath $script:IconPath) {
|
|||||||
|
|
||||||
$header = [Windows.Forms.Panel]::new()
|
$header = [Windows.Forms.Panel]::new()
|
||||||
$header.Dock = "Top"
|
$header.Dock = "Top"
|
||||||
$header.Height = 124
|
$header.Height = 96
|
||||||
$header.BackColor = [Drawing.Color]::FromArgb(27, 32, 35)
|
$header.BackColor = $colors.Background
|
||||||
$form.Controls.Add($header)
|
$form.Controls.Add($header)
|
||||||
|
|
||||||
$accent = [Windows.Forms.Panel]::new()
|
$brandLine = [Windows.Forms.Panel]::new()
|
||||||
$accent.Dock = "Left"
|
$brandLine.Dock = "Bottom"
|
||||||
$accent.Width = 8
|
$brandLine.Height = 1
|
||||||
$accent.BackColor = [Drawing.Color]::FromArgb(28, 185, 111)
|
$brandLine.BackColor = $colors.Border
|
||||||
$header.Controls.Add($accent)
|
$header.Controls.Add($brandLine)
|
||||||
|
|
||||||
$logoBox = [Windows.Forms.PictureBox]::new()
|
$logoBox = [Windows.Forms.PictureBox]::new()
|
||||||
$logoBox.Size = [Drawing.Size]::new(44, 44)
|
$logoBox.Size = [Drawing.Size]::new(42, 42)
|
||||||
$logoBox.Location = [Drawing.Point]::new(34, 30)
|
$logoBox.Location = [Drawing.Point]::new(28, 26)
|
||||||
$logoBox.SizeMode = "StretchImage"
|
$logoBox.SizeMode = "StretchImage"
|
||||||
if (Test-Path -LiteralPath $script:IconPath) {
|
if (Test-Path -LiteralPath $script:IconPath) {
|
||||||
$logoBox.Image = [Drawing.Icon]::new($script:IconPath).ToBitmap()
|
$logoBox.Image = [Drawing.Icon]::new($script:IconPath).ToBitmap()
|
||||||
}
|
}
|
||||||
$header.Controls.Add($logoBox)
|
$header.Controls.Add($logoBox)
|
||||||
|
|
||||||
$title = [Windows.Forms.Label]::new()
|
$title = New-Label -Text "MrTrust" -X 86 -Y 20 -Width 260 -Height 36 -Color $colors.Text -Font ([Drawing.Font]::new("Segoe UI", 18, [Drawing.FontStyle]::Bold))
|
||||||
$title.Text = "MrTrust"
|
|
||||||
$title.ForeColor = [Drawing.Color]::White
|
|
||||||
$title.Font = [Drawing.Font]::new("Segoe UI", 24, [Drawing.FontStyle]::Bold)
|
|
||||||
$title.AutoSize = $true
|
|
||||||
$title.Location = [Drawing.Point]::new(92, 24)
|
|
||||||
$header.Controls.Add($title)
|
$header.Controls.Add($title)
|
||||||
|
|
||||||
$subtitle = [Windows.Forms.Label]::new()
|
$subtitle = New-Label -Text "Local certificate trust for MrSphay signed Windows apps" -X 88 -Y 56 -Width 520 -Height 24 -Color $colors.Muted
|
||||||
$subtitle.Text = "Trust setup for MrSphay signed Windows apps"
|
|
||||||
$subtitle.ForeColor = [Drawing.Color]::FromArgb(177, 190, 183)
|
|
||||||
$subtitle.AutoSize = $true
|
|
||||||
$subtitle.Location = [Drawing.Point]::new(96, 74)
|
|
||||||
$header.Controls.Add($subtitle)
|
$header.Controls.Add($subtitle)
|
||||||
|
|
||||||
$statusText = [Windows.Forms.Label]::new()
|
$statusCard = [Windows.Forms.Panel]::new()
|
||||||
$statusText.Text = "Status"
|
$statusCard.Anchor = "Top,Right"
|
||||||
$statusText.ForeColor = [Drawing.Color]::FromArgb(177, 190, 183)
|
$statusCard.Location = [Drawing.Point]::new(780, 20)
|
||||||
$statusText.AutoSize = $true
|
$statusCard.Size = [Drawing.Size]::new(300, 56)
|
||||||
$statusText.Location = [Drawing.Point]::new(646, 32)
|
$statusCard.BackColor = $colors.Panel
|
||||||
$header.Controls.Add($statusText)
|
$statusCard.BorderStyle = "FixedSingle"
|
||||||
|
$header.Controls.Add($statusCard)
|
||||||
|
|
||||||
|
$statusText = New-Label -Text "Trust status" -X 18 -Y 7 -Width 130 -Height 20 -Color $colors.Muted -Font ([Drawing.Font]::new("Segoe UI", 8.5))
|
||||||
|
$statusCard.Controls.Add($statusText)
|
||||||
|
|
||||||
$script:StatusPill = [Windows.Forms.Panel]::new()
|
$script:StatusPill = [Windows.Forms.Panel]::new()
|
||||||
$script:StatusPill.Size = [Drawing.Size]::new(16, 16)
|
$script:StatusPill.Size = [Drawing.Size]::new(14, 14)
|
||||||
$script:StatusPill.Location = [Drawing.Point]::new(646, 62)
|
$script:StatusPill.Location = [Drawing.Point]::new(18, 31)
|
||||||
$script:StatusPill.BackColor = [Drawing.Color]::FromArgb(242, 153, 74)
|
$script:StatusPill.BackColor = $colors.Orange
|
||||||
$header.Controls.Add($script:StatusPill)
|
$statusCard.Controls.Add($script:StatusPill)
|
||||||
|
|
||||||
$script:StatusLabel = [Windows.Forms.Label]::new()
|
$script:StatusLabel = New-Label -Text "Checking..." -X 40 -Y 26 -Width 210 -Height 24 -Color $colors.Text -Font ([Drawing.Font]::new("Segoe UI", 10, [Drawing.FontStyle]::Bold))
|
||||||
$script:StatusLabel.Text = "Checking..."
|
|
||||||
$script:StatusLabel.ForeColor = [Drawing.Color]::FromArgb(225, 231, 227)
|
|
||||||
$script:StatusLabel.AutoSize = $false
|
|
||||||
$script:StatusLabel.AutoEllipsis = $true
|
$script:StatusLabel.AutoEllipsis = $true
|
||||||
$script:StatusLabel.Location = [Drawing.Point]::new(674, 57)
|
$statusCard.Controls.Add($script:StatusLabel)
|
||||||
$script:StatusLabel.Size = [Drawing.Size]::new(190, 28)
|
|
||||||
$header.Controls.Add($script:StatusLabel)
|
|
||||||
|
|
||||||
$content = [Windows.Forms.Panel]::new()
|
$script:ProgressBar = [Windows.Forms.ProgressBar]::new()
|
||||||
$content.Dock = "Fill"
|
$script:ProgressBar.Anchor = "Top,Left,Right"
|
||||||
$content.Padding = [Windows.Forms.Padding]::new(30)
|
$script:ProgressBar.Location = [Drawing.Point]::new(28, 86)
|
||||||
$content.BackColor = [Drawing.Color]::FromArgb(22, 26, 29)
|
$script:ProgressBar.Size = [Drawing.Size]::new(1052, 4)
|
||||||
$form.Controls.Add($content)
|
$script:ProgressBar.Visible = $false
|
||||||
|
$header.Controls.Add($script:ProgressBar)
|
||||||
|
|
||||||
$infoPanel = [Windows.Forms.Panel]::new()
|
$shell = [Windows.Forms.Panel]::new()
|
||||||
$infoPanel.BackColor = [Drawing.Color]::FromArgb(31, 37, 40)
|
$shell.Dock = "Fill"
|
||||||
$infoPanel.Size = [Drawing.Size]::new(820, 226)
|
$shell.BackColor = $colors.Background
|
||||||
$infoPanel.Location = [Drawing.Point]::new(40, 34)
|
$form.Controls.Add($shell)
|
||||||
$content.Controls.Add($infoPanel)
|
|
||||||
|
|
||||||
$scopeLabel = [Windows.Forms.Label]::new()
|
$sidebar = [Windows.Forms.Panel]::new()
|
||||||
$scopeLabel.Text = "Scope"
|
$sidebar.Dock = "Left"
|
||||||
$scopeLabel.ForeColor = [Drawing.Color]::FromArgb(177, 190, 183)
|
$sidebar.Width = 220
|
||||||
$scopeLabel.Location = [Drawing.Point]::new(24, 24)
|
$sidebar.BackColor = $colors.Shell
|
||||||
$scopeLabel.AutoSize = $true
|
$shell.Controls.Add($sidebar)
|
||||||
$infoPanel.Controls.Add($scopeLabel)
|
|
||||||
|
$sideAccent = [Windows.Forms.Panel]::new()
|
||||||
|
$sideAccent.Dock = "Left"
|
||||||
|
$sideAccent.Width = 4
|
||||||
|
$sideAccent.BackColor = $colors.Green
|
||||||
|
$sidebar.Controls.Add($sideAccent)
|
||||||
|
|
||||||
|
$navTitle = New-Label -Text "Navigation" -X 24 -Y 26 -Width 160 -Height 22 -Color $colors.Muted -Font ([Drawing.Font]::new("Segoe UI", 8.5, [Drawing.FontStyle]::Bold))
|
||||||
|
$sidebar.Controls.Add($navTitle)
|
||||||
|
|
||||||
|
$script:NavButtons = @{}
|
||||||
|
$script:NavButtons.Trust = New-NavButton -Key "Trust" -Text "Trust" -Y 58
|
||||||
|
$script:NavButtons.Diagnostics = New-NavButton -Key "Diagnostics" -Text "File scan" -Y 110
|
||||||
|
$script:NavButtons.SmartScreen = New-NavButton -Key "SmartScreen" -Text "SmartScreen" -Y 162
|
||||||
|
foreach ($navButton in $script:NavButtons.Values) {
|
||||||
|
$sidebar.Controls.Add($navButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
$sideNote = New-Label -Text "Installs public certificates only. No Defender, SmartScreen, UAC, firewall, or policy bypasses." -X 24 -Y 510 -Width 164 -Height 96 -Color $colors.Muted -Font ([Drawing.Font]::new("Segoe UI", 8.5))
|
||||||
|
$sideNote.Anchor = "Left,Bottom"
|
||||||
|
$sidebar.Controls.Add($sideNote)
|
||||||
|
|
||||||
|
$contentHost = [Windows.Forms.Panel]::new()
|
||||||
|
$contentHost.Dock = "Fill"
|
||||||
|
$contentHost.BackColor = $colors.Background
|
||||||
|
$contentHost.Padding = [Windows.Forms.Padding]::new(34, 30, 34, 30)
|
||||||
|
$shell.Controls.Add($contentHost)
|
||||||
|
|
||||||
|
$script:Pages = @{}
|
||||||
|
|
||||||
|
$trustPage = [Windows.Forms.Panel]::new()
|
||||||
|
$trustPage.Dock = "Fill"
|
||||||
|
$trustPage.BackColor = $colors.Background
|
||||||
|
$contentHost.Controls.Add($trustPage)
|
||||||
|
$script:Pages.Trust = $trustPage
|
||||||
|
|
||||||
|
$trustTitle = New-PageTitle -Title "Trust" -Description "Install, remove, and verify the MrSphay public trust certificates."
|
||||||
|
$trustPage.Controls.Add($trustTitle.Title)
|
||||||
|
$trustPage.Controls.Add($trustTitle.Description)
|
||||||
|
|
||||||
|
$trustPanel = New-Card -X 0 -Y 82 -Width 820 -Height 236
|
||||||
|
$trustPage.Controls.Add($trustPanel)
|
||||||
|
|
||||||
|
$scopeLabel = New-Label -Text "Scope" -X 24 -Y 22 -Width 160 -Height 22 -Color $colors.Muted -Font ([Drawing.Font]::new("Segoe UI", 8.5, [Drawing.FontStyle]::Bold))
|
||||||
|
$trustPanel.Controls.Add($scopeLabel)
|
||||||
|
|
||||||
$script:AllUsersCheckBox = [Windows.Forms.CheckBox]::new()
|
$script:AllUsersCheckBox = [Windows.Forms.CheckBox]::new()
|
||||||
$script:AllUsersCheckBox.Text = "Install for all users (requires Administrator)"
|
$script:AllUsersCheckBox.Text = "All users (LocalMachine, requires Administrator)"
|
||||||
$script:AllUsersCheckBox.ForeColor = [Drawing.Color]::FromArgb(225, 231, 227)
|
$script:AllUsersCheckBox.ForeColor = $colors.Text
|
||||||
$script:AllUsersCheckBox.Location = [Drawing.Point]::new(24, 50)
|
$script:AllUsersCheckBox.Location = [Drawing.Point]::new(24, 46)
|
||||||
$script:AllUsersCheckBox.AutoSize = $true
|
$script:AllUsersCheckBox.AutoSize = $true
|
||||||
$script:AllUsersCheckBox.FlatStyle = "Flat"
|
$script:AllUsersCheckBox.FlatStyle = "Flat"
|
||||||
$script:AllUsersCheckBox.Add_CheckedChanged({ Refresh-MrTrustStatus })
|
$script:AllUsersCheckBox.Add_CheckedChanged({ Update-TrustStatus })
|
||||||
$infoPanel.Controls.Add($script:AllUsersCheckBox)
|
$trustPanel.Controls.Add($script:AllUsersCheckBox)
|
||||||
|
|
||||||
$rootLabel = [Windows.Forms.Label]::new()
|
$trustPanel.Controls.Add((New-Label -Text "Root thumbprint" -X 24 -Y 90 -Width 170 -Height 24))
|
||||||
$rootLabel.Text = "Root thumbprint"
|
$script:RootThumbprintLabel = New-Label -Text "-" -X 210 -Y 90 -Width 560 -Height 24 -Color $colors.Text -Font ([Drawing.Font]::new("Consolas", 9))
|
||||||
$rootLabel.ForeColor = [Drawing.Color]::FromArgb(177, 190, 183)
|
$script:RootThumbprintLabel.AutoEllipsis = $true
|
||||||
$rootLabel.Location = [Drawing.Point]::new(24, 92)
|
$trustPanel.Controls.Add($script:RootThumbprintLabel)
|
||||||
$rootLabel.AutoSize = $true
|
|
||||||
$infoPanel.Controls.Add($rootLabel)
|
|
||||||
|
|
||||||
$script:RootThumbprintLabel = [Windows.Forms.Label]::new()
|
$trustPanel.Controls.Add((New-Label -Text "Publisher thumbprint" -X 24 -Y 124 -Width 170 -Height 24))
|
||||||
$script:RootThumbprintLabel.Text = "-"
|
$script:PublisherThumbprintLabel = New-Label -Text "-" -X 210 -Y 124 -Width 560 -Height 24 -Color $colors.Text -Font ([Drawing.Font]::new("Consolas", 9))
|
||||||
$script:RootThumbprintLabel.ForeColor = [Drawing.Color]::FromArgb(225, 231, 227)
|
$script:PublisherThumbprintLabel.AutoEllipsis = $true
|
||||||
$script:RootThumbprintLabel.Font = [Drawing.Font]::new("Consolas", 9)
|
$trustPanel.Controls.Add($script:PublisherThumbprintLabel)
|
||||||
$script:RootThumbprintLabel.Location = [Drawing.Point]::new(180, 92)
|
|
||||||
$script:RootThumbprintLabel.AutoSize = $true
|
|
||||||
$infoPanel.Controls.Add($script:RootThumbprintLabel)
|
|
||||||
|
|
||||||
$publisherLabel = [Windows.Forms.Label]::new()
|
$trustPanel.Controls.Add((New-Label -Text "Expires" -X 24 -Y 158 -Width 170 -Height 24))
|
||||||
$publisherLabel.Text = "Publisher thumbprint"
|
$script:ExpiryLabel = New-Label -Text "-" -X 210 -Y 158 -Width 180 -Height 24 -Color $colors.Text
|
||||||
$publisherLabel.ForeColor = [Drawing.Color]::FromArgb(177, 190, 183)
|
$trustPanel.Controls.Add($script:ExpiryLabel)
|
||||||
$publisherLabel.Location = [Drawing.Point]::new(24, 128)
|
|
||||||
$publisherLabel.AutoSize = $true
|
|
||||||
$infoPanel.Controls.Add($publisherLabel)
|
|
||||||
|
|
||||||
$script:PublisherThumbprintLabel = [Windows.Forms.Label]::new()
|
$trustPanel.Controls.Add((New-Label -Text "Active scope" -X 24 -Y 192 -Width 170 -Height 24))
|
||||||
$script:PublisherThumbprintLabel.Text = "-"
|
$script:ScopeValueLabel = New-Label -Text "-" -X 210 -Y 192 -Width 200 -Height 24 -Color $colors.Text
|
||||||
$script:PublisherThumbprintLabel.ForeColor = [Drawing.Color]::FromArgb(225, 231, 227)
|
$trustPanel.Controls.Add($script:ScopeValueLabel)
|
||||||
$script:PublisherThumbprintLabel.Font = [Drawing.Font]::new("Consolas", 9)
|
|
||||||
$script:PublisherThumbprintLabel.Location = [Drawing.Point]::new(180, 128)
|
|
||||||
$script:PublisherThumbprintLabel.AutoSize = $true
|
|
||||||
$infoPanel.Controls.Add($script:PublisherThumbprintLabel)
|
|
||||||
|
|
||||||
$expiryLabelTitle = [Windows.Forms.Label]::new()
|
$summaryPanel = New-Card -X 0 -Y 338 -Width 820 -Height 76 -BackColor $colors.PanelAlt
|
||||||
$expiryLabelTitle.Text = "Expires"
|
$trustPage.Controls.Add($summaryPanel)
|
||||||
$expiryLabelTitle.ForeColor = [Drawing.Color]::FromArgb(177, 190, 183)
|
|
||||||
$expiryLabelTitle.Location = [Drawing.Point]::new(24, 164)
|
|
||||||
$expiryLabelTitle.AutoSize = $true
|
|
||||||
$infoPanel.Controls.Add($expiryLabelTitle)
|
|
||||||
|
|
||||||
$script:ExpiryLabel = [Windows.Forms.Label]::new()
|
$script:TrustSummaryLabel = New-Label -Text "Checking trust state..." -X 22 -Y 18 -Width 760 -Height 34 -Color $colors.Text -Font ([Drawing.Font]::new("Segoe UI", 10, [Drawing.FontStyle]::Bold))
|
||||||
$script:ExpiryLabel.Text = "-"
|
$summaryPanel.Controls.Add($script:TrustSummaryLabel)
|
||||||
$script:ExpiryLabel.ForeColor = [Drawing.Color]::FromArgb(225, 231, 227)
|
|
||||||
$script:ExpiryLabel.Location = [Drawing.Point]::new(180, 164)
|
|
||||||
$script:ExpiryLabel.AutoSize = $true
|
|
||||||
$infoPanel.Controls.Add($script:ExpiryLabel)
|
|
||||||
|
|
||||||
$installButton = [Windows.Forms.Button]::new()
|
$installButton = [Windows.Forms.Button]::new()
|
||||||
$installButton.Text = "Install trust"
|
$installButton.Text = "Install trust"
|
||||||
$installButton.BackColor = [Drawing.Color]::FromArgb(28, 185, 111)
|
$installButton.Size = [Drawing.Size]::new(160, 44)
|
||||||
$installButton.ForeColor = [Drawing.Color]::White
|
$installButton.Location = [Drawing.Point]::new(0, 438)
|
||||||
$installButton.FlatStyle = "Flat"
|
Add-AnimatedButton -Button $installButton -Normal $colors.Green -Hover $colors.GreenHover
|
||||||
$installButton.Size = [Drawing.Size]::new(180, 46)
|
|
||||||
$installButton.Location = [Drawing.Point]::new(40, 292)
|
|
||||||
$installButton.Add_Click({ Install-MrTrustCertificates })
|
$installButton.Add_Click({ Install-MrTrustCertificates })
|
||||||
$content.Controls.Add($installButton)
|
$trustPage.Controls.Add($installButton)
|
||||||
|
|
||||||
$removeButton = [Windows.Forms.Button]::new()
|
$removeButton = [Windows.Forms.Button]::new()
|
||||||
$removeButton.Text = "Remove trust"
|
$removeButton.Text = "Remove trust"
|
||||||
$removeButton.BackColor = [Drawing.Color]::FromArgb(44, 52, 56)
|
$removeButton.Size = [Drawing.Size]::new(160, 44)
|
||||||
$removeButton.ForeColor = [Drawing.Color]::FromArgb(225, 231, 227)
|
$removeButton.Location = [Drawing.Point]::new(176, 438)
|
||||||
$removeButton.FlatStyle = "Flat"
|
Add-AnimatedButton -Button $removeButton -Normal $colors.PanelAlt -Hover $colors.Border
|
||||||
$removeButton.Size = [Drawing.Size]::new(180, 46)
|
|
||||||
$removeButton.Location = [Drawing.Point]::new(240, 292)
|
|
||||||
$removeButton.Add_Click({ Remove-MrTrustCertificates })
|
$removeButton.Add_Click({ Remove-MrTrustCertificates })
|
||||||
$content.Controls.Add($removeButton)
|
$trustPage.Controls.Add($removeButton)
|
||||||
|
|
||||||
$refreshButton = [Windows.Forms.Button]::new()
|
$refreshButton = [Windows.Forms.Button]::new()
|
||||||
$refreshButton.Text = "Refresh"
|
$refreshButton.Text = "Refresh"
|
||||||
$refreshButton.BackColor = [Drawing.Color]::FromArgb(44, 52, 56)
|
$refreshButton.Size = [Drawing.Size]::new(124, 44)
|
||||||
$refreshButton.ForeColor = [Drawing.Color]::FromArgb(225, 231, 227)
|
$refreshButton.Location = [Drawing.Point]::new(352, 438)
|
||||||
$refreshButton.FlatStyle = "Flat"
|
Add-AnimatedButton -Button $refreshButton -Normal $colors.PanelAlt -Hover $colors.Border
|
||||||
$refreshButton.Size = [Drawing.Size]::new(140, 46)
|
$refreshButton.Add_Click({ Update-TrustStatus })
|
||||||
$refreshButton.Location = [Drawing.Point]::new(440, 292)
|
$trustPage.Controls.Add($refreshButton)
|
||||||
$refreshButton.Add_Click({ Refresh-MrTrustStatus })
|
|
||||||
$content.Controls.Add($refreshButton)
|
|
||||||
|
|
||||||
$note = [Windows.Forms.Label]::new()
|
$note = New-Label -Text "Trust actions are reversible and scoped to the selected Windows certificate store." -X 0 -Y 508 -Width 820 -Height 26 -Color $colors.Muted
|
||||||
$note.Text = "MrTrust installs public certificates only. It does not disable Defender, SmartScreen, UAC, or enterprise policies."
|
$trustPage.Controls.Add($note)
|
||||||
$note.ForeColor = [Drawing.Color]::FromArgb(177, 190, 183)
|
|
||||||
$note.Location = [Drawing.Point]::new(40, 376)
|
|
||||||
$note.Size = [Drawing.Size]::new(820, 48)
|
|
||||||
$content.Controls.Add($note)
|
|
||||||
|
|
||||||
$form.Add_Shown({ Refresh-MrTrustStatus })
|
$diagnosticsPage = [Windows.Forms.Panel]::new()
|
||||||
|
$diagnosticsPage.Dock = "Fill"
|
||||||
|
$diagnosticsPage.BackColor = $colors.Background
|
||||||
|
$diagnosticsPage.Visible = $false
|
||||||
|
$contentHost.Controls.Add($diagnosticsPage)
|
||||||
|
$script:Pages.Diagnostics = $diagnosticsPage
|
||||||
|
|
||||||
|
$diagnosticsTitle = New-PageTitle -Title "File scan" -Description "Inspect a Windows executable, installer, catalog, or DLL for signature and origin signals."
|
||||||
|
$diagnosticsPage.Controls.Add($diagnosticsTitle.Title)
|
||||||
|
$diagnosticsPage.Controls.Add($diagnosticsTitle.Description)
|
||||||
|
|
||||||
|
$filePanel = New-Card -X 0 -Y 82 -Width 820 -Height 420
|
||||||
|
$diagnosticsPage.Controls.Add($filePanel)
|
||||||
|
|
||||||
|
$chooseButton = [Windows.Forms.Button]::new()
|
||||||
|
$chooseButton.Text = "Choose file"
|
||||||
|
$chooseButton.Size = [Drawing.Size]::new(150, 42)
|
||||||
|
$chooseButton.Location = [Drawing.Point]::new(24, 24)
|
||||||
|
Add-AnimatedButton -Button $chooseButton -Normal $colors.Green -Hover $colors.GreenHover
|
||||||
|
$filePanel.Controls.Add($chooseButton)
|
||||||
|
|
||||||
|
$scanButton = [Windows.Forms.Button]::new()
|
||||||
|
$scanButton.Text = "Scan again"
|
||||||
|
$scanButton.Size = [Drawing.Size]::new(130, 42)
|
||||||
|
$scanButton.Location = [Drawing.Point]::new(190, 24)
|
||||||
|
Add-AnimatedButton -Button $scanButton -Normal $colors.PanelAlt -Hover $colors.Border
|
||||||
|
$filePanel.Controls.Add($scanButton)
|
||||||
|
|
||||||
|
$script:FileVerdictLabel = New-Label -Text "Choose a Windows app or installer to inspect." -X 24 -Y 88 -Width 760 -Height 30 -Color $colors.Muted -Font ([Drawing.Font]::new("Segoe UI", 11, [Drawing.FontStyle]::Bold))
|
||||||
|
$filePanel.Controls.Add($script:FileVerdictLabel)
|
||||||
|
|
||||||
|
$filePanel.Controls.Add((New-Label -Text "File" -X 24 -Y 136 -Width 170 -Height 24))
|
||||||
|
$script:FileNameLabel = New-Label -Text "-" -X 210 -Y 136 -Width 560 -Height 24 -Color $colors.Text
|
||||||
|
$script:FileNameLabel.AutoEllipsis = $true
|
||||||
|
$filePanel.Controls.Add($script:FileNameLabel)
|
||||||
|
|
||||||
|
$filePanel.Controls.Add((New-Label -Text "Path" -X 24 -Y 170 -Width 170 -Height 24))
|
||||||
|
$script:FilePathLabel = New-Label -Text "-" -X 210 -Y 170 -Width 560 -Height 40 -Color $colors.Text
|
||||||
|
$script:FilePathLabel.AutoEllipsis = $true
|
||||||
|
$filePanel.Controls.Add($script:FilePathLabel)
|
||||||
|
|
||||||
|
$filePanel.Controls.Add((New-Label -Text "Signature status" -X 24 -Y 222 -Width 170 -Height 24))
|
||||||
|
$script:SignatureStatusLabel = New-Label -Text "-" -X 210 -Y 222 -Width 560 -Height 24 -Color $colors.Text
|
||||||
|
$filePanel.Controls.Add($script:SignatureStatusLabel)
|
||||||
|
|
||||||
|
$filePanel.Controls.Add((New-Label -Text "Signer" -X 24 -Y 256 -Width 170 -Height 24))
|
||||||
|
$script:SignerLabel = New-Label -Text "-" -X 210 -Y 256 -Width 560 -Height 36 -Color $colors.Text
|
||||||
|
$script:SignerLabel.AutoEllipsis = $true
|
||||||
|
$filePanel.Controls.Add($script:SignerLabel)
|
||||||
|
|
||||||
|
$filePanel.Controls.Add((New-Label -Text "MrSphay match" -X 24 -Y 306 -Width 170 -Height 24))
|
||||||
|
$script:MrSphayMatchLabel = New-Label -Text "-" -X 210 -Y 306 -Width 160 -Height 24 -Color $colors.Text
|
||||||
|
$filePanel.Controls.Add($script:MrSphayMatchLabel)
|
||||||
|
|
||||||
|
$filePanel.Controls.Add((New-Label -Text "Mark-of-the-Web" -X 390 -Y 306 -Width 160 -Height 24))
|
||||||
|
$script:MotwLabel = New-Label -Text "-" -X 560 -Y 306 -Width 160 -Height 24 -Color $colors.Text
|
||||||
|
$filePanel.Controls.Add($script:MotwLabel)
|
||||||
|
|
||||||
|
$filePanel.Controls.Add((New-Label -Text "SmartScreen note" -X 24 -Y 352 -Width 170 -Height 24))
|
||||||
|
$script:SmartScreenLabel = New-Label -Text "-" -X 210 -Y 352 -Width 560 -Height 48 -Color $colors.Muted
|
||||||
|
$filePanel.Controls.Add($script:SmartScreenLabel)
|
||||||
|
|
||||||
|
$chooseButton.Add_Click({
|
||||||
|
$dialog = [Windows.Forms.OpenFileDialog]::new()
|
||||||
|
$dialog.Filter = "Windows apps and installers (*.exe;*.msi;*.dll;*.cat)|*.exe;*.msi;*.dll;*.cat|All files (*.*)|*.*"
|
||||||
|
if ($dialog.ShowDialog() -eq [Windows.Forms.DialogResult]::OK) {
|
||||||
|
$script:SelectedFilePath = $dialog.FileName
|
||||||
|
Test-SelectedFile -Path $script:SelectedFilePath
|
||||||
|
}
|
||||||
|
})
|
||||||
|
$scanButton.Add_Click({
|
||||||
|
if ($script:SelectedFilePath) {
|
||||||
|
Test-SelectedFile -Path $script:SelectedFilePath
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
$helpPage = [Windows.Forms.Panel]::new()
|
||||||
|
$helpPage.Dock = "Fill"
|
||||||
|
$helpPage.BackColor = $colors.Background
|
||||||
|
$helpPage.Visible = $false
|
||||||
|
$contentHost.Controls.Add($helpPage)
|
||||||
|
$script:Pages.SmartScreen = $helpPage
|
||||||
|
|
||||||
|
$helpTitle = New-PageTitle -Title "SmartScreen" -Description "Understand what MrTrust can verify and what Windows reputation still controls."
|
||||||
|
$helpPage.Controls.Add($helpTitle.Title)
|
||||||
|
$helpPage.Controls.Add($helpTitle.Description)
|
||||||
|
|
||||||
|
$helpPanel = New-Card -X 0 -Y 82 -Width 820 -Height 330
|
||||||
|
$helpPage.Controls.Add($helpPanel)
|
||||||
|
|
||||||
|
$helpPanel.Controls.Add((New-Label -Text "Local trust" -X 24 -Y 24 -Width 180 -Height 24 -Color $colors.Text -Font ([Drawing.Font]::new("Segoe UI", 11, [Drawing.FontStyle]::Bold))))
|
||||||
|
$helpPanel.Controls.Add((New-Label -Text "MrTrust installs the public MrSphay root and publisher certificates into the selected Windows certificate stores." -X 24 -Y 54 -Width 740 -Height 42 -Color $colors.Muted))
|
||||||
|
|
||||||
|
$helpPanel.Controls.Add((New-Label -Text "Windows reputation" -X 24 -Y 118 -Width 220 -Height 24 -Color $colors.Text -Font ([Drawing.Font]::new("Segoe UI", 11, [Drawing.FontStyle]::Bold))))
|
||||||
|
$helpPanel.Controls.Add((New-Label -Text "SmartScreen can still warn for a new or rarely downloaded file, even when the signature is valid and the publisher is recognized." -X 24 -Y 148 -Width 740 -Height 42 -Color $colors.Muted))
|
||||||
|
|
||||||
|
$helpPanel.Controls.Add((New-Label -Text "What to check" -X 24 -Y 212 -Width 180 -Height 24 -Color $colors.Text -Font ([Drawing.Font]::new("Segoe UI", 11, [Drawing.FontStyle]::Bold))))
|
||||||
|
$helpPanel.Controls.Add((New-Label -Text "Use File scan to verify signature status, MrSphay signer matching, and Mark-of-the-Web. MrTrust never disables SmartScreen." -X 24 -Y 242 -Width 740 -Height 46 -Color $colors.Muted))
|
||||||
|
|
||||||
|
$pulseTimer = [Windows.Forms.Timer]::new()
|
||||||
|
$pulseTimer.Interval = 100
|
||||||
|
$pulseTimer.Add_Tick({
|
||||||
|
$script:CurrentAccent = ($script:CurrentAccent + 1) % 40
|
||||||
|
$value = 130 + [Math]::Abs(20 - $script:CurrentAccent) * 4
|
||||||
|
$sideAccent.BackColor = [Drawing.Color]::FromArgb(0, [Math]::Min(205, $value), 91)
|
||||||
|
})
|
||||||
|
$pulseTimer.Start()
|
||||||
|
|
||||||
|
$form.Add_Shown({
|
||||||
|
Show-MrTrustPage -Key "Trust"
|
||||||
|
Update-TrustStatus
|
||||||
|
})
|
||||||
[Windows.Forms.Application]::Run($form)
|
[Windows.Forms.Application]::Run($form)
|
||||||
|
|||||||
Reference in New Issue
Block a user