Workflow: return PSCredential object from inlinescript.

Oke some background info .. We have a script library for restarting / stopping etc our business application. It's run on several servers devided over tons of services. All these together is the entire application. We then have build several of these compartments. So we have 8 of these silo's  running in production.

There are quite a lot of services and machines so we have the starting of the services (in particular order) scripted via background jobs. With the amount of machines and services this can be quit slow on production. (400+).

The script which runs this is run under an account with no priviliges. We save our credentials with the following scripts.

https://github.com/RamblingCookieMonster/PowerShell/blob/master/Import-PSCredential.ps1

https://github.com/RamblingCookieMonster/PowerShell/blob/master/Export-PSCredential.ps1

We have an array of our servers as input. Each object has a property .computername  and .username. This is because some servers require different credentials (different zone, i.e. back-end or front-end).

The idea is to rewrite the background jobs into workflow and see if this can speed things up. (the alternative is runspaces but this is much harder to script and the amount of people who can maintain the scripts will be drastically less).

Now when I started testing I see a huge speed increase so I wanted to dive some more into the workflow option. However I ran across a very weird thing I cannot explain.

I have a computer list and a username as input for my workflow. At the start I get the credentials for the username I input and loop through the computers.

workflow Test-Workflow { [cmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateNotNull()] $ComputerName, [Parameter(Mandatory = $true)] [int32]$ThrottleLimit, [Parameter(Mandatory = $false)] [String]$Username ) $credentials = Inlinescript { Import-Module PSCredentials -Global $creds = Set-PSCredential -UserName $Using:UserName -SavePath "C:\Credentials" $creds }

    write-verbose $credentials foreach -parallel -throttlelimit $ThrottleLimit ($Computer in $ComputerName) { if (Test-Connection -ComputerName $Computer -Count 1 -ErrorAction silentlycontinue) { Inlinescript { #... do magic } -PSComputerName $Computer -PSCredential $Credentials } else { Write-Error "$Computer Not online!" } } }

The import PSCredentials has the functions I listed above. The moment I return the [PSCredential] object from the first inlinescript the entire workflow stalls.

I added some write-verbose in Import-PSCredential so see where it happens.  as such.

	write-verbose 'Import credential file'
    
	$import = Import-Clixml -Path $Path -ErrorAction Stop

	write-verbose 'Test for valid import'
	if ( -not $import.UserName -or -not $import.EncryptedPassword ) {
		Throw "Input is not a valid ExportedPSCredential object."
	}

	write-verbose 'Build the new credential object'
	$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $import.Username, $($import.EncryptedPassword | ConvertTo-SecureString)
    write-host 1
	if ($OutVariable)
    {
		New-Variable -Name $GlobalVariable -scope Global -value $Credential -Force
	} 
    else
    {
        write-verbose 'Output object'
		$Credential
        write-verbose 'exit function'
	}

VERBOSE: [localhost]:Importing function 'Export-PSCredential'.
VERBOSE: [localhost]:Importing function 'Import-PSCredential'.
VERBOSE: [localhost]:Importing function 'Set-PSCredential'.
VERBOSE: [localhost]:Import credential file
VERBOSE: [localhost]:Test for valid import
VERBOSE: [localhost]:Build the new credential object
VERBOSE: [localhost]:Output object
VERBOSE: [localhost]:exit function

After that nothing happens anymore. When I output only a [PsCredential] object without the password. So basically an credential object without password the script runs fine ...

I changed the following line.

$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $import.Username

VERBOSE: [localhost]:Importing function 'Export-PSCredential'.
VERBOSE: [localhost]:Importing function 'Import-PSCredential'.
VERBOSE: [localhost]:Importing function 'Set-PSCredential'.
VERBOSE: [localhost]:Import credential file
VERBOSE: [localhost]:Test for valid import
VERBOSE: [localhost]:Build the new credential object
VERBOSE: [localhost]:Output object
VERBOSE: [localhost]:exit function
VERBOSE: [localhost]:<domain>\<username> System.Management.Automation.PSCredential
Hit Line breakpoint on 'script.ps1:22'

I tried returning different objects and this stalling only happens with a [PSCredential] object.

Anyone has any idea why this happens? If I rewrite the whole thing and do the import-xml and export outside of an inlinescript block it runs fine. But that way I cannot use my custom functions and modules and makes it harder to maintain in multiple scripts.

February 20th, 2015 11:28am

Hi _mbezemer,

out of curiosity:
Why do you need to do anything outside the inner inline script beyond starting it once for every computer?

Can't tell you much about the workflow issues - we can't rely on them here, since most customers have older systems so far - however regarding Runspaces, there are several good Script-Functions available on the Technet Gallery that do all the Runspace implementation for you (like my own humble contribution).

Cheers,
Fred

Free Windows Admin Tool Kit Click here and download it now
February 20th, 2015 11:42am

Well it's because the inline script runs in a for each and can require different credentials per computer.

I tried the runspaces, but it seems much harder to maintain in a team with people with below average Powershell knowledge ;)

I also had some parameter issues with runspaces.

February 24th, 2015 6:43am

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics