How to run as SYSTEM and be able to display a UI to the logged in user?

Although I’m a long time PSADT user for deploying applications in a ConfigMgr environment, I need help understanding what is required in order allow PSADT to be display prompt to users.

To accomplish a few org-specific tasks, we’ve created a PowerShell script that is executed via a Scheduled Task running as SYSTEM. The custom script we’ve created dot sources the AppDeployToolkitMain.ps1 module exactly the same way the Deploy-Application.ps1 calls since the brilliant team behind PSADT has nailed all the key functionality we’d like to use and then some.

Everything works in general except for one thing: None of the prompts (balloon tips, installation welcome, installation prompt, dialog box) appear when called. In reviewing the log it shows the following:

[PSAppDeployToolkit] :: Session 0 detected, process not running in user interactive mode; deployment mode set to [NonInteractive].
[PSAppDeployToolkit] :: Installation is running in [NonInteractive] mode.

We are setting $DeployMode to Interactive and the Scheduled Task is running the following to call the script but still no dice:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\Path\To\Custom\Script.ps1

I can confirm that adding [Environment]::UserInteractive in the script returns false.
I then ran the following which also returned false:

psexec.exe -s "C:\tmpStorage\PSTools\PsExec.exe" -s powershell.exe -Command "& {start-transcript C:\tmpStorage\Test.log -append; [Environment]::UserInteractive; stop-transcript}"

Doing the same with the -i parameter returns true.

So I’m trying to wrap my head around this: When I deploy a PSADT wrapped app in ConfigMgr, it’s running as SYSTEM yet is able to display prompts to the user. Is ConfigMgr using ServiceUI? If not, then how is this possible?

With SCCM being close source, I can only guess that they’ve used some of the ServiceUI code in SCCM.

I don’t dwell on the “why it works”. I’m just happy that is does work.

I would suggest you try including ServiceUI.exe in your command line to see if this resolves the issue

1 Like

Yeah, I’m thinking that or they’ve got another method that does this. Hah I hear you :slight_smile:

I think Adrian_Scott is correct on this one.

1 Like

This is an issue I ran into when testing for this:

Might be worth a look?

We have what we call an invoke script which is called by SCCM, that identifies what kind of session is logged in and then calls “Deploy-Application.exe Install / Uninstall” we have 3 different ways depending on what it finds. We have even gone a little fancy and integrated it back into “Deploy-Application.ps1” so we have less scripts to keep up-to-date!

2 Likes

@Adi-R - That ‘Invoke script’ sounds quite good for more than one of our (Intune) deployments - It could also allow us to reduce a couple of our deployments that are currently targetted specifically during the Enrollment Status Page (ESP or OOBE) phase or as a different deployment for users to install interactively.
Could you be willing to share your script? Or at least with any of your proprietry content redacted / removed?

:pray:

Thanks in advance,
Adrian

1 Like

It is possible using ExecuteProcessAsUser too for displaying Window message. But for exe who need user interaction, I would like someone adding a good function in PSADTK. It would be easier to figure how making it work. ServiceUI might be a little hard to use.

I’ve created a new thread with the information:

2 Likes

Excellent @Adi-R,
I will have a play with this and see how it might simplify our Cisco Secure Client deployments
:crossed_fingers: I can reduce this to one deployment that works on both the AutoPilot Enrollment Status Page and as an interactive install for our users on existing machines.

Thanks again

1 Like

Funny enough I just rolled out our Cisco Secure Client upgrade this morning to the test group, 0 errors so far!

1 Like
  • For our interactive install I have written a custom PSADT install to give clear pre-warnings that a restart is required at the end of the install (with 3 deferrals), on continue (or deferrals run out) it then checks the VPN is not connected before commencing the install, It installs the 3 Secure Client modules we need (Core / VPN, NAM & DaRT), copies in the latest NAM and VPN config files, then gives the users 15mins to restart at the end.
  • For the Silent Install I have a simpler (non PSADT version) that installs to devices with a forced restart on completion - We only target this at AutoPilot ‘new build’ machines via the ESP - This also has a requirement rule to ensure the C:\Program Files (x86)\Cisco folder does not exist to guarantee it is not deployed to machines with an exisiting (AnyConnect or Secure Client) install.

With your script additions I hope to get rid of the need for separate silent deployment

3 Likes

Ah, that’s slightly more complicated than ours as we actually only use the Umbrella functionality of Cisco Secure Client. We use AoVPN for the VPN connection but I’ll just say that’s the most complex bit of integration with AD/GPO/SCCM/Task Scheduler/PowerShell that I’ve ever done, works well though!

