Automating administrative tasks on Windows often requires running scripts with elevated privileges. When you can’t have a UAC prompt interrupting your workflow, you need a reliable, non-interactive way to elevate. Two powerful and modern approaches to this problem are gsudo for local elevation and Invoke-SSHCommand for remote execution.

This guide provides a deep dive into both tools, comparing their strengths and weaknesses to help you decide which one is the right fit for your automation needs, whether you’re managing a local machine or a fleet of remote servers.


Part 1: Local Elevation with gsudo

gsudo is a free, open-source sudo equivalent for Windows. It allows a script or user to elevate their privileges in the current console or run a new command as an administrator, often without a UAC prompt if the credentials are correct or cached.

How to Install gsudo

You can install gsudo easily with winget or by downloading the MSI.

# Install using winget (recommended)
winget install gerardog.gsudo

# Or, download the MSI and install it silently
# msiexec /i gsudo.x.x.x.msi /quiet

Non-Interactive Elevation with gsudo

The real power of gsudo for automation is its ability to run commands non-interactively, using provided credentials to bypass the UAC prompt.

Here’s how to run a command as a specific admin user without any user interaction:

# Define the credentials for the local admin user
$cred = [pscredential]::new("$env:COMPUTERNAME\localadmin", ('myP@ssw0rd' | ConvertTo-SecureString -AsPlainText -Force))

# This part is tricky: we need to get the password as plain text for the gsudo command line
$ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($cred.Password)
$plainPass = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($ptr)
[System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($ptr) # Clear the password from memory

# Define the command to run
$cmdToRun = 'cmd /c "c:\job\update-mps\msOffice\9-msOffice.cmd"'

# Execute the command with gsudo
& gsudo runas "/user:$($cred.UserName)" "/password:$plainPass" $cmdToRun

This approach is perfect for scheduled tasks, CI/CD pipelines, or any other scenario where a script needs to elevate itself locally without user intervention.

Reusable Function: Invoke-GsudoCommand

To make this even easier, you can use a reusable PowerShell function that handles the credential conversion securely.

function Invoke-GsudoCommand {
    param (
        [Parameter(Mandatory = $true)]
        [string]$CmdToRun,
        [Parameter(Mandatory = $true)]
        [pscredential]$Credential
    )

    $ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($Credential.Password)
    try {
        $plainPass = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($ptr)
        
        # Build the arguments for gsudo
        $gsudoArgs = "runas", "/user:$($Credential.UserName)", "/password:$plainPass", $CmdToRun
        
        # Pipe the password to gsudo
        echo $plainPass | gsudo @gsudoArgs
    }
    finally {
        # Always clear the plain text password from memory
        if ($ptr -ne [System.IntPtr]::Zero) {
            [System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($ptr)
        }
    }
}

# --- How to Use ---
# In a real script, you would get the credential from a secure source
$cred = Get-Credential "$env:COMPUTERNAME\localadmin"
Invoke-GsudoCommand -CmdToRun 'powershell -Command "Get-Service -Name sshd"' -Credential $cred

Part 2: Remote Execution with Invoke-SSHCommand

When you need to run administrative tasks on a remote Windows machine, Invoke-SSHCommand (from the Posh-SSH module) is an excellent choice. It uses the standard SSH protocol, which is secure, reliable, and often already allowed through firewalls.

How to Set Up

  1. Install Posh-SSH Module:
    Install-Module -Name Posh-SSH -Scope CurrentUser
  2. Enable OpenSSH Server on the remote machine: On the remote Windows server, install and enable the OpenSSH Server feature.

Running a Remote Command

The script below connects to a remote host via SSH and executes a PowerShell script as an administrator.

# Define the credentials for an admin user on the remote host
$cred = [pscredential]::new("$hostName\localadmin", ('myP@ssw0rd' | ConvertTo-SecureString -AsPlainText -Force))

# Create an SSH session
$session = New-SSHSession -ComputerName $hostName -Credential $cred -AcceptKey

# Invoke the command on the remote host
Invoke-SSHCommand -SSHSession $session -Command 'powershell -NoProfile -File "C:\job\update-mps\msOffice\9-msOffice.ps1"'

# Clean up the session
Remove-SSHSession -SSHSession $session

Because the SSH session is headless, no UAC prompt is ever displayed. If the user you connect with is an administrator, the command will run with full administrative privileges.


Part 3: Comparison and Recommendations

Feature Invoke-SSHCommand (Posh-SSH) gsudo
Target Remote host (via SSH) Local host only
Elevation Method Uses the privileges of the SSH user account Elevates the current process or runs a new one as admin
Requires Server? ✅ Yes (OpenSSH Server) ❌ No
Network Protocol TCP/22 (encrypted) None (local process)
UAC Prompt None (headless) Yes, unless credentials are provided or cached
Best For Remote automation, managing a fleet of servers Local elevation, scheduled tasks, CI/CD agents

Which Tool Should You Choose?

Scenario Recommended Tool Why
Automating tasks on remote servers Invoke-SSHCommand Secure, reliable, and uses a standard protocol.
A script needs to elevate itself on a local machine gsudo Fast, simple, and designed for local elevation.
Running a scheduled task as an admin gsudo Perfect for non-interactive local elevation.
Working in an air-gapped or offline environment gsudo Works without any network connectivity.
You need to avoid UAC prompts entirely Both, when used correctly Invoke-SSHCommand is naturally headless; gsudo can be with provided credentials.

Conclusion

Both gsudo and Invoke-SSHCommand are excellent, modern solutions for automating administrative tasks on Windows without interactive UAC prompts. The choice between them is simple:

  • For local elevation, use gsudo. It is the perfect tool for scripts that need to run as an administrator on the machine they are executed on.
  • For remote execution, use Invoke-SSHCommand. It provides a secure and reliable way to manage remote machines over a standard, firewall-friendly protocol.

By understanding the strengths of each tool, you can build robust, non-interactive automation workflows for any scenario, whether it’s on a single machine or across your entire infrastructure.