Endpoint deployment

Configure policy, install the MSI and confirm that each device collects and uploads its health report.

1. Registry Configuration

All settings are read from a single registry key. Deploy via GPO Preferences, Intune OMA-URI, SCCM, or any registry tool.

Prefer Group Policy? Every value on this page is also available as a proper Administrative Template, with explain text, drop-down lists and range validation. Download the ADMX / ADML templates →
Registry Path
HKLM\SOFTWARE\Policies\Highwind

1.1 Background Collector

Value NameTypeDefaultDescription
EnableBackgroundCollectorDWORD01 = enable, 0 = off
CollectionIntervalMinutesDWORD480Minutes between collections (min 5)
CacheFolderSZ%ProgramData%\Highwind\cacheLocal cache folder
MaxCacheFilesDWORD48Rolling file count
CacheRetentionDaysDWORD30Delete older than N days (0 = no limit)

1.2 Upload: Function App

Value NameTypeDefaultDescription
EnableUploadDWORD01 = enable upload
FunctionAppUrlSZe.g. https://func-highwind.azurewebsites.net/api/HealthReportIngestion
FunctionAppAudienceSZe.g. api://highwind-func
UploadIntervalMinutesDWORD480Upload frequency (min 5)
UploadTimeoutSecondsDWORD30HTTP POST timeout (5–300)
UploadRetryCountDWORD2Retries on failure (0–10)

1.3 Upload: Direct Blob Storage (Alternative)

Value NameTypeDefaultDescription
EnableBlobUploadDWORD01 = enable blob upload
BlobStorageAccountNameSZStorage account name
BlobContainerNameSZmde-telemetryContainer name
BlobEndpointSuffixSZe.g. blob.core.usgovcloudapi.net

1.4 Identity / Authentication