2 Likes

Thanks for the reply, everyone, @Adrian_Scott @That-Annoying-Guy @francois-3 @Adi-R
I really do appreciate it!

I am using ServiceUI to call my custom script which itself dot sources the PSADT toolkit.

C:\Path\to\ServiceUI.exe -process:explorer.exe powershell.exe -File C:\Path\To\Custom\Script.ps1

While doing this does indeed display the UI prompts & toast notifications, it unfortunately also displays the entire PowerShell window showing the script to the user which not acceptable!

I then called PowerShell with -NonInteractive -WindowStyle Hidden:

C:\Path\to\ServiceUI.exe -process:explorer.exe powershell.exe -NonInteractive -WindowStyle Hidden -File C:\Path\To\Custom\Script.ps1

That does work to hide the PowerShell window when it’s called, but it briefly flashes on screen which will either panic people or annoy them, neither of which is desirable.

After playing around with this for a bit, I got it to work by using ServiceUI to call wscript.exe which runs a VBScript that in turn launches PowerShell as a hidden process with the same command line, except without -NonInteractive -WindowStyle Hidden. It’s a bit Rube Goldbergian but it works.

1 Like

For this are you thinking that the Execute-ProcessAsUser would then run some vbscript to display a prompt? (or a PowerShell script that displays some UI?)

I have had very similar issues when trying to dot source the PSADT for specific module I wanted to use for a previous solution, in the end, I resorted to using the full Toolkit to get it to work rather than use a VBScript solution like yours.

It’s a shame you have had to resort to using VBScript as your workaround, just be aware that this won’t work forever - in case you had not seen Microsoft announced on the 10th October 2023 that VBScript will be deprecated.

“VBScript is being deprecated. In future releases of Windows, VBScript will be available as a feature on demand before its removal from the operating system.”

The Register link:

and Microsoft link:

I have found a possible workaround to ServiceUI.EXE’s limitation requiring an instance of Explorer.exe running.

The following CMD script runs in the system context and checks if a user is logged in.
If a user is detected, it uses ServiceUI.EXE
If NO user is detected, it does not.

Save the following as Install.CMD:

    REM This is meant for installing on Intune/MEM.
    REM The following determine if users are logged on or not.
    REM If Users are logged in, we use ServiceUI.EXE and hide the PS Console with Deploy-Application.exe
    query user | FIND "No User exists for"
    Set USERFOUND=%ERRORLEVEL%
    Echo [%~NX0] query user USERFOUND =[%USERFOUND%]

    If "%USERFOUND%" == "1" (
        Echo [%~NX0] Logged-in users Found. Launching Interactively
		REM Deploy-Application.exe hides the PS console but It only launches Deploy-Application.ps1
		ServiceUI.exe -Process:explorer.exe Deploy-Application.exe -DeploymentType "Install" -DeployMode "Interactive"

    ) Else (
        Echo [%~NX0] NO logged in users found. Launching silently
		powershell.exe -ExecutionPolicy Bypass -File "Deploy-Application.ps1" -DeploymentType "Install"

	)

*** DISCLAIMER: Untested ***

I am still testing at my end

I think we should have an EXE detect users and launch ServiceUI.EXE if needed instead of this script.

1 Like

That looks good.

Although maybe I’d suggest an exe (or script) that can take parameters such as -Install, -Uninstall, or -Repair so you can have one app (or script) that can be used to pass through to PSADT the required command(s) - Might make the install, uninstall or repair commands cleaner
:person_shrugging:

Well the code to detect logged-in users exists in PSADT already so you could write the equivalent in PowerShell. I could post it here if you want. I needed it in CMD at my work.

We don’t have SCCM or Intune and PSEXEC is frowned upon. So we have to use a somewhat roundabout approach to get software installing remotely and interactively under the SYSTEM account.
So ServiceUI kicks in and works as expected.
Add this Powershell module to the PC pushing out the instruction “invoke-CommandAS
Copy all files locally, including ServiceUI.exe in the same folder as Deploy-Application.exe

invoke-commandAS -computername  <PCName> { .\Serviceui.exe -process:explorer.exe c:\Appdeployfolder\deploy-application.exe } -AsSystem

This is the 1st test, and results are looking consistently good.
most certainly needs peer review from other PSADT admins, as it has taken me a couple of months to get even this far…

2 Likes