Scheduled task to launch powershell script in system contect but have it run interactively

Graeme Talboys 96 Reputation points
2021-01-26T20:55:04.603+00:00

Hi
I have a powershell script that sets some HKLM reg keys but also interacts with the current logged in user by presenting them with a dialogue box which they can click OK on.
It works fine in SCCM when I deploy it to the system and set it to run interactively, the user gets the dialogue box (I am using a MessageBox to do this) and the reg keys get set.

I want to try and get this to run as a scheduled task but am having trouble getting it to do what I want.
If I run the scheduled task with the Builtin\Users user account and call the powershell script it presents the dialog box but the reg keys dont get set as the registry needs to be edited using admin creds.

If I run the scheduled task using the System account, the dialogue box isnt displayed but the reg keys are all set.

Any advice greatly appreciated

Thanks

Windows for business Windows Client for IT Pros User experience Other
{count} votes

Accepted answer
  1. Graeme Talboys 96 Reputation points
    2021-02-01T11:31:13.833+00:00

    I ended up using "ServiceUI.exe" which can be found in the MDT tools. It allows you to use the system account but still have it interact with the user


3 additional answers

Sort by: Most helpful
  1. MotoX80 36,291 Reputation points
    2021-01-27T17:13:11.03+00:00

    One solution is to use 2 scripts. That should work well as long as you don't need a lot of user interaction.

    Here is Server.ps1. Schedule a task to run it. It will create and run the task that interacts with the user.

    # This script runs as the system account so that it can perform admin changes
    # 
    # TODO: Add logging or use a PS Transcript 
    $ScriptFolder = "C:\Temp\Foo1"                    # Our scripts are here.
    $MsgFolder = "C:\Temp\Foo1\Msg"                   # This is where we communicate. Maybe use C:\Windows\Temp\MyMessages
    
    if ((Test-Path $MsgFolder)) {
        "Cleaning up old messages." 
        Remove-Item -path  $MsgFolder\*.msg 
    } else {
        "Creating MSG folder" 
        New-Item -ItemType Directory -Path $MsgFolder
    }
    
    # It was easier for me to just use the command line program instead of the PS cmdlets. 
    # Schedule the task for midnight because we have to specify a start time.
    # That doesn't matter because we will run the task immediately. 
    SCHTASKS /Create /tn "ClientTask"  /tr "Powershell.exe -File ""$ScriptFolder\Client.ps1""" /ru interactive /sc once /st 23:59 /f
    SCHTASKS /run /tn "ClientTask" 
    
    # Wait for the client to fire up and the user to say go. 
    $Wait4It = $false 
    while (!$Wait4It) {
        start-sleep 3
        $Wait4It = test-path $MsgFolder\Client.msg                   # wait for the go-ahead from the client 
        # TODO: check time to see if we've been waiting too long and need to give up. 
    }
    
    # We could read the msg if we needed. The fact that it got created tells us to proceed. 
    
    # Now do whatever it is we need to do.
    
    # TODO:  Add amin level code here.
    
    # Clean up the client msg and send some text back to the client script. 
    Remove-Item -path  $MsgFolder\Client.msg
    "The update was successful." | Out-File  $MsgFolder\Server.msg 
    
    # Wait for the client to acknowledge our message  
    $Wait4It = $false 
    while (!$Wait4It) {
        start-sleep 3
        $Wait4It = test-path $MsgFolder\Client.msg                   # wait for the client to acknowledge that we ran  
        # TODO: check time to see if we've been waiting too long and need to give up. 
    }
    
    # we're all done. The client is terminating. Do a little cleanup here.  
    
    Remove-Item -path  $MsgFolder\*.msg 
    SCHTASKS /delete /tn "ClientTask" /f 
    #TODO: Maybe delete the server task too. And send an email or something.  
    

    Here is the Client.ps1 script.

    # This is the script that interacts with the desktop user.
    $MsgFolder = "C:\Temp\Foo1\Msg"                   # This is where we communicate.
    
    #TODO: Use https://poshgui.com to build your form if you don't like this one.
    
    Add-Type -AssemblyName System.Windows.Forms
    
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")  
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 
    [void] [System.Windows.Forms.Application]::EnableVisualStyles() 
    
    # Here is where we communicate with the server script.  
    function Service 
    { 
        # Do something here
        if ($Okbutton.Text -eq "Done") { 
            "Client is terminating." | Out-File  $MsgFolder\Client.msg
            $form.Close()
            return
        }
    
        # Create client.msg
        "You may fire when ready, Gridley." | Out-File  $MsgFolder\Client.msg 
    
        $Wait4It = $false 
        while (!$Wait4It) {
            start-sleep 2
            "Waiting"
            $Wait4It = test-path $MsgFolder\Server.msg                   # wait for the server to send us a message   
            # TODO: check time to see if we've been waiting too long and need to give up. 
        }
        $Label.Text = Get-Content $MsgFolder\Server.msg                  # read the message and display on our form   
        $Okbutton.Text = "Done"  
    } 
    
    $Form = New-Object system.Windows.Forms.Form 
    $Form.Size = New-Object System.Drawing.Size(400,300) 
    $form.MaximizeBox = $false 
    $Form.StartPosition = "CenterScreen" 
    $Form.FormBorderStyle = 'Fixed3D' 
    $Form.Text = "Alert Message" 
    
    $Label = New-Object System.Windows.Forms.Label 
    $Label.Text = "Hey, it's lunch time. `nFree tacos in the break room." 
    $Label.AutoSize = $true 
    $Label.Location = New-Object System.Drawing.Size(75,50) 
    $Font = New-Object System.Drawing.Font("Arial",15,[System.Drawing.FontStyle]::Bold) 
    $form.Font = $Font 
    $Form.Controls.Add($Label) 
    $Okbutton = New-Object System.Windows.Forms.Button 
    $Okbutton.Location = New-Object System.Drawing.Size(140,180) 
    $Okbutton.Size = New-Object System.Drawing.Size(120,50) 
    $Okbutton.Text = "Okay" 
    $Okbutton.Add_Click({service}) 
    $Form.Controls.Add($Okbutton) 
    $Form.ShowDialog() 
    
    2 people found this answer helpful.

  2. S.Sengupta 24,476 Reputation points MVP
    2021-01-27T00:18:05.217+00:00

  3. Anonymous
    2021-01-27T03:42:20.2+00:00

    Hi,

    Applying reg keys needs administrator privilege. Please try using Builtin\Users account and checking "Run with highest privileges" to see if it helps.

    Thanks,

    Eleven

    If the Answer is helpful, please click "Accept Answer" and upvote it. Thanks.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.