14-day trial, no credit cardStart now

PowerShell install script

Install-PermitUSB.ps1 is the recommended way to install, upgrade and uninstall on Windows endpoints. It wraps the MSI with what msiexec alone cannot do: prerequisite checks, friendly errors, automatic .NET 10 Desktop Runtime install, distinct exit codes for fleet-deploy branching, and an upgrade path that stops the running agent and tray before swapping binaries.

DeploymentRecommended

Quickstart

Get the exact command, with the token pre-filled, from the dashboard Enrollment page. Roughly, from PowerShell as Administrator in the folder you saved the script to:

powershell -ExecutionPolicy Bypass -File .\Install-PermitUSB.ps1 -TenantToken '<token>'

The -ExecutionPolicy Bypass argument applies only to that one invocation and does not change your system-wide policy. The script is EV code-signed, so on a RemoteSigned box it runs without Bypass too.

What the script does

  • Checks for admin elevation and 64-bit Windows up front
  • Probes for the .NET 10 Desktop Runtime through dotnet --list-runtimes at the arch-specific path, and if missing downloads and installs it silently from the official Microsoft URL
  • Downloads PermitUSB.msi using your enrollment token, or uses a local copy next to the script when you pass -LocalMsi
  • For upgrades, stops the agent service and force-kills the tray before running msiexec so the install does not fight locked files
  • Runs msiexec with the token, server and optional endpoint group
  • Prints a step marker for each phase and writes a full msiexec log to %TEMP%\PermitUSB-install.log on failure

Parameters

ParameterWhat it does
-TenantTokenThe enrollment token. Required for fresh installs and for upgrades that fetch the MSI from the dashboard, since the download endpoint is token-keyed. Optional with -Upgrade -LocalMsi.
-ServerAgent-channel URL, default https://agent.permitusb.com. On upgrades the script forwards it only if you set it explicitly, so a non-prod server is never silently re-pointed at prod.
-EndpointGroupPre-assigns the endpoint to a named group. Matched case-insensitively; unrecognized names fall back to the default group.
-InstallerBaseUrlWhere to fetch the MSI from, default https://permitusb.com. Override for an internal mirror.
-SkipPrereqsSkip the .NET 10 check and auto-install. Useful when the runtime is deployed through a separate channel and you want a loud failure otherwise. -Upgrade implies this.
-LocalMsiUse a PermitUSB.msi sitting next to the script instead of downloading.
-MsiPath <path>Explicit path to the MSI, including UNC paths. Mutually exclusive with -LocalMsi.
-UpgradeIn-place upgrade of an existing install.

Fresh install

The default path. Downloads the MSI by token, installs prerequisites, runs msiexec. The agent enrolls within a minute and appears on the Endpoints page as active.

Offline and vetted installs

For air-gapped fleets, SCCM or Intune packaging, and admins who want to vet the binary before deploying. Put PermitUSB.msi and Install-PermitUSB.ps1 in the same folder, then:

powershell -ExecutionPolicy Bypass -File .\Install-PermitUSB.ps1 -TenantToken '<token>' -LocalMsi

The script resolves $PSScriptRoot to find the MSI beside it and prints the MSI ProductVersion as a sanity check before installing. The script must be on disk for this: piping it through irm and iex leaves $PSScriptRoot empty, and the script fails fast with a clear message. The local MSI is not deleted after install, because you brought it.

Upgrades

Skips the .NET prereq check, drops the token requirement when combined with -LocalMsi, and explicitly stops the agent service and kills the tray before msiexec runs.

# Online upgrade, downloads the current MSI by token powershell -ExecutionPolicy Bypass -File .\Install-PermitUSB.ps1 -Upgrade -TenantToken '<token>' # Fully offline upgrade, no token needed powershell -ExecutionPolicy Bypass -File .\Install-PermitUSB.ps1 -Upgrade -LocalMsi

Why pre-stop? The MSI declares WixCloseApplications for the tray and ServiceControl Wait for the service, which usually works. But WixCloseApplications sends WM_CLOSE only, so a tray process that is hung or ignoring the message keeps a handle on its own EXE and the install bails with a locked-file 1603. The wrapper force-stops the process instead, which handles that failure mode.

Environment variables

For fleet-deploy wrappers that prefer environment configuration to arguments: PERMITUSB_TOKEN, PERMITUSB_SERVER and PERMITUSB_ENDPOINT_GROUP are fallbacks for the matching parameters.

$env:PERMITUSB_TOKEN = '<token>' powershell -ExecutionPolicy Bypass -File .\Install-PermitUSB.ps1

Exit codes

CodeMeaning
0Installed cleanly. A 3010 from msiexec surfaces as 0 with a reboot-requested note.
2No token provided, and not an -Upgrade -LocalMsi run.
3Not running as Administrator.
432-bit Windows.
5.NET runtime install failed. Check the Windows installer logs.
6MSI download failed: token invalid, expired, or a network problem.
7-LocalMsi could not find a usable MSI.
othermsiexec’s own exit code. Check %TEMP%\PermitUSB-install.log.

Inspect before running

The script is around 250 lines of readable PowerShell. Download it, open it in an editor, read it, then run it. It is EV code-signed by JJMK Studios, LLC; confirm the publisher with Get-AuthenticodeSignature before you trust it.

Something missing or wrong here? Tell us. Documentation gaps get filled fast.