0

I am trying to write small powerscript to execute an existing .ps1 file as a different user account than the one that is logged in. I need to run the existing .ps1 file on a regular basis. I need a powershell script that can be double clicked to run and it executes the existing .ps1 file as different user.

This is what I have so far:

$username = 'username'
$password = 'password'
$script = '\\path\to\file\script.ps1'


$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword
Start-Process powershell.exe -File $script -Credential $credential

Seems that the credential flags might not be in the right spot.

Would appreciate any guidance.

user695752
  • 319
  • 7
  • 18
  • Does this answer your question? [Running PowerShell as another user, and launching a script](https://stackoverflow.com/questions/28989750/running-powershell-as-another-user-and-launching-a-script) – Jeremy Thompson Feb 27 '23 at 01:58

2 Answers2

0

As an aside: Using plain-text passwords, especially if stored as such in a script, is best avoided in the interest of security.

tl;dr

Start-Process powershell.exe "-File `"$script`"" -Credential $credential

Start-Process has a -FilePath parameter that specifies the target executable and an array-typed -ArgumentList parameter that accepts all arguments to pass to that executable.

These two parameters are the first two positional parameters, so you don't strictly need to name them, but you must fulfill the syntax requirements for -ArgumentList, which means two things:

  • If you pass the pass-through arguments individually, you must separate them with , (which creates an array).

  • While not all pass-through arguments require quoting, those with special characters do, which notably includes those that start with -, because Start-Process will otherwise interpret them as its parameters.

Thus:

# !! May, but isn't guaranteed to work - see below.
Start-Process powershell.exe '-File', $script -Credential $credential

which is short for:

# !! May, but isn't guaranteed to work - see below.
Start-Process -FilePath powershell.exe -ArgumentList '-File', $script -Credential $credential

Unfortunately, a long-standing bug that won't be fixed in the interest of backward compatibility makes this approach brittle, because PowerShell does not apply on-demand double-quoting and escaping for you when it constructs the process command line behind the scenes - see GitHub issue #5576.

You must therefore perform any embedded double-quoting and escaping yourself, which is ultimately easier to do if you pass a single string to -ArgumentList that encodes all arguments to pass, using embedded double-quoting and escaping as needed, as shown in the solution at the top.

mklement0
  • 382,024
  • 64
  • 607
  • 775
0

As mklement0 correctly noted, it is better not to use passwords explicitly. I suggest using start-job instead of running a separate script. Plus, I will add password encryption functions on my own.

function setCred($role,$credPath){
    $credMassiv = @()
    if (Test-Path "$credPath\cred.csv"){$credMassiv = @(Import-Csv -Delimiter ";" -Path "$credPath\cred.csv")}
    else {$credMassiv = @()}
    $array = "" | Select user, Encrypted, role
    $array.user = read-host "user for $role"
    $pwd = read-host "password:" -AsSecureString
    $array.Encrypted = ConvertFrom-SecureString -SecureString $pwd
    $array.role = $role
    $cred = New-Object System.Management.Automation.PSCredential -ArgumentList $array.user, $pwd
    $credMassiv += $array
    $credMassiv |Export-Csv -Delimiter ";" -Encoding UTF8 -Path "$credPath\cred.csv"


    $cred
}



function getCred($role,$credPath){
$credMassiv = @()
$array = "" | Select user, Encrypted, role
    if (!(Test-Path "$credPath\cred.csv")){ $cred = setCred $role $credPath }

    if (Test-Path "$credPath\cred.csv"){
        $credMassiv = Import-Csv -Delimiter ";" -Path "$credPath\cred.csv"

        $user = $credMassiv |Where-Object {$_.role -eq $role} |Select-Object -Expand user
        $pwd = $credMassiv |Where-Object {$_.role -eq $role} |Select-Object -Expand Encrypted | ConvertTo-SecureString
        
        if ([string]::IsNullOrEmpty($pwd)){$cred = setCred $role $credPath}
        else {$cred = New-Object System.Management.Automation.PSCredential -ArgumentList $user, $pwd}
    }
    

$cred
}

$credential = get-cred "worker" $PSScriptRoot

$ScriptBlock = {
 param($path)
 write-host $path

}

          $temp = Start-Job -name "script" -Credential $credential -ArgumentList "C:\test" -ScriptBlock $ScriptBlock 
Get-Job -Name "script"

output: C:\test

rinat gadeev
  • 114
  • 4