Managed deployment on Windows
Push the Windows observer to a fleet with Intune, Group Policy, SCCM, or an RMM.
Push the Windows observer to a fleet with your device-management tool. Devices enroll with an enrollment token and are attributed to their signed-in Windows user automatically, or to a specific person if you pass their email as USER_EMAIL.
Step 1: Download the installer
Get ProxonObserver.msi from Install. That page serves the build for this environment, so take the .msi from there rather than reusing a download link from another environment.
Step 2: Generate an enrollment token
Create one in the Enrollment tokens block on the Devices settings page.
Step 3: Run the silent install
Run the install with the token, pushed to each machine.
Silent install
msiexec /i ProxonObserver.msi ENROLL_TOKEN=<token> /quiet /norestartReplace <token> with the enrollment token you generated. To attribute the install to a specific person, add USER_EMAIL="ada@acme.com".
MSI properties
| Property | Detail |
|---|---|
ENROLL_TOKEN |
Enrollment token, a secret. Required for a fleet push. |
TENANT_ID |
Tenant or organization id, when the token does not already pin it. |
USER_EMAIL |
Optional. The employee's email or UPN, for example ada@acme.com, to attribute the device to that person, overriding the auto-detected identity. Omit to fall back to auto-detection. |
INGEST_URL |
Custom ingest endpoint. Omit to use the default. |
UPDATE_CHANNEL |
Update track: stable, the default, beta, or canary. This is not a switch. To stop automatic updates, use the Disable automatic updates Group Policy instead. |
POLICY_LOCK |
Set to 1 to lock enterprise mode so users cannot opt out. |
Standard installer switches apply: /quiet, /qn, /norestart, /l*v install.log, and TRANSFORMS=.
Property names must be uppercase, and an empty value counts as absent, so the installer skips it rather than writing a blank.
How devices are attributed to people
By default the observer resolves the logged-in Windows user's UPN, meaning their user@domain on an Entra or Azure AD-joined or domain-joined machine, called the system email, and the backend maps that UPN to the person. No extra input is needed.
To attribute a device explicitly, pass USER_EMAIL="ada@acme.com". It is sent as the enrollment's windows_upn and overrides the auto-detected identity. It is stored only in the admin-only enrollment.json, never the registry.
Workgroup caveat: on a non-domain machine the auto-detected UPN degrades to DOMAIN\user, which weakens automatic attribution. Pass USER_EMAIL, or have the user sign in through the browser device-code flow after install, which needs no token.
Push the .msi with the same properties through Intune, Group Policy, or SCCM, or run it from a NinjaOne script, or by hand on a single machine. Pick the channel your fleet already uses.
Microsoft Intune (Win32 app)
Intune does not assign a .msi directly. Wrap it with the Microsoft Win32 Content Prep Tool to produce an .intunewin package first.
-
Download the Win32 Content Prep Tool and extract
IntuneWinAppUtil.exe. -
Put
ProxonObserver.msiin its own source folder, then run the prep tool against it:IntuneWinAppUtil.exe -c C:\IntunePkg\ProxonObserver -s ProxonObserver.msi -o C:\IntunePkg\Output -
In the Intune admin center go to Apps, Windows, Add, choose Windows app (Win32), and upload
ProxonObserver.intunewin. -
Set the Install command to the silent-install command above, with your token, plus any other properties you need.
-
Set the Uninstall command. Pass the enrollment token, since that is the one uninstall form valid in every device state. See Uninstall and retire a device below for why a bare
/xis refused on an enterprise install. Intune runs this from the package it already extracted, so naming the.msikeeps it pointed at the version that package installs, which is only the installed version while the device is actually on it. A fleet mid-upgrade, or a machine that missed a release, is on a different build, and/xagainst the wrong package returns1605. See Troubleshooting, Common failure modes below.msiexec /x ProxonObserver.msi ENROLL_TOKEN=<token> /quiet /norestart
This command carries a secret. Intune stores it in the app configuration, shows it to any admin who opens the app, and every device writes it to AppEnforce.log when it runs. The installer's Hidden="yes" masks the token in the MSI log only. It does nothing for the copies your management tool keeps. Treat the uninstall command as a secret and rotate the token if it is exposed.
- Add a Detection rule. Prefer MSI product code detection, since Intune reads the product code out of the package you upload, so it is right for the version you are deploying. The product code is per-version, not stable. The installer declares only an
UpgradeCodeand noProductCode, so every build gets a fresh product GUID, andUpgradeCodeis the identifier that survives upgrades. Upload the new package each release and Intune re-populates the rule for you. Anything you hard-code from a product code has to be re-pointed by hand. Only fall back to a file-exists rule on%PROGRAMFILES%\Proxon\app-X.Y.Z\ProxonObserver.exe, and if you do, substitute the version you are deploying forX.Y.Zand re-point the rule on every upgrade. Set Requirements to Windows 10 or 11, x64. - Assign it to your target device groups. Devices install on their next check-in, roughly every 8 hours by default, or force a sync from Company Portal, Settings, Sync. Track rollout under Apps, ProxonObserver, Device install status.
Transforms: Intune's Win32 wrapper cannot pass TRANSFORMS= on the command line the way a shell can. Intune supports command-line properties natively, so put the properties in the install command, or, if you must ship an .mst, pre-apply it to the MSI and repackage the result.
The install command is visible to admins in the Intune portal. Rotate the enrollment token after rollout, or use a short-lived one, but rotate the uninstall command with it. An uninstall only authorizes a device that still holds the token on its command line, so a rotation leaves the configured uninstall unable to retire the fleet it was configured for until you re-provision those devices onto the new token. See Re-provision or deprovision a device below.
Group Policy (GPO)
Group Policy does two separate jobs here. It pushes the MSI, and it manages the observer's update policy.
Pushing the MSI
- Copy
ProxonObserver.msito a network share every target machine can read, for example\\fileserver\software\proxon\. - Open the Group Policy Management Console with
gpmc.mscand create or edit a GPO linked to the target OU. - Go to Computer Configuration, Policies, Software Settings, Software installation, then right-click, New, Package.
- Browse to the MSI by UNC path. A mapped drive will not work.
- Deploy it as Assigned. Machines install on their next Group Policy refresh plus reboot.
An assigned package takes no command-line properties, so this is the one channel where ENROLL_TOKEN= cannot simply be typed in. Put the properties into an .mst transform, which Orca or InstEd both author, attach it under the package's Modifications tab, and keep it on the same share. To test the transform on one machine first:
msiexec /i ProxonObserver.msi TRANSFORMS=acme-corp.mst /quietManaging update policy (ADMX)
You do not have to find or stage the administrative templates. The MSI already installs them on every machine, at %SystemRoot%\System32\PolicyDefinitions\Proxon.admx and %SystemRoot%\System32\PolicyDefinitions\en-US\Proxon.adml. The only manual step is copying that pair from one installed machine into your domain controller's SYSVOL PolicyDefinitions central store, with the .admx at the top level and the .adml in its en-US subfolder.
Once it is there, the Proxon policies appear in the Group Policy editor under Administrative Templates, Proxon. The Updates category is the one most fleets touch, covering update channel, pinned version, the deferral window, maximum deferral days, and disabling automatic updates altogether. The templates also ship categories for capture, log shipping, WSL integration, tamper protection, and data-loss prevention. Browse the editor for the current, complete list. Intune can consume the same templates through imported administrative templates.
SCCM and ConfigMgr
Create an application deployment and put the silent-install command above into the Installation program field. Properties and transforms behave exactly as they do on a command line, so nothing else is Proxon-specific.
Uninstall program
Put the token-bearing form in the Uninstall program field. It is the one uninstall valid in every device state, see Uninstall and retire a device below, and ConfigMgr runs it from the deployment type's own content, so naming the .msi keeps it matched to the version that deployment type installs:
msiexec /x ProxonObserver.msi ENROLL_TOKEN=<token> /quiet /norestartThat only holds while the deployment type actually delivers content for the uninstall. On its Content tab, leave Uninstall content settings at Same as install content. Set it to No uninstall content and the uninstall command runs with no package folder, so there is no ProxonObserver.msi for it to name. As with Intune, the package matches only a device that is on that version, and a fleet mid-upgrade earns a 1605. See Troubleshooting, Common failure modes below.
The same secret handling applies as in Intune. ConfigMgr stores this command in the application model, and each device writes it to AppEnforce.log. Rotate the token if it is exposed, and re-provision any device whose configured uninstall still carries the old one.
Detection method
Use a Windows Installer clause matched on the MSI's product code, but that code is per-version. The installer declares an UpgradeCode and no ProductCode, so WiX generates a fresh product GUID on every build, and only UpgradeCode is stable across releases. Update the clause each release with the code the new build actually installed. Read it off an installed machine, where IdentifyingNumber is the product code:
Get-CimInstance Win32_Product -Filter "Name LIKE 'Proxon%'" | Select-Object Name, Version, IdentifyingNumberA file-path clause pinned to app-X.Y.Z\ has the same problem for the same reason, so neither clause is set-and-forget.
NinjaOne
NinjaOne is RMM-first, not an MDM. It deploys by running a script on the endpoint rather than by pushing a managed package. There is no Proxon app to add. Create a script or automation that runs the same silent install, and let it run with administrator rights.
# Replace the lookup on the next line with your NinjaOne custom-field accessor before running this.
$token = <your NinjaOne custom-field lookup>
msiexec /i ProxonObserver.msi ENROLL_TOKEN="$token" /quiet /norestartRead the token from a NinjaOne custom field instead of hard-coding it, so one script covers the whole fleet. Substitute whatever field lookup your Ninja instance uses. Attribution needs nothing extra here, since the observer auto-detects the signed-in user's UPN. Add USER_EMAIL from a per-device custom field only where that detection is weak.
Whatever NinjaOne records about the script it ran will contain the token, so treat the script as a secret and rotate the token here if that changes.
Manual install
For one machine or a pilot, double-click the .msi or run it with a basic progress bar and no prompts:
msiexec /i ProxonObserver.msi /qbNo token? Install without one and have the person sign in through the browser device-code flow, which is the self-serve path and needs no enrollment token at all. To pre-enroll instead, add ENROLL_TOKEN=<token> and any other properties to the same command.
Uninstall and retire a device
A device installed with a token refuses a bare msiexec /x at every point in its life, not just part of it. Two things mark it enterprise: the enrollment token sitting in enrollment.json before it enrolls, and the durable marker the observer writes into that same file the moment it does. One or the other is present from install until the device is properly retired, so a plain msiexec /x is blocked throughout and msiexec returns 1603.
On a successful enrollment the observer clears the single-use token from the file and stamps enterprise_enrolled_at in its place. That marker is what carries the device's enterprise status across restarts. Until it existed a freshly enrolled machine read back as self-serve and any local administrator could retire it with a bare /x, and that gap is closed. The same refusal covers the two states that were always blocked: a device that never finished enrolling, and one whose enrollment.json cannot be read while the machine still registers as enterprise.
What this is. It stops the one-command removal: on an enrolled device msiexec /x on its own now fails, where before it succeeded. It is not a tamper-proof lock, and is not meant to be. An administrator can still remove the observer with FORCE_UNINSTALL=1 below, or by deleting enrollment.json, which the guard deliberately reads as self-serve so that a half-broken install can never become impossible to uninstall. Treat it as a deployment control that keeps a managed device managed, not as a guarantee against a local administrator who intends to remove it.
Devices enrolled before this release. The marker is written at enrollment, so a device that enrolled earlier gets one only if the observer can backfill it on its next start, and that needs both the device credential and a TENANT_ID recorded in enrollment.json. A fleet installed with only ENROLL_TOKEN, as the command above shows, has no tenant id recorded, so those devices are not backfilled and keep the old behavior, meaning a bare /x still retires them, until they re-enroll. Pass TENANT_ID at install, or re-enroll, if you need the block on an existing fleet.
Configure the token-bearing command in your MDM. It is the one form that works in every one of those states, so a command you set up once does not depend on which state a machine happens to be in when you retire it:
msiexec /x ProxonObserver.msi ENROLL_TOKEN=<token> /quiet /norestartThe token has to match the one that device installed with, so a rotated token will not retire a device still holding the old one. Re-provision it first, see Re-provision or deprovision a device below. Once the device has enrolled there is no token left in enrollment.json to compare against, so the guard matches what you pass against the copy the MSI recorded at install time, which is why this command keeps working after enrollment. The command carries a secret, so whatever your management tool stores and logs, such as the Intune app configuration, the ConfigMgr application model, or AppEnforce.log on the device, will contain it.
The override, when the matching token is unavailable:
msiexec /x ProxonObserver.msi FORCE_UNINSTALL=1 /quiet /norestartFORCE_UNINSTALL=1 bypasses policy, so keep it for one-off recovery, such as a lost token or a corrupted enrollment, not for fleet retirement.
Not available yet: the guard also accepts a .unenroll-authorized marker file on the device, valid for 7 days. Nothing writes that file today, so it is not a retirement path you can use, and it is not a way to avoid putting a token on the command line. The server side is not a substitute either. Deactivate, on a person's device card under Members, is the only in-app control that reaches an IT-enrolled device. It stops the device reporting and fails its credential refresh server-side, but it does not authorize an uninstall on the machine.
A self-serve install, one done without a token, carries no enterprise policy and uninstalls with no authorization at all.
Re-provision or deprovision a device
Enrollment is sticky on purpose. Once a device enrolls it holds a machine credential, and the observer skips enrollment for as long as that credential is there. Re-imaging the box, handing it to a new person, or issuing it a new token does not re-enroll it on its own. There are two separate levers:
reset-enrollmentclears the credential the device is already holding, which reopens the enrollment gate. It runs on the machine, needs no reinstall, and keepsenrollment.json, meaning the tenant, ingest URL, and update channel you deployed with. It re-enrolls the device on its own only while that file still holds an unused enrollment token. Enrolling consumes the token, so on a device that has already enrolled, the reset leaves it with neither a credential nor a token, and it stops reporting until you deliver a fresh token. The command tells you which case you are in.WRITE_ENROLLMENT_ON_UPGRADE=1is an install-time property. It re-stamps that enrollment file on an install pass that would otherwise preserve it, which is how a new token, tenant, or ingest URL reaches the device at all.
On a device that has already enrolled, the property on its own changes nothing about enrollment, since the freshly stamped token sits unread behind the credential that is still there. Reset the credential, deliver the new config, and restart. On a machine that never enrolled, such as a self-serve install you are adopting into the fleet, the install property alone is enough.
Reset enrollment in place
Run in PowerShell as Administrator on the device. The first line finds the installed executable, since it lives in a per-version folder and there is no fixed path to type.
$exe = (Get-ChildItem "$env:ProgramW6432\Proxon\app-*\ProxonObserver.exe" | Sort-Object LastWriteTime | Select-Object -Last 1).FullName
if (-not $exe) { throw "ProxonObserver.exe not found under $env:ProgramW6432\Proxon\app-*. Is the observer installed?" }
& $exe reset-enrollmentOn its own this only re-enrolls a device that never consumed its token. The reset reopens the enrollment gate, but the service still needs a token in enrollment.json to walk through it, and a successful enrollment clears that token. So on a device that has already enrolled, a plain reset takes it off reporting until you deliver a fresh token, see Re-stamp the enrollment config below, and restart. The command says which case it left you in, either that it still carries an enroll token so the service will re-enroll on its next start, or that there is no enroll token because it was already consumed, so you must deliver a fresh one.
It prints what it cleared and is safe to run twice, since the second run is a no-op. If it reports that it could not remove the credential it exits non-zero, but it does not stop there. It goes on to clear device-credentials.json and the relayer routing env anyway, so the device is left partly cleared with the enrollment gate still shut. Re-run it from an elevated shell rather than deleting the registry key by hand. The only path that aborts leaving the device untouched is a --purge that cannot delete enrollment.json, described below.
Nothing takes effect until the service restarts. The reset does not stop or start the service, and a running service keeps using the credential it already loaded, so it can still report at the old target. This is the step whose absence turns a reset into a support ticket:
Restart-Service ProxonObserverRe-stamp the enrollment config
To rotate an enrollment token, or to move an already self-serve machine onto one without uninstalling first, re-run the install with WRITE_ENROLLMENT_ON_UPGRADE=1. That forces the enrollment file to be re-stamped instead of preserved.
msiexec /i ProxonObserver.msi ENROLL_TOKEN=<token> WRITE_ENROLLMENT_ON_UPGRADE=1 /quiet /norestartValues you do not pass are kept, so pass every property you want changed.
To rotate a live device onto a new token, run these on the machine in order: reset-enrollment, re-run the install with the new token, then restart the service. The reset has to come first, or the freshly stamped token sits unread behind the credential that is still there.
To kill the old credential server-side as well, which is worth doing on a compromised or reassigned device, do it first, before the three local steps above, so it is dead even if they are interrupted. Open Members, find the person the device is attributed to, and choose Deactivate on their device card. That is the only in-app control that reaches a device your management tool pushed, since the Enrolled devices table deliberately shows no per-row menu on IT-enrolled devices. It is reversible, since re-enrolling the device reactivates it, so it is safe to do before you know whether the machine is coming back.
That path reaches a device only when its owner has a Proxon account. Members lists account holders, so a device attributed to someone who has never signed in sits under nobody there, and a push to machines whose users are not Proxon accounts yet produces exactly those by default. Such a device can be switched off nowhere in the product today, and neither can an Unattributed row with no owner at all. Do not read the Enrolled devices table as evidence otherwise, since it fills the owner cell from the directory as well as from accounts, so a device can show a person's name there and still be reachable by no in-app control. For both, the local reset above is the whole story.
Do not reach for Revoke here. The only Revoke on this page is in the Enrollment tokens block, and it revokes the shared enrollment token, which stops every device from enrolling with it, not one machine. Deactivate is the per-device action. It stops the device reporting and fails its credential refresh, and it does not authorize an uninstall on the machine.
Deprovision a device
Run in PowerShell as Administrator, as above, since the verb clears machine-wide credential state and refuses to run from an unelevated shell whichever flags you pass.
Add --purge when the machine is being handed to someone else or decommissioned. It does everything the reset does and also deletes enrollment.json, which is where the enroll token and the USER_EMAIL you attributed the device with live. The device will not enroll again until a fresh enrollment file is delivered.
$exe = (Get-ChildItem "$env:ProgramW6432\Proxon\app-*\ProxonObserver.exe" | Sort-Object LastWriteTime | Select-Object -Last 1).FullName
if (-not $exe) { throw "ProxonObserver.exe not found under $env:ProgramW6432\Proxon\app-*. Is the observer installed?" }
& $exe reset-enrollment --purgeThe purge deletes enrollment.json first and stops there if it cannot, since a locked file aborts the whole reset rather than reopening enrollment while a usable token and someone's email are still on disk. Stop the service to free the lock and re-run.
There is an uninstall counterpart, uninstall --deprovision, which performs the same wipe as part of the observer's own uninstall:
# On an MSI-deployed device use reset-enrollment --purge instead, since this verb deletes files Windows Installer owns.
$exe = (Get-ChildItem "$env:ProgramW6432\Proxon\app-*\ProxonObserver.exe" | Sort-Object LastWriteTime | Select-Object -Last 1).FullName
if (-not $exe) { throw "ProxonObserver.exe not found under $env:ProgramW6432\Proxon\app-*. Is the observer installed?" }
& $exe uninstall --deprovisionTwo things it is not. It is not an authorization, since the uninstall guard described above runs only from the MSI, this flag never reaches it, and it decides exactly one thing, which is whether the machine credential is deleted. And it is not the msiexec path, since an MSI uninstall never deprovisions, and this verb removes the installed files that Windows Installer owns. On an MSI-deployed fleet, run reset-enrollment --purge while the observer is still installed, then retire the device with the uninstall command above.
Troubleshooting
Check the service
Get-Service ProxonObserverStart type must be Automatic. The status may read Running or Stopped straight after a silent install, and both are healthy. The installer does not start the service inside the install transaction, since a slow start there used to roll the whole install back. It registers the service to start automatically and then kicks off a best-effort start, so on a busy machine the service comes up moments later, or at the next boot. A service still Stopped after a reboot is the real fault, so read the service log below.
Verify enrollment and attribution
Run this in PowerShell as Administrator, since the file is readable only by LocalSystem and Administrators, so an ordinary shell cannot open it.
Get-Content "$env:ProgramData\Proxon\enrollment.json"Before a device enrolls, an enterprise install shows the token, tenant, and, if you passed it, user_email, which is what the device is attributed by. After it enrolls the token reads null and enterprise_enrolled_at is set instead: that is a healthy enrolled device, not a self-serve one. A self-serve install shows nulls throughout, which is correct for that path. The file lives at %PROGRAMDATA%\Proxon\enrollment.json and is readable only by LocalSystem and Administrators.
Read the service log
Get-Content "$env:ProgramData\Proxon\logs\service.log" -Tail 50%PROGRAMDATA%\Proxon\logs\service.log is the observer's own log and the first place to look when the service installs but nothing ever reports.
The install itself failed
Check Event Viewer, Windows Logs, Application, for MsiInstaller errors, then re-run with verbose logging and search install.log for the failing custom action.
msiexec /i ProxonObserver.msi ENROLL_TOKEN=<token> /l*v install.log /quietCommon failure modes
enrollment.jsonmissing after install: the MSI has to run elevated. Check the obvious impostor first, since Access Denied on the verify command above means your shell is not elevated, not that the file is missing or that the install needs re-running across the fleet. Re-read it from an elevated PowerShell before concluding anything. If it really is absent, check free space under%PROGRAMDATA%and whether antivirus quarantined files the installer wrote, then allow-listProxonObserver.exeand%PROGRAMDATA%\Proxon\.- A property did not land: the installer ignores empty values, so
ENROLL_TOKEN=""counts as absent, and lowercase property names are dropped by Windows Installer. Searchinstall.logfor the property name.ENROLL_TOKENis a secure property, so its value is masked in the log, which is expected, not a failure. - Installed but never reports: the MSI does not validate the token or the endpoint, since that happens at first service start. Confirm the token is still active in the Enrollment tokens block, and that the machine can reach your ingest host on port 443.
- Intune deployment stuck: the detection rule has to match the real install path, and the version in
app-X.Y.Z\changes on upgrade. Force a sync from the device, then readC:\ProgramData\Microsoft\IntuneManagementExtension\Logs\IntuneManagementExtension.logon that machine. - The uninstall returns
1605, meaning the action is only valid for products that are currently installed. This is not the authorization block, which is1603. It means the product you targeted is not the one on the machine. Every build gets a fresh product code, so a hard-coded GUID goes stale at the next release, and runningmsiexec /x ProxonObserver.msiagainst a different version's.msifails the same way. Point it at the installed version's package, or read the installed product code with the command under SCCM and ConfigMgr, Detection method above.
Verify that enrolled devices appear in the Enrolled devices list.