Use PowerShell to Install a Windows Service remotely

Use PowerShell to Install a Windows Service remotely

When installing a Windows Service remotely as a “Local Service” there are no credentials involved and this is a pretty straight forward  task.

But if you need to have the service installed under the account of a local user or a domain user then this is somewhat tricky. The security credentials you create using the PSCredential object are created using the DAPI (Windows Data Protection API) of the local machine and therefor will work only on that machine where they are created. So when passing them to a remote machine using Invoke-Command or PSsession the remote service will get installed but when started it will fail to start due to log on failure error.

The way to handle this is that when using the 2 methods ConvertTo-SecureString and ConvertFrom-SecureString we need to use the Key or SecureKey parameters. This results in using the the Advanced Encryption Standard (AES) encryption algorithm instead of the Windows Data Protection API (DPAPI). The specified key must have a length of 128, 192, or 256 bits because those are the key lengths supported by the AES encryption algorithm (If no key is specified, the Windows Data Protection API (DPAPI) is used to encrypt the standard string representation).

Here is an example of a script that I have used that uses a function I have created to accomplish the task of installing a Windows Service remotely on multiple machines.

<#
#https://powershelladministrator.com/2019/12/19/passing-user-credentials-to-a-remote-computer/

# mangment pc
Enable-WSManCredSSP -Role Client -DelegateComputer *. -Force

# remote pc
Invoke-Command -Session $session -ScriptBlock { Enable-WSManCredSSP -Role Server -Force; }
Invoke-Command -Session $session -ScriptBlock {New-Service -Name $using:service -BinaryPathName $using:path -StartupType $using:start_mode -DisplayName $using:service -Credential $using:credentials; }
Invoke-Command -Session $session -ScriptBlock { Disable-WSManCredSSP Server; }

#> 

function Install-Service
{
    param(
        $ComputerName,
        $User,
        $Password,
        $Path,
        $Service,      
        $Description,
        $StartMode
    )         
 
        $Credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $Password;
        $null = Invoke-Command -ComputerName $ComputerName -ScriptBlock {New-Service -Name $using:Service -BinaryPathName $using:Path -StartupType $using:StartMode -DisplayName $using:Service -Credential $using:Credentials;}
}


$pw_path = 'c:\temp';
if(-not( Test-Path -Path $pw_path) )
{
    New-Item -Path $pw_path -ItemType Directory;
}  

$pw_file = 'pw.txt';
$pw_file_full_name = Join-Path $pw_path $pw_file
 
if (-not $Secure)
{
   $Secure = Read-Host -AsSecureString;
}
$Key = (1,3,2,4,56,34,254,222,1,1,4,23,42,54,33,233,1,34,2,7,6,5,35,43);
$Encrypted = ConvertFrom-SecureString -SecureString $Secure -Key $key;
$Encrypted | Set-Content $pw_file_full_name;
 
 
$server = 'ECAESQLWFS11';
$user = 'eca\sqladm';
$service = 'CloudMonitoringCollector';
$path = '"C:\Program Files\CloudMonitoring\CloudMonitoringCollectorConsole.exe"';
$description = 'Collects Monitoring Metrics';
$start_mode = 'Automatic';
 
$password = Get-Content $pw_file_full_name | ConvertTo-SecureString -Key $Key;
 
Install-Service -ComputerName $server -User $user -Password $password -Path $path -Service $service -Description $description -StartMode $start_mode;
The following two tabs change content below.
Yaniv Etrogi is an SQL Server consultant. He loves SQL Server and he is passionate about Performance Tuning, Automation and Monitoring.

1 thought on “Use PowerShell to Install a Windows Service remotely”

  1. Pingback: SQL Server Utilities - Use SqlCredential with Powershell to connect to an instance of SQL Server - SQL Server Utilities

Leave a Comment

Your email address will not be published. Required fields are marked *