Write-Verbose freezes PowerShell Workflow - powershell

I just stumbled upon this strange behavior of PowerShell Workflows and now I'm curious if anyone else can reproduce the behavior and maybe even explain it to me.
To describe the situation I've created two workflows that are almost identical. The only difference is that the PSCredential object is created in the workflow scope in the first and in the inlinescript in the second.
First I define the Workflows with the following code:
workflow WorkflowCred
{
[cmdletbinding()]
Param()
$Password = 'test' | ConvertTo-SecureString -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList 'test',$Password
InlineScript
{
Function Test-Verbose
{
[CmdletBinding()]
Param(
$Credential
)
Write-Output 'Start'
$Credential.GetType().FullName
Write-Verbose 'Testing'
Write-Output 'End'
}
Test-Verbose -Credential $Using:Credential
}
}
workflow InlineCred
{
[cmdletbinding()]
Param()
InlineScript
{
Function Test-Verbose
{
[CmdletBinding(
)]
Param(
$Credential
)
Write-Output 'Start'
$Credential.GetType().FullName
Write-Verbose 'Testing'
Write-Output 'End'
}
$Password = 'test' | ConvertTo-SecureString -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList 'test',$Password
Test-Verbose -Credential $Credential
}
}
Now to the strangeness. I can run the following Three commands without any problem:
WorkflowCred
InlineCred
WorkflowCred -Verbose
But if I run the second workflow with -Verbose my console freezes until I hit CTRL+C??
InlineCred -Verbose
I can see this behavior if all of the following conditions are true:
I run a function from within an InlineScript (in a PowerShell Workflow)
One of the parameters are given an object of the type PSCredential as value
The PSCredential object is created within the inlinescript
The function is Writing to the Verbose stream
I've tried this in PowerShell version 3 and 4.

Related

Jenkins Pipeline Powershell Variables

I having problems with Jenkins Pipeline when trying to excecute a PS Script and pass in a variable from a parameter
I saw a similar problem to mine here
Powershell script in jenkins pipeline
pipeline{
agent any
parameters {
choice choices: ['enargas', 'ci','scada','despacho','degnet','degabi','cm','AccesoDegas'], name: 'MODULO'
}
stages{
stage('Nea Modulos'){
steps{
powershell(
script: '''
$srvPassword = ConvertTo-SecureString "pass" -AsPlainText -Force
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist "AD\\user", $srvPassword
$parameters = #{
ComputerName = '172.16.40.8'
Credential = $cred
ArgumentList =123
ScriptBlock = {
Param ($param1)
echo $param1
[System.Environment]::SetEnvironmentVariable( \'modulo\', ${params.MODULO}, [System.EnvironmentVariableTarget]::User);
}
}
Invoke-Command #parameters
''')
}
}
}
}
I am expecting that a variable is ceated on the remote pc but no value comes from de parameter

Powershell start-process from Jenkins pipeline with -RedirectStandardOutput does not output

When running powershell start-process from Jenkins pipeline with -RedirectStandardOutput "$PSScriptRoot\Script.output.txt"
locally it writes the output to the file.
When it runs in my jenkins pipeline i does not out anything to "$PSScriptRoot\Script.output.txt"
The pipeline runs on a windows node calls the script like this
stage("RunPowershellWith AnotherUser")
{
steps
{
script
{
withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'c7e30cd4-4b6f-4387-8b2d-59f095bb5aae', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
powershell "${workspace}\\startAS.ps1 ${USERNAME} ${PASSWORD} "
}
}
}
}
The startAS.ps1 executes another powershell script with other credentials. The $PSScriptRoot\Script.output.txt is created, but there are no data in it. In fact i am in doubt if it is executed at all.
The powershell script looks like this
Param
(
[Parameter(Mandatory=$true, HelpMessage="Please provide username")][string] $username
,[Parameter(Mandatory=$true, HelpMessage="Please provide password")][string] $password
)
Write-Host "Running startAS"
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword
Start-process C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
"$PSScriptRoot\update_gdpr_module_dt_tables.ps1" -Credential $credential -WorkingDirectory "C:\Windows\System32\WindowsPowerShell\v1.0\" -RedirectStandardError "$PSScriptRoot\Script.output.error.txt" -RedirectStandardOutput "$PSScriptRoot\Script.output.txt"
It Runs fine from my locale workstation
The above code did not even execute the script. My problem was to execute a powershell withcredentials from another user.
I figured it out with this example
stage('run powershell with credentials from jenkins') {
steps {
withCredentials([usernamePassword(credentialsId: 'c7e30cd4-4b6f-4387-8b2d-59f095bb5aae', passwordVariable: 'passVar', usernameVariable: 'userVar')]) {
powershell '''
& .\\myscript.ps1
'''
}
}
}

PowerShell Install .exe application with Credentials stored in Clixml

