Method invocation error when using PSCredential in Powershell - powershell

I will start by saying that I have successfully tested this script when running locally on my laptop against a remote dev server.
However, when I have migrated the script to our TFS server, I am now encountering the below (sanitized) error message.
2019-06-10T18:46:05.8256626Z Generating script.
2019-06-10T18:46:05.8257313Z Formatted command: . 'E:\***.ps1' -username "***" -password "***" -servername "***" -ScriptPath "***" -SourcePath "***" -DestinationPath "***" -CleanupFlag "***"
2019-06-10T18:46:06.0290179Z ##[command]"C:\windows\System32\WindowsPowerShell\v1.0\powershell.exe" -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command ". 'E:\***.ps1'"
2019-06-10T18:46:06.7520864Z Method invocation failed because [System.Management.Automation.PSCredential] does not contain a method named 'new'.
2019-06-10T18:46:06.7521292Z At E:\***.ps1:5 char:1
2019-06-10T18:46:06.7521480Z + $CredentialSec = [System.Management.Automation.PSCredential]::new($username,$PWsec)
2019-06-10T18:46:06.7523016Z + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2019-06-10T18:46:06.7523588Z + CategoryInfo : InvalidOperation: (:) [], ParentContainsErrorRecordException
2019-06-10T18:46:06.7524614Z + FullyQualifiedErrorId : MethodNotFound
2019-06-10T18:46:06.7525361Z
2019-06-10T18:46:06.8602349Z ##[error]PowerShell exited with code '1'.
The script is attempting to Invoke-Command (to run a different script) on a remote system. It appears to be messing up at the section where it creates a credential from the username and encrypted password.
This is the code that I'm attempting to execute:
param($username, $password, $servername, $ScriptPath, $SourcePath, $DestinationPath, $CleanupFlag)
$PWsec = ConvertTo-SecureString -String $password -AsPlainText -Force
$CredentialSec = [System.Management.Automation.PSCredential]::new($username,$PWsec)
Invoke-Command -ComputerName $servername -Credential $CredentialSec -FilePath $ScriptPath -ArgumentList $SourcePath, $DestinationPath, $CleanupFlag

Per mcclayton's suggestion in the comments... because the new server is running an older version of Powershell, it worked when I changed from this format:
$CredentialSec = [System.Management.Automation.PSCredential]::new($username,$PWsec)
To this format:
$CredentialSec = New-Object System.Management.Automation.PSCredential($username,$PWsec)

Related

How to use SSISDeploy command in powershell script

I'm running SSISDeploy command (documentation is here) in my CMD:
SSISDeploy.exe -s:"download\Integration Services.ispac" -d:catalog;/SSISDB/TEST/DEVOPS;"TEST03,1234" -at:win
all working good, and now I need to run it thought powershell script (against windows server 2019 slave), so I tried this syntax:
$SSISDeploy = Start-Process -FilePath SSISDeploy.exe -ArgumentList '/source:"download\Integration Services.ispac"',"/destination:catalog;${Target};"${Env}"" -at:win -wait -PassThru -Credential $cred -RedirectStandardOutput ssisstdout.txt -RedirectStandardError ssisstderr.txt
but it fails with exception:
Start-Process : A positional parameter cannot be found that accepts argument 'TEST03,1234'.
+ ... SISDeploy = Start-Process -FilePath SSISDeploy.exe -ArgumentList '/so ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Start-Process], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.StartProcessCommand
Can you suggest what's wrong with the syntax?
$StartProcessProps = #{
FilePath = 'SSISDeploy.exe'
ArgumentList = '-s:"download\Integration Services.ispac" -d:catalog;{0};{1} -at:win' -f $Target, $Env
Wait = $true
PassThru = $true
Credential = $cred
RedirectStandardOutput = 'ssisstdout.txt'
RedirectStandardError = 'ssisstderr.txt'
}
$SSISDeploy = Start-Process #StartProcessProp

calling PowerShell script from batch file to connect remote machine is not working

