I was poking around in workflows and stumbled across this when I looked at a workflows definition and saw a large PowerShell scriptblock. I'm sure some of you will find this as interesting as I did. Actually, this explains a lot about workflows and how and why they behave the way they do. Enjoy!
Note: fu was the actual workflow name I used just to look at an empty defined workflow, e.g. workflow fu {}; then use this to see the properties of the workflow: gci function:fu | fl *
Below is what is in the ScriptBlock property.
Note: fu was the actual workflow name I used just to look at an empty defined workflow, e.g. workflow fu {}; then use this to see the properties of the workflow: gci function:fu | fl *
Below is what is in the ScriptBlock property.
- [CmdletBinding()]
- param (
- [hashtable[]] $PSParameterCollection,
- [string[]] $PSComputerName,
- [ValidateNotNullOrEmpty()] $PSCredential,
- [uint32] $PSConnectionRetryCount,
- [uint32] $PSConnectionRetryIntervalSec,
- [ValidateRange(1, 2147483)][uint32] $PSRunningTimeoutSec,
- [ValidateRange(1, 2147483)][uint32] $PSElapsedTimeoutSec,
- [bool] $PSPersist,
- [ValidateNotNullOrEmpty()] [System.Management.Automation.Runspaces.AuthenticationMechanism] $PSAuthentication,
- [ValidateNotNullOrEmpty()][System.Management.AuthenticationLevel] $PSAuthenticationLevel,
- [ValidateNotNullOrEmpty()] [string] $PSApplicationName,
- [uint32] $PSPort,
- [switch] $PSUseSSL,
- [ValidateNotNullOrEmpty()] [string] $PSConfigurationName,
- [ValidateNotNullOrEmpty()][string[]] $PSConnectionURI,
- [switch] $PSAllowRedirection,
- [ValidateNotNullOrEmpty()][System.Management.Automation.Remoting.PSSessionOption] $PSSessionOption,
- [ValidateNotNullOrEmpty()] [string] $PSCertificateThumbprint,
- [hashtable] $PSPrivateMetadata,
- [switch] $AsJob,
- [string] $JobName,
- [Parameter(ValueFromPipeline=$true)]$InputObject
- )
- begin {
- function fu {
- [CmdletBinding()]
- param (
- $PSInputCollection,
- [string[]] $PSComputerName,
- [ValidateNotNullOrEmpty()] $PSCredential,
- [uint32] $PSConnectionRetryCount,
- [uint32] $PSConnectionRetryIntervalSec,
- [ValidateRange(1, 2147483)][uint32] $PSRunningTimeoutSec,
- [ValidateRange(1, 2147483)][uint32] $PSElapsedTimeoutSec,
- [bool] $PSPersist,
- [ValidateNotNullOrEmpty()] [System.Management.Automation.Runspaces.AuthenticationMechanism] $PSAuthentication,
- [ValidateNotNullOrEmpty()][System.Management.AuthenticationLevel] $PSAuthenticationLevel,
- [ValidateNotNullOrEmpty()] [string] $PSApplicationName,
- [uint32] $PSPort,
- [switch] $PSUseSSL,
- [ValidateNotNullOrEmpty()] [string] $PSConfigurationName,
- [ValidateNotNullOrEmpty()][string[]] $PSConnectionURI,
- [switch] $PSAllowRedirection,
- [ValidateNotNullOrEmpty()][System.Management.Automation.Remoting.PSSessionOption] $PSSessionOption,
- [ValidateNotNullOrEmpty()] [string] $PSCertificateThumbprint,
- [hashtable] $PSPrivateMetadata,
- [switch] $AsJob,
- [string] $JobName,
- [Parameter(ValueFromPipeline=$true)]$InputObject
- ) $PSBoundParameters
- }
- $PSInputCollection = New-Object 'System.Collections.Generic.List[PSObject]'
- }
- process {
- if ($PSBoundParameters.ContainsKey('InputObject'))
- {
- $PSInputCollection.Add($InputObject)
- }
- }
- end {
- $parametersWithDefaults = @()
- trap { break }
- $parameterCollectionProcessed = $false
- $PSParameterCollectionDefaultsMember = $null
- if ($PSBoundParameters.ContainsKey('PSParameterCollection'))
- {
- foreach ($pa in $PSBoundParameters.Keys)
- {
- if ($pa -eq 'JobName' -or $pa -eq 'AsJob' -or $pa -eq 'InputObject' -or $pa -eq 'PSParameterCollection')
- {
- continue
- }
- $msg = [Microsoft.PowerShell.Commands.ImportWorkflowCommand]::InvalidPSParameterCollectionAdditionalErrorMessage;
- throw (New-Object System.Management.Automation.ErrorRecord $msg, StartWorkflow.InvalidArgument, InvalidArgument, $PSParameterCollection)
- }
- $parameterCollectionProcessed = $true
- foreach ($collection in $PSParameterCollection)
- {
- if ($collection['PSComputerName'] -eq '*' )
- {
- if ($PSParameterCollectionDefaultsMember -ne $null)
- {
- $msg = [Microsoft.PowerShell.Commands.ImportWorkflowCommand]::ParameterErrorMessage;
- throw ( New-Object System.Management.Automation.ErrorRecord $msg, StartWorkflow.InvalidArgument, InvalidArgument, $PSParameterCollection)
- }
- $PSParameterCollectionDefaultsMember = $collection;
- foreach($parameter in $parametersWithDefaults)
- {
- if(! $collection.ContainsKey($parameter))
- {
- $collection[$parameter] = (Get-Variable $parameter).Value
- }
- }
- }
- }
- $PSParameterCollection = [Microsoft.PowerShell.Commands.ImportWorkflowCommand]::MergeParameterCollection(
- $PSParameterCollection, $PSParameterCollectionDefaultsMember)
- $PSParameterCollection = foreach ( $c in $PSParameterCollection) {
- if($c.containskey('AsJob') -or $c.containsKey('JobName') -or $c.containsKey('PSParameterCollection') -or $c.containsKey('InputObject'))
- {
- $msg = [Microsoft.PowerShell.Commands.ImportWorkflowCommand]::InvalidPSParameterCollectionEntryErrorMessage;
- throw ( New-Object System.Management.Automation.ErrorRecord $msg, StartWorkflow.InvalidArgument, InvalidArgument, $PSParameterCollection)
- }
- & "fu" @c
- }
- if (-not $PSParameterCollectionDefaultsMember)
- {
- foreach ($collection in $PSParameterCollection)
- {
- foreach($parameter in $parametersWithDefaults)
- {
- if(! $collection.ContainsKey($parameter))
- {
- $collection[$parameter] = (Get-Variable $parameter).Value
- }
- }
- }
- }
- }
- else
- {
- foreach($parameter in $parametersWithDefaults)
- {
- if(! $PSBoundParameters.ContainsKey($parameter))
- {
- $PSBoundParameters[$parameter] = (Get-Variable $parameter).Value
- }
- }
- $PSBoundParameters = & "fu" @PSBoundParameters
- }
- if ($PSBoundParameters['PSCredential'])
- {
- $CredentialTransform = New-Object System.Management.Automation.CredentialAttribute
- $LocalCredential = $CredentialTransform.Transform($ExecutionContext, $PSCredential)
- $PSBoundParameters['PSCredential'] = [system.management.automation.pscredential]$LocalCredential
- if (!$PSBoundParameters['PSComputerName'] -and !$PSBoundParameters['PSConnectionURI'])
- {
- $PSBoundParameters['PSComputerName'] = New-Object string @(,'localhost')
- }
- }
- $jobName = ''
- if ($PSBoundParameters['JobName'])
- {
- $jobName = $PSBoundParameters['JobName']
- [void] $PSBoundParameters.Remove('JobName');
- }
- [hashtable[]] $jobSpecifications = @()
- $parametersCollection = $null;
- if ($PSBoundParameters['PSParameterCollection'])
- {
- $parameterSCollection = $PSBoundParameters['PSParameterCollection']
- [void] $PSBoundParameters.Remove('PSParameterCollection');
- }
- if ($PSBoundParameters['InputObject'])
- {
- [void] $PSBoundParameters.Remove('InputObject');
- }
- $null = $PSBoundParameters.Remove('AsJob')
- $null = $psBoundParameters.Remove('WarningVariable')
- $null = $psBoundParameters.Remove('ErrorVariable')
- $null = $psBoundParameters.Remove('OutVariable')
- $null = $psBoundParameters.Remove('OutBuffer')
- $psBoundParameters['PSWorkflowRoot'] = ''
- try
- {
- $psBoundParameters['PSSenderInfo'] = $PSSenderInfo
- }
- catch
- {
- }
- $psBoundParameters['PSCurrentDirectory'] = $pwd.Path
- $myCommand = $MyInvocation.MyCommand
- $myModule = $myCommand.Module
- if ($myModule)
- {
- [Hashtable] $privateData = $myModule.PrivateData -as [Hashtable]
- if ($privateData)
- {
- [hashtable] $authorMetadata = $privateData[$myCommand.Name]
- if ($authorMetadata)
- {
- $authorMetadata = @{} + $authorMetadata
- if ($psBoundParameters['PSPrivateMetadata'])
- {
- foreach ($pair in $psPrivateMetadata.GetEnumerator())
- {
- $authorMetadata[$pair.Key] = $pair.Value
- }
- }
- $psBoundParameters['PSPrivateMetadata'] = $authorMetadata
- }
- }
- }
- if (! $PSBoundParameters['PSInputCollection'])
- {
- $PSBoundParameters['PSInputCollection'] = $PSInputCollection
- }
- $errorAction = "Continue"
- if ($PSBoundParameters['ErrorAction'] -eq "SilentlyContinue")
- {
- $errorAction = "SilentlyContinue"
- }
- if($PSBoundParameters['ErrorAction'] -eq "Ignore")
- {
- $PSBoundParameters['ErrorAction'] = "SilentlyContinue"
- $errorAction = "SilentlyContinue"
- }
- if ($PSBoundParameters['ErrorAction'] -eq "Inquire")
- {
- $PSBoundParameters['ErrorAction'] = "Continue"
- $errorAction = "Continue"
- }
- $warningAction = "Continue"
- if ($PSBoundParameters['WarningAction'] -eq "SilentlyContinue" -or $PSBoundParameters['WarningAction'] -eq "Ignore")
- {
- $warningAction = "SilentlyContinue"
- }
- if ($PSBoundParameters['WarningAction'] -eq "Inquire")
- {
- $PSBoundParameters['WarningAction'] = "Continue"
- $warningAction = "Continue"
- }
- $finalParameterCollection = $null
- if ($PSParameterCollection -ne $null)
- {
- $finalParameterCollection = $PSParameterCollection
- }
- else
- {
- $finalParameterCollection = $PSBoundParameters
- }
- try
- {
- $job = [Microsoft.PowerShell.Commands.ImportWorkflowCommand]::StartWorkflowApplication(
- $PSCmdlet,
- $jobName,
- 'ab0c05c8-c28f-48c7-97ea-915f34f4c0b8',
- $AsJob,
- $parameterCollectionProcessed,
- $finalParameterCollection)
- }
- catch
- {
- $e = $_.Exception
- if ($e -is [System.Management.Automation.MethodException] -and $e.InnerException)
- {
- $e = $e.InnerException
- }
- $msg = [Microsoft.PowerShell.Commands.ImportWorkflowCommand]::UnableToStartWorkflowMessageMessage -f `
- $MyInvocation.MyCommand.Name, $e.Message
- $newException = New-Object System.Management.Automation.RuntimeException $msg, $e
- throw (New-Object System.Management.Automation.ErrorRecord $newException, StartWorkflow.InvalidArgument, InvalidArgument, $finalParameterCollection)
- }
- if (-not $AsJob -and $job -ne $null)
- {
- try
- {
- Receive-Job -Job $job -Wait -Verbose -Debug -ErrorAction $errorAction -WarningAction $warningAction
- $PSCmdlet.InvokeCommand.HasErrors = $job.State -eq 'failed'
- }
- finally
- {
- if($job.State -ne "Suspended" -and $job.State -ne "Stopped")
- {
- Remove-Job -Job $job -Force
- }
- else
- {
- $job
- }
- }
- }
- else
- {
- $job
- }
- }
Great find! This makes understanding all the crazy restrictions so much easier to understand.
ReplyDelete