Calling ServiceUI.exe From PS

I am trying to call the ServiceUI.exe from a script that is running from Intune. Everything runs correctly when not running from Intune. Basically, when the script runs, it gets to the ServiceUI.exe portion and appears to skip that entire section, not even kicking errors. I have been at this for a week and can’t figure out what is happening.

Here is the script flow.

Intune downloads script to workstation.

CopyScripts.ps1 runs.

New-Item -Path "C:\Program Files\BitlockerPINSetup" -ItemType Directory
Copy-Item -Path DetectBitlocker\* -Destination "C:\Program Files\BitlockerPINSetup" -Recurse -Force

Start-Sleep -Seconds 30

Start-Process powershell.exe -Argumentlist "-executionpolicy bypass -File `"C:\Program Files\BitlockerPINSetup\DetectBitlockerPIN.ps1`"" -Wait -RedirectStandardError 'C:\Logs\DetectBitlocketPIN_StartupError.txt' -NoNewWindow

DectectBitlockerPIN.ps1

#region Functions
function WriteLogFile() {
	[CmdletBinding()]
	Param (
		[Parameter(ValueFromPipeline)]
		$message
	)
	$message | Out-File $logfile -Encoding $encode -Append
}

function launch_bitlockerpinprompt {
	$arglist = '-process:explorer.exe C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive -WindowStyle Hidden -File ' + "$PSScriptRoot" + '\BitlockerPINPrompt.ps1'
	try {
		Start-Process -FilePath $PSScriptRoot\ServiceUI.exe -ArgumentList $arglist -ErrorAction Stop -Wait
		"$PSScriptRoot\ServiceUI.exe $arglist" | WriteLogFile
		"$time : Informa : Launched BitlockerPINPrompt.ps1" | WriteLogFile
	}
	catch {
		"$time : Failure : Could not launch BitlockerPINPrompt.ps1" | WriteLogFile
		$_ | WriteLogFile
	}
	
}
#endregion

#region Setup Logging

#region Set Log Path
if (Test-Path C:\Logs -PathType Container) {
	Write-Host 'Setting log path to C:\Logs' -ForegroundColor Cyan
	$logpath = 'C:\Logs'
}
else {
	Write-Host 'Creating log folder on C:\' -ForegroundColor Cyan
	New-Item -Path C:\ -Name 'Logs' -ItemType Directory | Out-Null
	$logpath = 'C:\Logs'
}
#endregion

#region Set Log Name
$pc = $env:COMPUTERNAME
$logname = $pc + '_BitlockerPIN.log'
#endregion

#region Set Full Log Path and Encoding
$logfile = $logpath + "\" + $logname
Write-Host 'Setting full log path name to' $logfile -ForegroundColor Cyan
# Setting Out-File Encoding
$encode = "utf8"

if (Test-Path -Path $logfile) {
}
else {
	Write-Host 'Creating log file' $logname -ForegroundColor Cyan
	New-Item -Path C:\Logs -Name $logname -ItemType File -Force | Out-Null
}
#endregion

#region Create Dynamic Time Stamp
$time = Get-Date -Format o
Set-PSBreakpoint -Variable time -Mode Read -Action {
	$global:time = Get-Date -Format o
} | Out-Null
#endregion

#region Start Log Output
if (Test-Path -Path $logfile) {
	if ((Get-Item $logfile).Length -gt 0kb) { }
	else {
		Write-Host ''
		Write-Host "$time : Informa : Started Logging" -ForegroundColor Cyan
		'Bitlocker PIN Set' | Out-File $logfile -Encoding $encode
		'====================================' | WriteLogFile
		'====================================' | WriteLogFile
		"Date/Time: $time" | WriteLogFile
		"Workstaion Name: $pc" | WriteLogFile
		"LogPath: $logfile" | WriteLogFile
		"" | WriteLogFile
		"" | WriteLogFile
		"$time : Informa : Started Logging" | WriteLogFile
	}
}
else {
	Write-Host ''
	Write-Host "$time : Informa : Started Logging" -ForegroundColor Cyan
	'PIN Set' | Out-File $logfile -Encoding $encode
	'====================================' | WriteLogFile
	'====================================' | WriteLogFile
	"Date/Time: $time" | WriteLogFile
	"Workstaion Name: $pc" | WriteLogFile
	"LogPath: $logfile" | WriteLogFile
	"" | WriteLogFile
	"" | WriteLogFile
	"$time : Informa : Started Logging" | WriteLogFile
}
#endregion

#endregion

"" | WriteLogFile
"$time : Informa : Setting temp_pin.txt path" | WriteLogFile

$temppath = 'C:\temp\temp_pin.txt'

"$time : Informa : Testing is temppath exists" | WriteLogFile
if (Test-Path -Path 'C:\temp') {
	"$time : Success : Temppath found" | WriteLogFile
}
else {
	"$time : Warning : Temppath not found" | WriteLogFile
	"$time : Informa : Creating temp folder on C:" | WriteLogFile
	
	try {
		New-Item -ItemType Directory -Path 'C:\temp' | Out-Null
		"$time : Success : Temp folder created on C:" | WriteLogFile
	}
	catch {
		"$time : Failure : Could not create temp folder" | WriteLogFile
	}
	
	"$time : Informa : Setting ACL on C:\Temp" | WriteLogFile
	
	try {
		$acl = Get-ACL -Path "C:\temp"
		$accessrule = New-Object System.Security.AccessControl.FileSystemAccessRule("Domain Users", "Modify", "Allow")
		$acl.SetAccessRule($AccessRule)
		$acl | Set-Acl -Path "C:\temp"
		"$time : Success : ACL set on C:\Temp" | WriteLogFile
	}
	catch {
		"$time : Failure : Could not set ACL on C:\Temp" | WriteLogFile
	}
	
}

"$time : Informa : Getting encryptions status" | WriteLogFile
$get_encryptionstatus = Get-BitLockerVolume

if ($get_encryptionstatus.VolumeStatus -eq 'FullyEncrypted') {
	$encrypted = $true
	"$time : Informa : Drive encrypted" | WriteLogFile
	$get_tpmpinstatus = (Get-BitLockerVolume -MountPoint $env:SystemDrive).KeyProtector | Where-Object { $_.KeyProtectorType -eq 'TpmPin' }
	if ($get_tpmpinstatus.KeyProtectorType -eq 'TpmPin') {
		$pinset = $true
		Write-Host 'TPM PIN Found'
		"$time : Success : TPM PIN found" | WriteLogFile
	}
	else {
		Write-Host 'Could not find TPM PIN'
		$pinset = $false
		"$time : Warning : TPM PIN not found" | WriteLogFile
		"$time : Informa : Launching BitlockerPINPrompt.ps1" | WriteLogFile
		
		try {
			launch_bitlockerpinprompt
		}
		catch {
			"$time : Failure : Could not launch BitlockerPINPrompt.ps1" | WriteLogFile
		}
		
		"$time : Informa : Attemping to set PIN" | WriteLogFile
		$testfile = Test-Path -Path $temppath
		if ($testfile -eq $true) {
			$securefile = Get-Content $temppath
			$securefilestring = ConvertTo-SecureString $securefile
			# $plainpin = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($securefilestring))
			if ($pinset -ne $true) {
				Write-Host 'PIN not set'
				try {
					Add-BitLockerKeyProtector -MountPoint "C:" -Pin $securefilestring -TPMandPinProtector
					"$time : Success : Bitlocker PIN set" | WriteLogFile
				}
				catch {
					"$time : Failure : Could not set Bitlocker PIN set" | WriteLogFile
				}
				
				"$time : Informa : Removing $temppath" | WriteLogFile
				Remove-Item $temppath
			}
		}
		else {
			Write-Host 'File not found'
			"$time : Failure : $temppath could not be found" | WriteLogFile
			Write-Host 'Stopping script'
		}
	}
}
else {
	Write-Host 'Workstation not encrypted'
	"$time : Failure : Workstation not encrypted" | WriteLogFile
}

BitlockerPINPrompt.ps1

function WriteLogFile() {
	[CmdletBinding()]
	Param (
		[Parameter(ValueFromPipeline)]
		$message
	)
	$message | Out-File $logfile -Encoding $encode -Append
}

#region Setup Logging

#region Set Log Path
if (Test-Path C:\Logs -PathType Container) {
	Write-Host 'Setting log path to C:\Logs' -ForegroundColor Cyan
	$logpath = 'C:\Logs'
}
else {
	Write-Host 'Creating log folder on C:\' -ForegroundColor Cyan
	New-Item -Path C:\ -Name 'Logs' -ItemType Directory | Out-Null
	$logpath = 'C:\Logs'
}
#endregion

#region Set Log Name
$pc = $env:COMPUTERNAME
$logname = $pc + '_BitlockerPIN.log'
#endregion

#region Set Full Log Path and Encoding
$logfile = $logpath + "\" + $logname
Write-Host 'Setting full log path name to' $logfile -ForegroundColor Cyan
# Setting Out-File Encoding
$encode = "utf8"

if (Test-Path -Path $logfile) {
}
else {
	Write-Host 'Creating log file' $logname -ForegroundColor Cyan
	New-Item -Path C:\Logs -Name $logname -ItemType File -Force | Out-Null
}
#endregion

#region Create Dynamic Time Stamp
$time = Get-Date -Format o
Set-PSBreakpoint -Variable time -Mode Read -Action {
	$global:time = Get-Date -Format o
} | Out-Null
#endregion

#region Start Log Output
if (Test-Path -Path $logfile) {
	if ((Get-Item $logfile).Length -gt 0kb) {
	}
	else {
		Write-Host ''
		Write-Host "$time : Informa : Bitlocker PIN Prompt" -ForegroundColor Cyan
		"$time : Informa : Bitlocker PIN Prompt" | WriteLogFile
	}
}
else {
	Write-Host ''
	Write-Host "$time : Informa : Bitlocker PIN Prompt" -ForegroundColor Cyan
	"$time : Informa : Bitlocker PIN Prompt" | WriteLogFile
}
#endregion

#endregion

"$time : Informa : Creating PIN Prompt form" | WriteLogFile
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
[System.Windows.Forms.Application]::EnableVisualStyles()

$temppath = 'C:\temp\temp_pin.txt'

function get_bitlockerpin {
	$pin = $tb_validatepin.Text
	$pinsecure = ConvertTo-SecureString $pin -AsPlainText -Force
	$pinencrypted = ConvertFrom-SecureString $pinsecure
	$pinencrypted | Out-File -FilePath $temppath
	$form.Close()
}


$l_createpin = New-Object System.Windows.Forms.Label
$l_createpin.Location = New-Object System.Drawing.Point(10, 20)
$l_createpin.Size = New-Object System.Drawing.Size(200, 20)
$l_createpin.Text = 'Please create a 6-20 character PIN'

$tb_createpin = New-Object System.Windows.Forms.TextBox
$tb_createpin.Location = New-Object System.Drawing.Point(10, 40)
$tb_createpin.Size = New-Object System.Drawing.Size(160, 20)

$l_validatepin = New-Object System.Windows.Forms.Label
$l_validatepin.Location = New-Object System.Drawing.Point(10, 65)
$l_validatepin.Size = New-Object System.Drawing.Size(200, 20)
$l_validatepin.Text = 'Please reenter PIN'

$tb_validatepin = New-Object System.Windows.Forms.TextBox
$tb_validatepin.Location = New-Object System.Drawing.Point(10, 85)
$tb_validatepin.Size = New-Object System.Drawing.Size(160, 20)

$btn_setpin = new-object System.Windows.Forms.Button
$btn_setpin.Location = new-object System.Drawing.Size(210, 50)
$btn_setpin.Size = new-object System.Drawing.Size(100, 40)
$btn_setpin.Text = "Set PIN"
$btn_setpin.Add_Click({ get_bitlockerpin })

$form = New-Object system.Windows.Forms.Form
$form.Size = New-Object System.Drawing.Size(350, 175)
$form.StartPosition = 'CenterScreen'
$form.Text = 'Create New Bitlocker PIN'

$form.Controls.Add($l_createpin)
$form.Controls.Add($tb_createpin)
$form.Controls.Add($l_validatepin)
$form.Controls.Add($tb_validatepin)
$form.Controls.Add($btn_setpin)
$form.ShowDialog()

When looking at the log file that is created, it appears that the BitlockerPINPrompt.ps1 file is just being skipped. I have been unable to locate any other system logs that would indicate differently.

Any help is greatly appreciated.

Pretty sure when running through intune it’s running as a service which means it can’t interact with the user interactive session. Meaning it’s not going to work

That is what the ServiceUI.exe. is suppose to do. It allows the service to enter into the user session. This may not be the correct forum for this question.

@neemobeer Intune runs as the local system account by default which also has impersonation rights to all local accounts on that system by default.

@joseph-monarch Have you tried running these from the system account manually? You can use psexec.exe to run as system interactively.

If you want an easy button, you could use my function

https://github.com/krzydoug/Tools/blob/master/Invoke-PowershellAsSystem.ps1

It will download psexec and launch as system for you.

I have been using a test system to run these cmds. It takes forever for Intune to do a sync. Psexec looks perfect for me to be able to test quicker. Depending on the answer I get from our IT Security department, I may be able to run this in production as well.

I will keep you updated.