When I am running a PowerShell script normally it's working fine, issue is raising when calling the same script from batch file.
Unt1.ps1 script:
$linux_app_user="ORXXXX\"+$args[0]
$pass_win=$args[1]
$path=$args[2]
$pass = ConvertTo-SecureString -AsPlainText $pass_win -Force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList
$linux_app_user, $pass
$Invoke-Command -ComputerName XXXXXXXX.XXXX.XXX.XXXX -Credential $cred -ErrorAction
Stop -ScriptBlock {
param($path)
Invoke-Expression $path
} -Arg $path
cal.bat script:
#echo off
SET Server=slXXXXXXXX.XXX.XXXX.com
SET PowerShellDir=C:\Windows\System32\WindowsPowerShell\v1.0
CD /D "%PowerShellDir%
powershell.exe -ExecutionPolicy RemoteSigned -File
C:\Users\chaj\Documents\String\Unt1.ps1 'XXXX' 'XXXX#321' 'C:\cal.bat'
Error:
[xxxxxx.xx.xxxxx.xxx] Connecting to remote server xxxxxx.xx.xxxxx.xxx failed
with the following error message : The user name or password is incorrect.
For more information, see the about_Remote_Troubleshooting Help topic.
At C:\Users\chafg\Documents\String\Unt1.ps1:7 char:1
+ $Result=Invoke-Command -ComputerName xxxxxx.xx.xxxxx.xxx -Credenti ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (xxxxxx.xx.xxxxx.xxx) [], PSRemotingTransportException
+ FullyQualifiedErrorId : LogonFailure,PSSessionStateBroken
When using the PowerShell CLI with the -File parameter, all arguments are used verbatim - except if enclosed in "..." (double quotes): unlike when you use -Command, '...' (single quotes) are not recognized as string delimiters.
Therefore, your command (simplified here):
powershell.exe -File C:\path\to\Unt1.ps1 'XXXX' 'XXXX#321' 'C:\cal.bat'
causes the Unt1.ps1 script to see the arguments with the enclosing ', which is not your intent; e.g., instead of $args[0] receiving XXXX, as intended, it receives 'XXXX', verbatim.
The fix is to use "..." (double quotes):
powershell.exe -File C:\path\to\Unt1.ps1 "XXXX" "XXXX#321" "C:\cal.bat"
Alternatively, given that your specific sample arguments don't require quoting (though the real ones may):
powershell.exe -File C:\path\to\Unt1.ps1 XXXX XXXX#321 C:\cal.bat

Jenkins and powershell. Download file

I have a script in Powershell and want to run this on many servers.
It's running from Jenkins via a Powershell step, the input param $env:servers
Simple example:
$SrvPassword = ConvertTo-SecureString -String "$($ENV:SlavePassword)" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ("$ENV:SlaveUser", $SrvPassword)
Invoke-Command -Computername $env:servers -ScriptBlock {
$client = New-Object System.Net.WebClient
$client.DownloadFile("\\server1.domain.ru\123\123.zip","C:\123.zip")
} -Credential $cred
But when I build it with parametrs, i got error:
[firstDeploy] $ powershell.exe -NonInteractive -ExecutionPolicy ByPass "& 'C:\Users\ADMINI~1\AppData\Local\Temp\jenkins6658148949844825772.ps1'"
Exception calling "DownloadFile" with "2" argument(s): "Access to the path '\\server1.domain.ru\123\123.zip' is denied."
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
+ PSComputerName : server2.domain.ru
When i do this without jenkins all work fine. Share full access. What's wrong?

Error assigning variable in scheduled task action

I have a .xml file containing a username and encrypted password (the accessid and key for an API). Using the following line, I retrieve the credential:
$Credential = Import-CliXml -Path "${env:\userprofile}\token.xml"
This works great in the shell, but I need to schedule this command (along with the script that uses the cred). In the scheduled task, I am starting powershell.exe and passing the following as an argument:
-Command "& $credential = Import-CliXml -Path ${env:\userprofile}\token.Cred"
But I get back the error:
& : The term 'System.Management.Automation.PSCredential' is not recognized
as the name of a cmdlet, function, script file, or operable program. Check
the spelling of the name, or if a path was included, verify that the path
is correct and try again.
At line:1 char:3
+ & System.Management.Automation.PSCredential = Import-CliXml -Path C:\ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (System.Manageme...on.PSCredential:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
I tried several variations, including:
-Command (& $credential = Import-CliXml -Path ${env:\userprofile}\token.Cred)
-Command ($credential = Import-CliXml -Path ${env:\userprofile}\token.Cred)
-Command "$credential = Import-CliXml -Path ${env:\userprofile}\token.Cred"
But I get the same error. I need the variable, because I am going to also run the following (in the same action):
.\script.ps1 -AccessId $Credential.UserName -AccessKey ((System.Runtime.InteropServices.Marshal::PtrToStringAuto(System.Runtime.InteropServices.Marshal::SecureStringToBSTR($Credential.Password))))
What gives?
# using cmd.exe
powershell.exe -Command "& {$credential = Import-CliXml -Path ${env:\userprofile}\token.Cred}"
# using powershell, escape special characters
Start-Process powershell.exe -ArgumentList "-Command `"& {`$credential = Import-CliXml -Path `${env:\userprofile}\token.Cred;pause}`""

Trying to Invoke a Script on a Remote Computer

I'm having to construct some paths before attempting to invoke the script which is present on the remote computer. I'm adapting something we have working in TeamCity, but I'm currently getting the following error:
The command cannot be run because the File parameter requires a file path. Supply a path for the File parameter and then try the command again.
+ CategoryInfo : NotSpecified: (The command can... command again.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
Relevant code below:
$stageScript = "D:\pkg\${dir}\stage.ps1"
$options = "production \\192.168.0.x\staging \\${server}\staging"
Invoke-Command -computername server.domain.com { powershell.exe -noprofile -executionpolicy Bypass -file $stageScript $options } -Credential $credential
You need to pass local variables to the script block as an argument list
$stageScript = "D:\pkg\${dir}\stage.ps1"
$options = "production \\192.168.0.x\staging \\${server}\staging"
Invoke-Command -computername server.domain.com { powershell.exe -noprofile -executionpolicy Bypass -file $args[0] $args[1] } -ArgumentList $stageScript,$options -Credential $credential