AppSense Environment Manager PowerShell: Advanced Script Examples
AppSense Environment Manager can apply user settings with impressive precision, but complex desktop requirements often call for PowerShell. Scripts extend Environment Manager actions with conditional logic, registry inspection, file management, event logging, and controlled remediation. Used carefully, they turn a static profile configuration into a responsive user environment.
This is particularly useful in Australian organisations where users may move between offices in Sydney, Melbourne, Brisbane, Perth, and regional locations. A single policy may need to account for slower branch links, shared workstations, hybrid staff, different printer fleets, and applications that behave differently during AEST or AEDT.
The most reliable approach is to keep Environment Manager responsible for policy orchestration while PowerShell performs a focused task. Each script should be predictable, repeatable, observable, and safe to run more than once. The examples below are designed for that model and can be adapted to AppSense DesktopNow or legacy Environment Manager deployments.
Designing Reliable EM PowerShell Actions
Environment Manager can launch PowerShell through an Execute File action, a Custom Action, or a policy node triggered by logon, process start, session unlock, or application launch. Use the 64-bit PowerShell host where the target application and registry view require it, and specify the complete executable path rather than relying on the user’s PATH variable.
A practical command line is:
%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe
-NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass
-File "\\domain.local\SYSVOL\Scripts\Set-UserDefaults.ps1"
-NoProfile prevents a user’s personal PowerShell profile from changing the result. -NonInteractive ensures a hidden prompt cannot stall logon. In a controlled enterprise environment, signing scripts and using an approved execution policy is preferable to broad bypass behaviour. If a script is stored on a network share, consider copying a versioned file to the local machine first, especially for offices in Perth or remote sites connected over higher-latency links.
The script should return a meaningful exit code and write to a location that administrators can collect. Avoid writing sensitive information to plain-text logs. A small helper function creates consistent logging without exposing passwords, tokens, or full user profile data:
$LogRoot = Join-Path $env:ProgramData 'Company\EnvironmentManager\Logs'
New-Item -Path $LogRoot -ItemType Directory -Force | Out-Null
$LogFile = Join-Path $LogRoot 'UserDefaults.log'
function Write-EmLog {
param([string]$Message)
$stamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
Add-Content -Path $LogFile -Value "$stamp [$env:USERNAME] $Message"
}
Detecting User And Session Context
Environment Manager conditions handle many common checks, yet PowerShell is helpful when several signals must be evaluated together. The following example identifies whether a session is running on a laptop, whether the user is connected through Remote Desktop, and whether the device appears to be outside the corporate network.
$computerSystem = Get-CimInstance Win32_ComputerSystem
$isLaptop = $computerSystem.PCSystemType -eq 2
$isRemote = $env:SESSIONNAME -like 'RDP-*'
$hasCorporateDns = $false
try {
$dns = Resolve-DnsName -Name 'intranet.company.local' `
-ErrorAction Stop
$hasCorporateDns = $dns.Count -gt 0
} catch {
$hasCorporateDns = $false
}
if ($isRemote) {
[Environment]::SetEnvironmentVariable(
'EM_SESSION_PROFILE', 'Remote', 'User')
} elseif ($isLaptop -and -not $hasCorporateDns) {
[Environment]::SetEnvironmentVariable(
'EM_SESSION_PROFILE', 'Offsite', 'User')
} else {
[Environment]::SetEnvironmentVariable(
'EM_SESSION_PROFILE', 'Office', 'User')
}
The environment variable can then be used by an Environment Manager condition to select a printer, map a drive, apply an application setting, or suppress a bandwidth-heavy action. This is generally cleaner than placing every decision inside one large script. Policy designers can see the outcome in the console, while the script remains responsible for collecting the raw signals.
For Australian users, session classification can accommodate practical differences between a corporate office and a home connection. A Melbourne user working during winter may have different connectivity from a Darwin user during the wet season, while a travelling consultant may unlock a cached profile at an airport lounge. The policy should make a conservative choice when network detection fails rather than repeatedly retrying a remote resource.
Managing Printers Without Profile Drift
Printer configuration is a frequent source of logon delays and unwanted profile changes. A script should remove only printers managed by the policy, install the appropriate connection, and avoid repeatedly altering the user’s default printer. A naming convention or a dedicated registry marker makes ownership clear.
The following example manages a user printer based on a site variable supplied by Environment Manager. It uses the PrintManagement module where available and records failures without stopping the entire logon process:
$site = [Environment]::GetEnvironmentVariable(
'EM_SITE', 'User')
$printerMap = @{
'SYD' = '\\print01\Sydney-Floor-2'
'MEL' = '\\print02\Melbourne-Floor-1'
'BNE' = '\\print03\Brisbane-Floor-3'
}
$target = $printerMap[$site]
if ($target) {
try {
$existing = Get-Printer -ErrorAction SilentlyContinue |
Where-Object { $_.Name -like 'EM-*' }
foreach ($printer in $existing) {
Remove-Printer -Name $printer.Name -ErrorAction SilentlyContinue
}
Add-Printer -ConnectionName $target -ErrorAction Stop
Set-Printer -Name $target -Comment 'Managed by Environment Manager'
} catch {
Write-EmLog "Printer action failed: $($_.Exception.Message)"
exit 20
}
}
Driver redirection deserves separate testing because print servers, packaged drivers, and user permissions can interact in unexpected ways. Before deploying a change, review this print redirection guide alongside vendor documentation and test on the Windows builds used by the organisation.
Do not silently replace every printer at every logon. A better design triggers the action when the site variable changes, when a user starts a managed session, or when a printer connection is absent. Shared computers in a Brisbane training room may need a different approach from a dedicated workstation in Adelaide, where preserving the last-used default can be more useful.
Building Idempotent Remediation
An idempotent script produces the same desired state whether it runs once or ten times. This matters because Environment Manager actions can be triggered by logon, reconnect, application start, or policy refresh. Scripts that append duplicate values, recreate folders unnecessarily, or overwrite user choices will create profile drift.
The example below sets a registry preference only when the current value differs. It also creates a folder with a controlled ACL and avoids changing ownership of an existing personal directory:
$regPath = 'HKCU:\Software\Company\Explorer'
$desired = 'Compact'
if (-not (Test-Path $regPath)) {
New-Item -Path $regPath -Force | Out-Null
}
$current = (Get-ItemProperty -Path $regPath `
-Name 'ViewMode' -ErrorAction SilentlyContinue).ViewMode
if ($current -ne $desired) {
New-ItemProperty -Path $regPath -Name 'ViewMode' `
-Value $desired -PropertyType String -Force | Out-Null
Write-EmLog "ViewMode changed to $desired"
}
$cachePath = Join-Path $env:LOCALAPPDATA 'Company\Cache'
if (-not (Test-Path $cachePath)) {
New-Item -Path $cachePath -ItemType Directory -Force | Out-Null
}
For a more advanced remediation, compare application versions before changing a setting. Registry paths differ between 32-bit and 64-bit applications, and some programs store configuration in JSON, XML, or SQLite files. Back up a configuration file to a per-user recovery directory before editing it, but apply a retention limit so a long-lived profile does not accumulate hundreds of copies.
When processing JSON, use ConvertFrom-Json and ConvertTo-Json rather than fragile text replacement. Validate that the expected property exists, write to a temporary file, and replace the original only after the new content has been serialised successfully. This prevents a terminated PowerShell process from leaving an application with a zero-byte configuration file.
Logging, Security, And Australian Operations
PowerShell actions should use the minimum permissions they need. User-context scripts should generally modify HKCU, the user profile, or per-user application data. Machine-level changes belong in a trusted deployment mechanism or a clearly controlled Environment Manager action running with appropriate rights. Do not embed service credentials in scripts, command lines, or AppSense configuration exports.
For organisations subject to Australian privacy obligations, logs should be proportionate. A useful event record might contain the action name, result, timestamp, device name, and a short error code. It rarely needs the contents of a user’s documents or a complete list of personal paths. Retain logs according to the organisation’s policy and protect the directory with suitable access controls.
Time handling is another small operational detail. Use ISO-style timestamps and store them in local system time only when administrators specifically need Australian local time. Central teams supporting Sydney and Perth should avoid ambiguous dates such as 03/04/2025; 2025-04-03T16:20:00+10:00 is much easier to interpret. If a script controls scheduled behaviour, account for daylight saving in NSW, Victoria, Tasmania, and the ACT rather than assuming all Australian locations change clocks together.
Test network and URL-dependent actions with approved endpoints. A lightweight policy test may launch a browser shortcut or validate that a destination is reachable, but it should never be used to bypass web filtering. For harmless content-handling tests, an administrator might use a small public resource such as 4sucres reference or a hobby-related site such as tabletop gaming resources, provided the organisation’s security controls permit those destinations.
Recommendations For Production Deployments
PowerShell examples become dependable Environment Manager components when they are packaged with clear ownership, version control, and a rollback path. Keep scripts short enough to review, but place reusable functions in a signed module when several policies need the same behaviour. Record the script version in the log so an incident can be matched to the exact deployed file.
The AppSense Exchange communities are useful for comparing implementation patterns, troubleshooting product-specific behaviour, and locating resources organised by product and version. Validate community examples against the Windows release, Environment Manager version, and security baseline used in your own estate before production use.
- Use explicit paths, parameters, timeouts, and exit codes in every PowerShell action.
- Separate detection, decision-making, remediation, and reporting where practical.
- Make registry, file, printer, and shortcut operations safe to repeat.
- Test on physical devices, virtual desktops, Remote Desktop sessions, and shared PCs.
- Pilot changes across Australian offices before applying them to every user.
Reliable automation is built through small changes and observable results. Begin with a single policy node, capture successful and failed outcomes, then expand the scope after testing logon duration, profile behaviour, printer selection, and application compatibility. Store the approved scripts with their change history and make rollback as simple as restoring the previous version.
Use these patterns as a foundation for an AppSense Environment Manager and PowerShell library tailored to your estate. Publish tested configurations, scripts, and troubleshooting notes to the appropriate AppSense Exchange resource area so other administrators can reuse proven solutions and contribute refinements.