Value NameTypeDefaultDescription
TenantIdSZ(auto)Auto-detected from PRT if blank
PreferredAuthMethodSZDefaultDefault (WAM broker, then non-interactive fallbacks) | WAM | DeviceCode | ManagedIdentity. Scheduled uploads never display a sign-in prompt.
AuthClientIdSZ(auto)Optional, but recommended for production. App (client) ID of the public client registration used for WAM/broker sign-in. When set, it is used on its own. When blank, the app ID inside FunctionAppAudience is tried first; which is already correct for the common setup where one registration both exposes the API and acts as the client; then the built-in Azure CLI client. Leaving it blank can mean your API is reached through Microsoft's own registration, so anyone with the Azure CLI can request tokens for it and Conditional Access cannot target an app you control. Whichever registration is used needs redirect URI ms-appx-web://microsoft.aad.brokerplugin/<client-id> registered under "Mobile and desktop applications", public client flows enabled, access to the exposed scope, and; if blob upload is enabled; a delegated user_impersonation permission on Azure Storage.
AzureEnvironmentSZPublicPublic | USGov | China | Germany
AuthorityHostOverrideSZ(auto)Custom Entra authority URI for sovereign / air-gapped clouds (e.g. https://login.microsoftonline.us/)

1.5 Data Scope

Control which telemetry categories are collected. All DWORD, 1 = on, 0 = off.

Value NameDefaultDescription
CollectDefenderStatus1RTP, Tamper, Signatures, engine + platform versions, scan times
CollectDefenderPolicies1ASR, NP, CFA, Device Control
CollectFirewallStatus1Domain/Private/Public profiles
CollectAppControl1WDAC status + .cip policy count
CollectDeviceGuard1VBS, HVCI, Credential Guard
CollectIntuneEnrollment1Intune / ConfigMgr info

1.6 Tagging / Organization

These values are written to the JSON snapshot and promoted to their own columns (DeviceTag, OrgUnit, Environment) in the Azure Table so Power BI can slice on them. The fleet agent (3.7.0) also reports them to the management console, where they group, filter and target devices and drive operator scopes (values over 64 characters are ignored by the fleet agent; restart HighwindFleetAgent after a change).

Value NameTypeDescription
DeviceTagSZFreeform label; e.g. Finance
OrgUnitSZe.g. US-East
EnvironmentSZProduction | Staging | Dev

1.7 UI / Feature Flags

Control the interactive WPF application (not the background collector). All DWORD, default 0.

Value NameDescription
DisableExportButtonsBlock every export path; report PDF/HTML, triage report, scan results, ASR event CSV, Advanced Hunting CSV/XML, WDAC XML, firewall migration JSON, investigation CSV. Blocked attempts show an explanatory dialog.
DisableRemoteTargetPin the toolkit to the local machine. The Target box is disabled and any non-local value is rejected, so no remote-capable service can be reached.
ForceReadOnlyModeDisable all write operations (remediation, policy push, ASR exclusions)
ShowPreviewFeaturesReveal features still marked Preview, currently Machine Investigator. Preview features are functional but may change between releases; consider a pilot group first.
SharePointDecisionStoreEnabled 3.7.0Show the SharePoint Decision Store on the App Control pages, so allow/block decisions can be shared through a SharePoint list over Microsoft Graph. 0 hides the SharePoint UI; decisions are still kept in the local ledger either way.
EnableDemoMode 3.7.0Demonstration mode: App Control pages show synthetic data so the product can be shown on a machine with no tenant or policy. Display only; nothing synthetic is saved, exported or uploaded. There is deliberately no in-app switch and no ADMX setting. Never set this on production devices.

Removed in 3.3.2. Seven values were previously accepted but never acted on, so setting them had no effect: CollectFirewallRules, CollectWfpFilters, CollectDeviceControl, CollectNetworkInfo, CollectSecurityScore, DisableAiFeatures and DisableAdvancedNetworking. The installer no longer writes them and the app ignores them if present; delete them so the policy key reflects only settings that are live.

To hide the AI or Networking surfaces, use VisibilityAiAnalysisPage and VisibilityNetworkingPage (section 1.9), which are enforced. DisableExportButtons and DisableRemoteTarget were in the same non-functional state and are now genuinely enforced rather than removed.

1.8 ASR Exclusion Guardrails

Restrict what administrators may create from ASR Rules → Events. All values are optional; a device with none of them set behaves as before (4h / 24h / 7d / 30d plus Permanent).

Value NameTypeDefaultDescription
AsrAllowPermanentExclusionsDWORD10 removes Permanent, forcing every exclusion to expire
AsrAllowTemporaryExclusionsDWORD10 removes all temporary durations
AsrExclusionMaxHoursDWORD0Hard cap in hours; 0 = uncapped. Applied last, so it cannot be widened by the list below
AsrExclusionDurationsHoursSZ4,24,168,720Duration menu in hours, comma-separated. Unparseable entries are ignored and reported
Example: temporary exclusions only, 4 hours maximum
reg add "HKLM\SOFTWARE\Policies\Highwind" /v AsrAllowPermanentExclusions /t REG_DWORD /d 0 /f
reg add "HKLM\SOFTWARE\Policies\Highwind" /v AsrExclusionMaxHours /t REG_DWORD /d 4 /f
Guardrails, not a boundary. These prevent accidental long-lived exclusions and configuration drift. They do not stop a determined local administrator, who can call Add-MpPreference directly; the toolkit's audit ledger is what makes that visible. Setting ForceReadOnlyMode to 1 blocks every exclusion write, both creation and removal.

1.9 Page Visibility

Show or hide individual pages in the interactive application, per elevation level. All DWORD.

ValueMeaning
0Hidden for everyone
1Visible only when the app is running elevated
2Visible only to standard (non-elevated) users
3Visible in both cases
Value NameDefaultPage
VisibilityAsrDashboardPage1ASR Rules overview
VisibilityAsrEventsPage1ASR Rules → Events. 3 gives standard users read-only triage; exclusion actions stay admin-gated regardless
VisibilityMdePoliciesPage1Defender policies
VisibilityFirewallPage1Firewall
VisibilityWfpEventsPage1WFP events
VisibilityWfpFiltersPage1WFP filters
VisibilityFwMigrationPage1Firewall migration
VisibilityDCPoliciesPage1Device Control policies
VisibilityCiToolPage1CiTool integration
VisibilityAppControlAdvancedHuntingPage1App Control → Advanced Hunting
VisibilityMachineInvestigatorPage1Machine Investigator. Also requires ShowPreviewFeatures = 1
VisibilityNetworkingPage1Advanced networking
VisibilityAiAnalysisPage3Highwind AI (formerly AI Analysis). Shown to everyone by default since 3.5.0, because the page opens on the built-in on-device agent. The optional Microsoft Foundry / OpenAI mode stays inactive until an endpoint and credential are configured. Set 0 to remove the page
VisibilityAppControlBlockPage 3.7.01App Control → Deploy → Block Applications
VisibilityAppControlAllowPage 3.7.01App Control → Deploy → Allow Applications
VisibilityAppControlImpactPage 3.7.01App Control → Deploy → Impact Scanner
VisibilityAppControlReadinessPage 3.7.01App Control → Deploy → Enforcement Readiness
VisibilityAppControlRuleRecommendationsPage 3.7.01App Control → Policy Management → Rule Recommendations
VisibilityAppControlLocalPoliciesPage 3.7.01App Control → Local Endpoint → Local Policies
Hiding a page is a UI decision, not an access control. It removes the page from navigation; it does not prevent the underlying Windows functionality being used by other means. Pair it with ForceReadOnlyMode where the intent is to prevent change.

1.10 Logging

Local service log written by the background collector and upload loops.

Value NameTypeDefaultDescription
LogLevelSZInfoNone | Error | Warning | Info | Verbose
LogFilePathSZ(CacheFolder)\service.logCustom log path
MaxLogSizeMbDWORD10Rotate at this size (1–500 MB)

1.11 Highwind AI

What Highwind AI may reach and how far it may go. By default it answers with a local engine using only data on the device; these values decide whether it may also look things up online, send evidence to a Microsoft Foundry model, or watch for changes unprompted. ADMX folder: Highwind AI.

Value NameTypeDefaultDescription
AllowAiOnlineLookupDWORD1Allow Microsoft Learn lookup (and, during Deep Thinking, the sources allowed by AiResearchTierCeiling). Only search terms are sent; never collected state, host names or configuration. 0 keeps Highwind AI entirely offline.
AllowAiModelReasoningDWORD1Allow gathered evidence (host names, file paths, command lines, configuration gaps) to be sent to your Microsoft Foundry model. The operator must still opt in and an endpoint must be configured, so the effective default is off. 0 forces the local engine regardless of operator choice.
AllowAiSecurityWatch 3.7.0DWORD1Allow the security watch: every two hours Highwind AI compares the collector’s snapshots and raises a weakened protection as a suggested question. Reads local snapshots only; nothing is sent. 0 stops the watch starting, overriding the operator’s own setting. Applies at next start.
AiAgentMaxIterationsDWORD4Plan/observe rounds per question (1–8, clamped). Deep Thinking adds up to 3, capped at 8.
AiResearchTierCeilingDWORD1Sources Deep Thinking may consult. 1 Microsoft docs, Microsoft GitHub and practitioner Q&A sites; 2 Microsoft docs and GitHub; 3 Microsoft docs only. Higher is stricter. No effect when AllowAiOnlineLookup is 0.

1.12 Example: GPO / Intune Deployment

PowerShell: Set registry for enterprise collection + upload
$regPath = "HKLM:\SOFTWARE\Policies\Highwind"
New-Item -Path $regPath -Force | Out-Null

Set-ItemProperty $regPath -Name EnableBackgroundCollector -Value 1 -Type DWord
Set-ItemProperty $regPath -Name EnableUpload             -Value 1 -Type DWord
Set-ItemProperty $regPath -Name FunctionAppUrl      -Value "https://func-highwind.azurewebsites.net/api/HealthReportIngestion"
Set-ItemProperty $regPath -Name FunctionAppAudience -Value "api://highwind-func"
Set-ItemProperty $regPath -Name AzureEnvironment -Value "Public"
Set-ItemProperty $regPath -Name DeviceTag -Value "Finance"
Set-ItemProperty $regPath -Name OrgUnit   -Value "US-East"
Set-ItemProperty $regPath -Name CacheRetentionDays -Value 30 -Type DWord

1.13 New Table Columns (v3.2+)

Recent client + Function App updates added the following columns to each row upserted into Azure Table Storage. Existing Power BI reports do not need to change; new columns simply become available for slicing.

ColumnSourceNotes
DeviceTag, OrgUnit, EnvironmentRegistry (section 1.6)Promoted from JSON body to top-level columns
IpAddressFirst non-loopback IPv4NetworkInterface enumeration
LastBootTimeUtcEnvironment.TickCount64ISO 8601 UTC
LastQuickScanUtc, LastFullScanUtcMSFT_MpComputerStatus age fields, registry fallbackISO 8601 UTC
AntivirusEngineVersionAMEngineVersion, filesystem fallbackMpEngine.dll version
PlatformVersionAMProductVersion, registry & folder-name fallbacksDefender platform version
SignatureVersionCIM + AVSignatureVersion registryDefinition version
ServiceVersionAMServiceVersionDefender service version
MdeOrgIdRegistry Windows Advanced Threat Protection\Status\OrgIdEmpty if not onboarded
AppControlPolicyCountC:\Windows\System32\CodeIntegrity\CIPolicies\Active\*.cipFile count, not enforcement
AppControlStatusKMCI + policy countEnforced | Audit | Configured (N policies, not enforced) | NotConfigured
PowerShellExecutionPolicyMachine policy → per-shell → defaultRestricted / RemoteSigned / AllSigned / Bypass / etc.
SmartScreenExplorerModeRegistry Explorer\SmartScreenEnabledRaw string (RequireAdmin, Warn, Off)
Azure Table Storage is schemaless per row. Existing rows keep their original columns; only newly upserted rows carry the new fields.

1.14 Fields fixed in v3.3.3

These columns existed in the schema but were never populated by the collector: they were uploaded at their default value on every device. A dashboard reading them saw false or 0 and could not tell that apart from a real measurement.

ColumnWasNow
ExploitProtectionDepEnabled, ExploitProtectionAslrEnabled, ExploitProtectionCfgEnabled Always false: never read Decoded from MitigationOptions under Session Manager\Kernel. A read failure now sets ExploitProtectionStatus to Unknown rather than leaving false to look like a measurement.
LocalAdminCount Always 0, which is impossible; every install has the built-in Administrator Counted via NetLocalGroupGetMembers resolved by well-known SID S-1-5-32-544, so it works on non-English installs. LocalAdminStatus now reflects the count, not just LAPS.
AppControlEnforcementMode Not written at all Enforced | Audit | Deployed | NotConfigured. Deployed means .cip policies are present but Code Integrity is not running them.
LastQuickScanUtc, LastFullScanUtc Blank when the scan ran today The age test was > 0; a scan that ran today has age 0, so the freshest devices reported as never scanned. Now >= 0.
Existing rows are not backfilled. Devices must upload at least once on 3.3.3 before these columns mean anything, and rows written by older agents keep their misleading defaults. Slice on ServiceVersion to see how far the rollout has reached, and consider deleting pre-3.3.3 rows if the false zeros would skew a report.

1.15 Fleet Agent Preview 3.7.0

Read by the Highwind Fleet Agent Windows service, which connects this device to a Highwind Management API you host. The service is only registered when the MSI is installed with INSTALLFLEETAGENT=1 (see section 2). Every value is prefixed Fleet and lives in the same key. The MSI does not seed these values, so they appear in regedit only once you set them.

Safe by default. Every switch defaults to off. While FleetDistributedAgentsEnabled is 0 the agent does nothing and none of the other values are validated. Once it is 1, an invalid value (missing URL, http:// URL, value out of range, unknown authentication mode) stops the agent at startup with the reason in its log, rather than the agent guessing.

Feature switches (DWORD, 1 = on, also accepts true/false as REG_SZ)

Value NameDefaultDescription
FleetDistributedAgentsEnabled0Master switch. Nothing below has any effect until this is 1
FleetAgentRegistrationEnabled0Register the device with the management service (first step; nothing else works without it)
FleetAgentHeartbeatsEnabled0Send liveness/health heartbeats
FleetCapabilityDiscoveryEnabled0Advertise the read-only operations this device can run
FleetBrokeredMessagingEnabled0Poll for requests and return results (read-only operation catalogue only)
FleetCustomChecksEnabled0Answer administrator-defined custom checks (registry under HKLM\SOFTWARE and HKLM\SYSTEM\CurrentControlSet, files under Program Files/ProgramData/Windows, services). Read-only; credential-like registry values are never returned. Restart HighwindFleetAgent after a change
FleetAppControlReportingEnabled0Report installed applications (Uninstall entries for the machine and each loaded user hive, plus provisioned packages: name, publisher, version; install locations and uninstall commands are never read) and local App Control audit/block events (Code Integrity and AppLocker, user-profile folders redacted) for the optional App Control management module. Answers only when the console also turns on the matching capability. Restart HighwindFleetAgent after a change
FleetAppControlFileScanEnabled0Answer an administrator’s request to list the executable files of one installed application (name, version, signer, Authenticode SHA-256, signer certificate TBS hashes) so App Control rules can be built for it. The device finds the folder itself from its own Uninstall entry or package (the request never names a path) and refuses drive roots, the Windows and system folders, Program Files, ProgramData and profile roots; only executable, installer and script files are hashed, links are not followed, file contents never leave the device and profile names are redacted. ADMX Allow App Control application file scans. Restart HighwindFleetAgent after a change
FleetPersistenceAuditEnabled0Allows the management service to ask this device for a read-only inventory of things that start with Windows or a sign-in: local administrators, scheduled tasks outside the Microsoft task tree, Run and RunOnce values and Startup folder files. It reports names, locations, commands, SHA-256 hashes and signature state, never file contents or credentials. Restart the Highwind service after changing this setting.
FleetSoftwareTrustEnabled0Allows the management service to ask this device which programs are running and who signed them: file name, SHA-256, version, product, whether the signature is embedded or from a Windows catalog, and the signing chain to its root certificate. It reads running programs only, builds the chain offline without checking revocation, and never reads file contents. Restart the Highwind service after changing this setting.
FleetKernelAssuranceEnabled0Allows the management service to ask this device for its kernel protections and loaded drivers: Secure Boot, TPM, virtualization-based security, memory integrity (HVCI), Credential Guard, kernel code integrity, the vulnerable driver blocklist setting, and for each running driver its file name, SHA-256, version, publisher, signature and file creation time. The service turns this into an explained Kernel Trust score. It reads metadata only, never file contents, and builds signature chains offline. Restart the Highwind service after changing this setting.
FleetAiSecurityEnabled0Allows the management service to ask this device which AI products and MCP servers it has and what they can reach: AI desktop apps, coding agents, local model runtimes and editor extensions, the MCP servers named in their configuration files (command, arguments with secrets removed, program hash and signer, destination, variable names without values), local model files, ports AI runtimes listen on, and which credential stores (Azure, GitHub, SSH, AWS and similar) exist in each user profile. It reads configuration files and file names only. It never starts an MCP server, never sends a secret value or file contents, and does not read credential stores, only whether they exist. Restart the Highwind service after changing this setting.
FleetHealthSignalsEnabled0Allows the management service to ask this device how often ordinary problems happened on it in the last 72 hours, in whole-hour counts: application crashes and hangs, Windows Error Reporting entries, service failures, unexpected restarts, driver load failures, App Control (Code Integrity) block and audit events, Microsoft Defender attack surface reduction block and audit events, Defender protection turned off, and failed sign-ins. It counts events only. It never reads event text, user names, file paths, program names or machine names. The management service uses the counts to show what normal looks like before a change, and asks more often, for a limited time, for devices that an administrator chose to observe in a What If run. Failed sign-ins are counted from the Security log, which needs the SYSTEM account that the Highwind service runs as. Restart the Highwind service after changing this setting.
FleetFirewallReportingEnabled0Allows the management service to ask this device about its Windows Firewall: the state of the Domain, Private and Public profiles, the effective rules (what each rule allows or blocks, where it applies, which program, where it came from), and a summary of allowed and blocked connections. Connection summaries are grouped by hour, program, port and remote address and carry no packet contents. They are read from the Windows Security log, so the audit policies Filtering Platform Connection and Filtering Platform Packet Drop must be turned on by your own Group Policy or Intune policy; Highwind never changes audit policy and reports Not enabled or Partial when it is off. Allowed-connection auditing can be high-volume, so Highwind reads a bounded window, caps what it sends and reports how many events it dropped. Needs the SYSTEM account that the Highwind service runs as. Restart the Highwind service after changing this setting.
FleetLabChangeEnabled0Lets this machine be a lab machine. The management service may ask it to change one Microsoft Defender attack surface reduction rule (Audit, Warn or Block) for a limited time. The agent refuses unless this machine is tagged Lab or Test, the rule is on its built-in list and the action is one of the three. It saves the old setting first (in %ProgramData%\Highwind\LabChange, readable only by SYSTEM and Administrators), reads the new one back, and puts the old one back when the lab check ends, when the time is up (checked every 5 minutes) or after a restart. A rule managed by another policy overrides the change and is reported as failed. This is the only setting Highwind ever changes. Never turn this on for a production or critical machine. Restart the Highwind service after changing this setting.
FleetPolicyProvenanceEnabled0Allows the management service to ask this device where its policy settings come from: whether it is enrolled in MDM (Intune), has applied Group Policy objects, or has the Configuration Manager client, and which of the Group Policy and MDM policy stores hold settings for Microsoft Defender, Windows Firewall and Device Guard. It reads registry key names, the MDM enrollment provider name and counts only, never a policy value, user name, server address or secret. Highwind uses this to say which management authority could have changed a security setting. Restart the Highwind service after changing this setting.
FleetPolicySettingsEnabled0Allows the management service to ask this device for every Group Policy, Intune (MDM) and Defender setting it holds, with the value and what set it (the Intune enrollment that won, or the Group Policy object). Reads HKLM\SOFTWARE\Policies, HKLM\SOFTWARE\Microsoft\PolicyManager\current\device, a short list of local Defender and Device Guard keys, the enrollment list (no user name) and Windows’ Group Policy results. Browser policy, Highwind’s own policy key and secret-looking values are skipped or hidden. Requires FleetBrokeredMessagingEnabled. ADMX: Allow policy settings report
FleetDistributedQueriesEnabled0Reserved. Accepted but has no effect yet; distributed queries are served through brokered messaging
FleetAiOrchestrationEnabled0Reserved. Not implemented
FleetDirectAgentCommunicationEnabled0Reserved. Not implemented; setting it to 1 stops the agent at startup. Leave unset

Connection and identity

Value NameTypeDefaultDescription
FleetManagementServiceUriSZRequired. Base URL of the Management API, including https://, e.g. https://highwind-fleet-api-01.azurewebsites.net (.azurewebsites.us in Azure Government). A bare host name is rejected
FleetManagementAudienceSZApplication ID URI of the API app registration, e.g. api://857e6dc9-f213-4455-be4a-d67632260c10, without /.default. Required in EntraId mode, unused in ClientCertificate mode
FleetExpectedTenantIdSZOptional tenant GUID. Checked against the tenant the device is joined to; a mismatch stops the agent
FleetAuthenticationModeSZEntraIdEntraId (app-only Entra token; the service needs an identity holding Highwind.Agent, see Turn on endpoints) or ClientCertificate (certificate from your CA, mutual TLS) or DeviceCertificate (zero-touch for Entra joined and hybrid joined devices: the service issues each device its own certificate; see Turn on endpoints). Any other value stops the agent
FleetRequireHardwareKeyDWORD0DeviceCertificate mode only. 1 refuses to fall back to a software key when the device has no usable TPM
FleetPortalConfigurationEnabledDWORD10 makes the agent ignore the reports the portal chooses (Admin › Client configuration) and use local policy only. Not set: where the portal names a report, its value wins over the local value
FleetReportLastLoggedOnUserDWORD10 stops the agent naming the last signed-in account (the portal’s Last user column and search by user); the service then deletes the account it held. The account name is personal data
FleetClientCertificateThumbprintSZSHA-256 thumbprint (64 hex characters; spaces/colons allowed). Set exactly one of thumbprint or subject
FleetClientCertificateSubjectSZCertificate subject. Picks the matching certificate with a private key that expires last, so it survives renewal
FleetClientCertificateStoreNameSZMyStore to search
FleetUseMachineCertificateStoreDWORD1Search LocalMachine rather than CurrentUser. Leave at 1; the service runs as LocalSystem
FleetIdentityFilePathSZTesting override for the identity file. Leave unset in production

Timing and limits (DWORD)

Value NameDefaultAllowed range
FleetHeartbeatIntervalSeconds30030 – 86400
FleetRequestPollIntervalSeconds6010 – 3600
FleetRequestTimeoutSeconds305 – 300
FleetMaxPayloadBytes2621444096 – 8388608
FleetMaxMessagesPerPoll21 – 25
FleetMaxResultCharacters65536256 – 1048576
Example: pilot device, Entra ID authentication
$p = "HKLM:\SOFTWARE\Policies\Highwind"
New-Item -Path $p -Force | Out-Null
Set-ItemProperty $p -Name FleetManagementServiceUri       -Value "https://highwind-api.contoso.com/"
Set-ItemProperty $p -Name FleetManagementAudience         -Value "api://highwind-fleet-api"
Set-ItemProperty $p -Name FleetDistributedAgentsEnabled   -Value 1 -Type DWord
Set-ItemProperty $p -Name FleetAgentRegistrationEnabled   -Value 1 -Type DWord
Set-ItemProperty $p -Name FleetAgentHeartbeatsEnabled     -Value 1 -Type DWord
Set-ItemProperty $p -Name FleetCapabilityDiscoveryEnabled -Value 1 -Type DWord
Set-ItemProperty $p -Name FleetBrokeredMessagingEnabled   -Value 1 -Type DWord
Restart-Service HighwindFleetAgent
Example: AD-only device, client certificate
Set-ItemProperty $p -Name FleetAuthenticationMode       -Value "ClientCertificate"
Set-ItemProperty $p -Name FleetClientCertificateSubject -Value "CN=$env:COMPUTERNAME.contoso.local"
Remove-ItemProperty $p -Name FleetManagementAudience -ErrorAction SilentlyContinue

Agent state lives in %ProgramData%\Highwind\fleet\: agent-identity.json (device identity), enrollment.secret (one-time enrollment secret, deleted once spent) and audit.jsonl (every request the agent executed). See Fleet central management for the server side.

2. MSI Deployment

The Highwind ships as a WiX v5 MSI installer, suitable for SCCM, Intune, or GPO.

What the MSI Does

  • Installs to C:\Program Files\Highwind\ (self-contained .NET 10 from 3.6.0; .NET 8 before)
  • Creates C:\ProgramData\Highwind\cache\
  • Writes HKLM\SOFTWARE\Highwind with Version and InstallPath
  • Creates scheduled task Highwind Collect (SYSTEM, every 8h)
  • Creates scheduled task Highwind Upload (interactive user, every 8h)
  • Seeds every policy value under HKLM\SOFTWARE\Policies\Highwind at its built-in default, so each setting is visible in regedit and can be edited rather than created. Existing values are never overwritten, so GPO/Intune settings and manual edits survive upgrades. Because each seeded value equals the code default, a freshly installed device behaves identically to one with no policy key; deleting a value simply restores its default.
  • Adds desktop and Start Menu shortcuts
  • 3.7.0 With INSTALLFLEETAGENT=1 only: registers the Highwind Fleet Agent service (HighwindFleetAgent, LocalSystem, automatic start, restart on failure) and writes HKLM\SOFTWARE\Highwind\FleetAgentService = Installed. Upgrades keep the service registered even if the property is not passed again. Without the property nothing is registered. The service is inert until the Fleet policy values enable it.

Silent Install

Command Line
msiexec /i Highwind-3.5.0.msi /qn
msiexec /i Highwind-3.5.0.msi /qn /l*v install.log

# 3.7.0+: also register the Fleet Agent service (opt-in, preview)
msiexec /i Highwind-3.7.0.msi /qn INSTALLFLEETAGENT=1

# Intune detection: HKLM\SOFTWARE\Highwind\Version exists
Upgrading from 3.4.0 or earlier? Those releases installed as MDE Toolkit and used HKLM\SOFTWARE\MDE-Toolkit\Version, C:\Program Files\MDE-Toolkit\ and the MDE Toolkit Collect / MDE Toolkit Upload tasks. The major upgrade removes all of that and migrates your policy values from HKLM\SOFTWARE\Policies\MDE-Toolkit automatically; but any detection rule, requirement script or allow-list still keyed to the old names will stop matching. Update those before you deploy, or Intune will report a healthy install as failed.

3. Scheduled Tasks

The MSI creates two tasks. Both use -StartWhenAvailable so missed runs catch up when the device comes back online. A third task is registered at runtime; see 3.4.

Offline resilience. If the machine is asleep or off at the scheduled time, Windows runs the task as soon as it wakes. One catch-up run fires; correct for telemetry.

3.1 Collect (SYSTEM)

PowerShell equivalent
$action    = New-ScheduledTaskAction `
  -Execute '"C:\Program Files\Highwind\Highwind.exe"' `
  -Argument '--collect --no-upload'
$trigger   = New-ScheduledTaskTrigger -Once -At (Get-Date) `
  -RepetitionInterval (New-TimeSpan -Hours 8)
$principal = New-ScheduledTaskPrincipal `
  -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest
$settings  = New-ScheduledTaskSettingsSet `
  -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable
Register-ScheduledTask -TaskName 'Highwind Collect' `
  -Action $action -Trigger $trigger -Principal $principal `
  -Settings $settings -Force

3.2 Upload (Interactive User)

PowerShell equivalent
$action    = New-ScheduledTaskAction `
  -Execute '"C:\Program Files\Highwind\Highwind.exe"' `
  -Argument '--upload'
$trigger   = New-ScheduledTaskTrigger -Once -At (Get-Date) `
  -RepetitionInterval (New-TimeSpan -Hours 8)
$principal = New-ScheduledTaskPrincipal `
  -GroupId 'BUILTIN\Users' -RunLevel Highest
$settings  = New-ScheduledTaskSettingsSet `
  -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable
Register-ScheduledTask -TaskName 'Highwind Upload' `
  -Action $action -Trigger $trigger -Principal $principal `
  -Settings $settings -Force

3.3 Settings Summary

SettingCollectUpload
Run asSYSTEMBUILTIN\Users (interactive)
IntervalEvery 8 hoursEvery 8 hours
StartWhenAvailable
AllowStartIfOnBatteries
WakeToRun
No GUI. Both modes run headless. The WPF window is never created.
User must be logged on. Upload uses interactive logon; deferred via StartWhenAvailable if no session is active.

3.4 ASR Exclusion Sweep (registered at runtime)

\Highwind\ASR Exclusion Sweep is not created by the MSI. It is registered the first time an administrator creates a temporary ASR exclusion, and runs as SYSTEM every 15 minutes. Defender has no native expiry for exclusions, so this task is what reverts them when the toolkit itself is closed.

SettingValue
Task path\Highwind\ASR Exclusion Sweep
Run asSYSTEM (highest privileges)
IntervalEvery 15 minutes
Script%ProgramData%\Highwind\asr-exclusion-sweep.ps1
Ledger%ProgramData%\Highwind\asr-exclusions.json
CreatedOn first temporary exclusion (not at install)
RemovedAutomatically on uninstall
Uninstall behaviour. Removing the product reverts still-active temporary exclusions first, then deletes the task and its script. Permanent exclusions are deliberately left in place, an administrator asked for those, and the ledger JSON is preserved as an audit record. Review the Exclusions tab before uninstalling if you want a clean slate.
Directory is hardened. %ProgramData%\Highwind is ACL'd to SYSTEM and Administrators with standard users read-only, because the sweep script executes as SYSTEM. If the directory cannot be secured, the toolkit refuses to register the task rather than create an escalation path.

4. Verification

4.1 Test Collection

PowerShell (Admin)
& "C:\Program Files\Highwind\Highwind.exe" --collect --no-upload
Get-Content "C:\ProgramData\Highwind\cache\latest.json" | ConvertFrom-Json | Select hostname, healthScore, overallStatus

4.2 Test Upload

PowerShell (logged-on user)
& "C:\Program Files\Highwind\Highwind.exe" --upload
Get-Content "C:\ProgramData\Highwind\cache\service.log" -Tail 10
If the upload fails with “Silent sign-in unavailable”, the log names the account Windows is signed in as and the tenant a token was requested for. When the device is not Entra joined to the tenant that owns the Function App, no registry setting can fix it; there is no primary refresh token to redeem. Sign in once as the user the upload task runs as:
PowerShell (logged-on user)
& "C:\Program Files\Highwind\Highwind.exe" --auth-login
This prompts once, acquires consent for every configured upload target, and caches the account in the user's profile so scheduled uploads refresh silently. It is the only mode that will ever display a sign-in window, and it is per-user: another user signing in to the same machine needs to run it too. Devices joined to the correct tenant do not need it at all.

4.3 Verify Tasks

PowerShell
Get-ScheduledTask -TaskName "Highwind*" | Format-Table TaskName, State, @{N='RunAs';E={$_.Principal.GroupId ?? $_.Principal.UserId}}

4.4 Verify Table Row

Azure CLI
az storage entity query \
  --table-name HealthReports \
  --account-name sthighwind \
  --filter "Hostname eq 'YOUR-PC-NAME'"

4.5 Expected Output

CheckExpected
Exit code0
latest.jsonExists with hostname, healthScore
Service logFunction App upload succeeded (200)
Table rowHealthScore > 0
RegistryHKLM\SOFTWARE\Highwind\Version = 3.7.0