Trying to create a Powershell script that installs an application (.exe) with stored credentials (Clixml).
Everything works fine when using:
Start-Process -FilePath "C:\Users\$($env:USERNAME)\Downloads\Software\Software.exe" -ArgumentList '/s' -Credential $credentials
But I would like a more elegant solution:
$startprocessParams = #{
FilePath = "C:\Users\$($env:USERNAME)\Downloads\Software\Software.exe"
ArgumentList = '/s'
Credential = $credentials
Verb = 'RunAs'
PassThru = $true
Wait = $true
}
$proc = Start-Process #startprocessParams
if ($proc.ExitCode -eq 0) {
'Software installed!'
}
else {
"Fail! Exit code: $($Proc.ExitCode)"
}
This works perfectly without the Credential parameter, you then get the "enter credentials/UAC" popup that I would like to avoid. With the Credential parameter I get this error:
Start-Process : Parameter set cannot be resolved using the specified name parameters.
What am I missing here? Appreciate any advice and/or guidance.
EDIT:
I use the following line to import the credentials:
$credentials = Import-Clixml "C:\Users\$Env:USERNAME\AppData\Local\Apps\SOFTWARE\cred.xml"
The credentials is created with a standard:
Get-Credential | Export-Clixml "C:\Users\$Env:USERNAME\AppData\Local\Apps\SOFTWARE\cred.xml"
This works as it should.
you need to set the credentials as PSCredential.
have a look at this solution:
$username = "username"
$password = "password"
$credentials = New-Object System.Management.Automation.PSCredential -ArgumentList #($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))
Start-Process dnscrypt-proxy.exe -WorkingDirectory path_here -Credential ($credentials)
is it stored in PSCredential in the first place?
Start-Process : Parameter set cannot be resolved using the specified name parameters.
The error tells us the set of parameters used is incorrect. Checking the MSDN doc or Get-Help for Start-Process will show that -Credential can not be used with -Verb.

How to run Command as a different user with Powershell?

I'm trying to make a script that changes the HostnameAlias for a given dns record.
But only certain users have access to editing these records, for example ADMIN can edit it but CURRENTUSER cannot.
Currently I have this piece of code:
param(
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
$Credential = $(Get-Credential)
)
$Command = "Set-DnsServerResourceRecord -NewInputObject $($NewObject) -OldInputObject $($OldObject) -ZoneName $($ZoneName)"
Start-Process -FilePath PowerShell -NoNewWindow -Credential $Credential -ArgumentList $Command
But i just keep getting Start-Process : This command cannot be run due to the error: The user name or password is incorrect even though I am absolutely sure they are indeed correct.
What am I doing wrong here.
Ps, I have looked at all the related questions, none seem to answer my question.
You can call System.Management.Automation.PSCredential object to specify any credentials you want and run with it in any process
$User = 'yourdomain\youruser'
$Password = 'yourpassword'
$Secure_Password = ConvertTo-SecureString $Password -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential($User, $Secure_Password)
$Command = "Set-DnsServerResourceRecord -NewInputObject $($NewObject) -OldInputObject $($OldObject) -ZoneName $($ZoneName)"
Start-Process -FilePath PowerShell -NoNewWindow -Credential $Credential -ArgumentList $Command
You can use this:
#Get User credential
$Credential = Get-Credential Domain\UserNameYouWant
#Use System.Diagnostics to start the process as User
$ProcessInfo = New-Object System.Diagnostics.ProcessStartInfo
#With FileName we're basically telling powershell to run another powershell process
$ProcessInfo.FileName = "powershell.exe"
#CreateNoWindow helps avoiding a second window to appear whilst the process runs
$ProcessInfo.CreateNoWindow = $true
#Note the line below contains the Working Directory where the script will start from
$ProcessInfo.WorkingDirectory = $env:windir
$ProcessInfo.RedirectStandardError = $true
$ProcessInfo.RedirectStandardOutput = $true
$ProcessInfo.UseShellExecute = $false
#The line below is basically the command you want to run and it's passed as text, as an argument
$ProcessInfo.Arguments = "The command you want"
#The next 3 lines are the credential for User as you can see, we can't just pass $Credential
$ProcessInfo.Username = $Credential.GetNetworkCredential().username
$ProcessInfo.Domain = $Credential.GetNetworkCredential().Domain
$ProcessInfo.Password = $Credential.Password
#Finally start the process and wait for it to finish
$Process = New-Object System.Diagnostics.Process
$Process.StartInfo = $ProcessInfo
$Process.Start() | Out-Null
$Process.WaitForExit()
#Grab the output
$GetProcessResult = $Process.StandardOutput.ReadToEnd()
# Print the Job results
$GetProcessResult
Just a mistake on my part, forgot to specify domain before username when entering credentials.
Can solve it like this Get-Credential Domain\

Call a remote script from another with multiple parameters not working

I am trying to create a script that will take input (hardcoded values for now) and call an install PS script and run it on multiple servers. I am using a PSSession and Invoke-Command(see below). The below runs, but does nothing. It doesn't seem to call the other script. Beyond getting it to actually install, I need to know if it was successful or not. I'm pretty novice at Powershell, so any hints/help/suggestions would be great. The below is wrapped in a ForEach to loop the servers with $Computer
Try
{
$session = New-PSSession -ComputerName App02 -Credential $cred
$sourceInstall = $sourceFolder + 'Install\Install.ps1'
Invoke-Command -Session $session -ScriptBlock{param($serviceName, $installFolder, $sourceFolder, $Action, $username, $password) $sourceInstall} -ArgumentList ($ServiceName, $installFolder, $sourceFolder, $Action, $username, $password)
}
Catch
{
$Filename = "Error.txt"
Write-Output "ERROR: Partial Service Deployment. See error log file(s)"
Add-Content $Filename $_.Exception.Message
}
Get-PSSession | Remove-PSSession
You can use it without $Using statement in any version of PowerShell.But pass that too as an argument.
Eg:-
Invoke-Command -ScriptBlock
param($Name)
& $Command $Name
} -ArgumentList 'Get-Process','Notepad'
But you have to pass the arguments positional when using the call operator '&'
Get-Help About_Parameters
https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_parameters
Regards,
Kvprasoon