Question workflow et powershell3

Plus d'informations
il y a 14 ans 5 mois #10733 par xyz
Réponse de xyz sur le sujet Re:workflow et powershell3
Pour info, le script de workflow suivant:
[code:1]
workflow WorkflowParallelForEach1
{
$counter = 0
foreach ($parallel_xx in 0..10)
{
if( $parallel_xx%2 -eq 0)
{
\"IfValue\" + $parallel_xx
}
else
{
Sleep -second 5
\"ElseValue\" + $parallel_xx
}
$counter += $parallel_xx
}
$counter
}
[/code:1]
subit qq transformations que l'on peut visualiser avec Get-Command :
[code:1]
$f=gcm -CommandType WorkflowParallelForEach1
$f.gettype()
#IsPublic IsSerial Name BaseType
#

----
#True False WorkflowInfo System.Management.Automation.FunctionInfo

$f|select *
$f.Parameters.getenumerator()|% {$_.Key}
$f.Parameters.getenumerator()|% {$_.value}
[/code:1]
La présence du mot clé workflow crée une entrée dans le provider function, c'est donc un nouveau type de fonction.
Là où pour une fonction son code initiale est identique, cf. propriété ScriptBlock, un workflow génére du code appellant le code initial transformé en XAML.

Le code d'appel :
[code:1]
#property ScriptBlock :
[CmdletBinding()]
param (
[switch] $AsJob,
[string[]] $PSComputerName,
[string] $JobName,
[ValidateNotNullOrEmpty()]
[string] $PSApplicationName,
[ValidateNotNullOrEmpty()]
$PSCredential,
[uint32] $PSPort,
[switch] $PSUseSSL,
[ValidateNotNullOrEmpty()]
[string] $PSConfigurationName,
[ValidateNotNullOrEmpty()]
[string[]] $PSConnectionURI,
[switch] $PSAllowRedirection,
[ValidateNotNullOrEmpty()]
[System.Management.Automation.Remoting.PSSessionOption] $PSSessionOption,
[ValidateNotNullOrEmpty()]
[System.Management.Automation.Runspaces.AuthenticationMechanism] $PSAuthentication,
[ValidateNotNullOrEmpty()]
[System.Management.AuthenticationLevel] $PSAuthenticationLevel,
[ValidateNotNullOrEmpty()]
[string] $PSCertificateThumbprint,
[uint32] $PSConnectionRetryCount,
[uint32] $PSConnectionRetryInterval,
[ValidateRange(1, 2147483647)]
[uint32] $PSRunningTimeoutSec,
[ValidateRange(1, 2147483647)]
[uint32] $PSElapsedTimeoutSec,
[ValidateRange(1, 2147483647)]
[uint32] $PSPersistInterval,
[bool] $PSPersist,
[string[]] $ForwardJobEvent,
[DateTime] $RunAt,
[hashtable] $PSPrivateMetadata,
[Parameter(ValueFromPipeline=$true)] $InputObject,
[hashtable[]] $PSParameterCollection
)
begin
{

function PSParameterCollectionValidation {
[CmdletBinding()]
param (
$PSInputCollection,
[switch] $AsJob,
[string[]] $PSComputerName,
[string] $JobName,
[ValidateNotNullOrEmpty()]
[string] $PSApplicationName,
[ValidateNotNullOrEmpty()]
$PSCredential,
[uint32] $PSPort,
[switch] $PSUseSSL,
[ValidateNotNullOrEmpty()]
[string] $PSConfigurationName,
[ValidateNotNullOrEmpty()]
[string[]] $PSConnectionURI,
[switch] $PSAllowRedirection,
[ValidateNotNullOrEmpty()]
[System.Management.Automation.Remoting.PSSessionOption] $PSSessionOption,
[ValidateNotNullOrEmpty()]
[System.Management.Automation.Runspaces.AuthenticationMechanism] $PSAuthentication,
[ValidateNotNullOrEmpty()]
[System.Management.AuthenticationLevel] $PSAuthenticationLevel,
[ValidateNotNullOrEmpty()]
[string] $PSCertificateThumbprint,
[uint32] $PSConnectionRetryCount,
[uint32] $PSConnectionRetryInterval,
[ValidateRange(1, 2147483647)]
[uint32] $PSRunningTimeoutSec,
[ValidateRange(1, 2147483647)]
[uint32] $PSElapsedTimeoutSec,
[ValidateRange(1, 2147483647)]
[uint32] $PSPersistInterval,
[bool] $PSPersist,
[string[]] $ForwardJobEvent,
[DateTime] $RunAt,
[hashtable] $PSPrivateMetadata,
[Parameter(ValueFromPipeline=$true)] $InputObject,
[hashtable[]] $PSParameterCollection
)
$PSBoundParameters
} #PSParameterCollectionValidation

$PSInputCollection = New-Object 'System.Collections.Generic.List[PSObject]'
}#begin

process {
if ($PSBoundParameters.ContainsKey('InputObject'))
{
$PSInputCollection.Add($InputObject)
}
} #process

end {
# None of the workflow parameters had default values
$parametersWithDefaults = @()
trap { break }
$parameterCollectionProcessed = $false
$PSParameterCollectionDefaultsMember = $null
if ($PSBoundParameters.ContainsKey('PSParameterCollection'))
{
$parameterCollectionProcessed = $true
# canonicalize each collection...
$PSParameterCollection = foreach ( $c in $PSParameterCollection) { PSParameterCollectionValidation @c }
# See if there is a defaults collection, indicated by '*'
foreach ($collection in $PSParameterCollection)
{
if ($collection -eq '*' )
{
if ($PSParameterCollectionDefaultsMember -ne $null)
{
throw ( New-Object System.InvalidOperationException([Microsoft.PowerShell.Commands.ImportWorkflowCommand]::«»ParameterErrorMessage) )
}
$PSParameterCollectionDefaultsMember = $collection;
foreach($parameter in $parametersWithDefaults)
{
if(! $collection.ContainsKey($parameter))
{
$collection[$parameter] = (Get-Variable $parameter).Value
}
} #foreach
} #if collection $collection
} #foreach

# If there was no '*' collection, added the paramter defaults
# to each individual collection if the parameter isn't already there...
if (-not $PSParameterCollectionDefaultsMember)
{
foreach ($collection in $PSParameterCollection)
{
foreach($parameter in $parametersWithDefaults)
{
if(! $collection.ContainsKey($parameter))
{
$collection[$parameter] = (Get-Variable $parameter).Value
}
}#foreach
} #foreach
}#if $PSParameterCollectionDefaultsMember
} # if $PSBound Contains PSParameterCollection
else
{
# no PSParameterCollection so add the default values to PSBoundParameters
foreach($parameter in $parametersWithDefaults)
{
if(! $PSBoundParameters.ContainsKey($parameter))
{
$PSBoundParameters[$parameter] = (Get-Variable $parameter).Value
}
}
}
if ($PSBoundParameters)
{
$CredentialTransform = New-Object System.Management.Automation.CredentialAttribute
$LocalCredential = $CredentialTransform.Transform($ExecutionContext,$PSCredential)
$PSBoundParameters = [system.management.automation.pscredential]$LocalCredential
}

# Extract the job name if specified
$jobName = ''
if ($PSBoundParameters)
{
$jobName = $PSBoundParameters
[void] $PSBoundParameters.Remove('JobName');
}

# Extract the PSParameterCollection if specified
[hashtable[]] $jobSpecifications = @()
$parametersCollection = $null;
if ($PSBoundParameters)
{
$parameterSCollection = $PSBoundParameters
[void] $PSBoundParameters.Remove('PSParameterCollection');
}

# Extract the job event registration if specified
$jobEventsToForward = $null
if ($PSBoundParameters)
{
$jobEventsToForward = $psBoundParameters
[void] $psBoundParameters.Remove('ForwardJobEvent');
}

# Remove the InputObject parameter from the bound parameters collection
if ($PSBoundParameters)
{
[void] $PSBoundParameters.Remove('InputObject');
}

# Remove parameters consumed by this function or PowerShell itself
$null = $PSBoundParameters.Remove('AsJob')
$null = $psBoundParameters.Remove('WarningVariable')
$null = $psBoundParameters.Remove('ErrorVariable')
$null = $psBoundParameters.Remove('OutVariable')
$null = $psBoundParameters.Remove('OutBuffer')
$null = $psBoundParameters.Remove('RunAt')

# Add parameter to add the path of the workflow module, needed by
Import-LocalizedData

# which uses this as a base path to find localized content files.
$psBoundParameters = ''

# Process author-specified metadata which is set using
# the Private member in the module manifest
$myCommand = $MyInvocation.MyCommand
$myModule = $myCommand.Module
if ($myModule)
{
# The function was defined in a module so look for
# the PrivateData member
[Hashtable] $privateData = $myModule.PrivateData -as [Hashtable]

if ($privateData)
{
# Extract the nested hashtable corresponding to this
# command
[hashtable] $authorMetadata = $privateData[$myCommand.Name]
if ($authorMetadata)
{
# Copy the author-supplied hashtable so we can safely
# modify it.
$authorMetadata = @{} + $authorMetadata
if ($psBoundParameters)
{
# merge in the user-supplied metadata
foreach ($pair in $psPrivateMetadata.GetEnumerator())
{
$authorMetadata[$pair.Key] = $pair.Value
}
}
# and update the bound parameter to include the merged data
$psBoundParameters = $authorMetadata
}
}
}

# Add in the input collection if there wasn't one explicitly passed
# which can only happen through PSParameterCollection
if (! $PSBoundParameters)
{
$PSBoundParameters = $PSInputCollection
}

# Create the final parameter collection...
$finalParameterCollection = $null
if ($PSParameterCollection -ne $null)
{
$finalParameterCollection = $PSParameterCollection
}
else
{
$finalParameterCollection = $PSBoundParameters
}

try
{
# Start the workflow and return the job object...
$job =[Microsoft.PowerShell.Commands.ImportWorkflowCommand]::«»StartWorkflowApplication(
$PSCmdlet,
$jobName,
'44cd3f37-18b0-499d-851c-2af8f65e0bba',
$AsJob,
$parameterCollectionProcessed,
$PSParameterCollectionDefaultsMember,
$finalParameterCollection)
}
catch
{
# extract exception from the error record
$e = $_.Exception
# this is probably a method invocation exception so we want the inner exception
# if it exists
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
throw (New-Object System.Management.Automation.ErrorRecord $msg,StartWorkflow.InvalidArgument, InvalidArgument, $finalParameterCollection)
}

if (-not $AsJob -and $job -ne $null)
{
Receive-Job -Job $job -Wait
Remove-Job -Job $job -Force
}
else
{
$job
}
} #end
[/code:1]
Remarquez que le code du workflow est exécuté dans un job et qu'il propose de nombreux paramètres.

Le code initial transformé :
[code:1]
$f.XamlDefinition

<Activity
x:Class=\"Microsoft.PowerShell.DynamicActivities.Activity_28de32c1b4714a0eb6b9cba8892ea75f\"
xmlns=\"schemas.microsoft.com/netfx/2009/xaml/activities\";
xmlns:«»sad=\"clr-namespace:«»System.Activities.Debugger;assembly=System.Activities\"
xmlns:local=\"clr-namespace:Microsoft.PowerShell.DynamicActivities\"
xmlns:mva=\"clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities\"
mva:VisualBasic.Settings=\"Assembly references and imported namespaces serialized as XML namespaces\"
xmlns:«»x=\"schemas.microsoft.com/winfx/2006/xaml\";
xmlns:ns0=\"clr-namespace:«»System;assembly=mscorlib\"
xmlns:ns1=\"clr-namespace:Microsoft.PowerShell.Activities;assembly=Microsoft.PowerShell.Activities\"
xmlns:ns2=\"clr-namespace:«»System.Collections.Generic;assembly=mscorlib\"
xmlns:ns3=\"clr-namespace:«»System.Management.Automation;assembly=System.Management.Automation\"
xmlns:ns4=\"clr-namespace:Microsoft.PowerShell.Utility.Activities;assembly=Microsoft.PowerShell.Utility.Activities\"
xmlns:ns5=\"clr-namespace:«»System.Activities.Statements;assembly=System.Activities\"
>
<Sequence>
<ns1:«»PowerShellValue x:TypeArguments=\"ns0:Object\" Expression=\"$counter = 0; $counter\" Result=\"[counter]\" />
<ParallelForEach x:TypeArguments=\"x:Object\">
<ParallelForEach.Values>
<InArgument x:TypeArguments=\"ns2:IEnumerable(ns0:Object)\">
<ns1:«»PowerShellValue x:TypeArguments=\"ns2:IEnumerable(ns0:Object)\" Expression=\",@(0..10)\" />
</InArgument>
</ParallelForEach.Values>
<ActivityAction x:TypeArguments=\"x:Object\">
<ActivityAction.Argument>
<DelegateInArgument x:TypeArguments=\"x:Object\" Name=\"parallel_xx\" />
</ActivityAction.Argument>
<Sequence>
<If>
<If.Condition>
<InArgument x:TypeArguments=\"ns0:Boolean\">
<ns1:«»PowerShellValue x:TypeArguments=\"ns0:Boolean\" Expression=\"$parallel_xx%2 -eq 0\" />
</InArgument>
</If.Condition>
<If.Then>
<Sequence>
<ns4:WriteOutput>
<ns4:WriteOutput.InputObject>
<InArgument x:TypeArguments=\"ns3:«»PSObject[]\">
<ns1:«»PowerShellValue x:TypeArguments=\"ns3:«»PSObject[]\" Expression=\""IfValue" + $parallel_xx\" />
</InArgument>
</ns4:WriteOutput.InputObject>
</ns4:WriteOutput>
</Sequence>
</If.Then>
<If.Else>
<Sequence>
<ns5:«»Delay>
<ns5:«»Delay.Duration>
<InArgument x:TypeArguments=\"ns0:TimeSpan\">
<ns1:«»PowerShellValue x:TypeArguments=\"ns0:TimeSpan\" Expression=\"'00:01:00'\" />
</InArgument>
</ns5:«»Delay.Duration>
</ns5:«»Delay>
<ns4:WriteOutput>
<ns4:WriteOutput.InputObject>
<InArgument x:TypeArguments=\"ns3:«»PSObject[]\">
<ns1:«»PowerShellValue x:TypeArguments=\"ns3:«»PSObject[]\" Expression=\""ElseValue" + $parallel_xx\" />
</InArgument>
</ns4:WriteOutput.InputObject>
</ns4:WriteOutput>
</Sequence>
</If.Else>
</If>
<ns1:«»PowerShellValue x:TypeArguments=\"ns0:Object\" Expression=\"$counter += $parallel_xx; $counter\" Result=\"[counter]\" />
</Sequence>
</ActivityAction>
</ParallelForEach>
<ns4:WriteOutput>
<ns4:WriteOutput.InputObject>
<InArgument x:TypeArguments=\"ns3:«»PSObject[]\">
<ns1:«»PowerShellValue x:TypeArguments=\"ns3:«»PSObject[]\" Expression=\"$counter\" />
</InArgument>
</ns4:WriteOutput.InputObject>
</ns4:WriteOutput>
<Sequence.Variables>
<Variable Name=\"counter\" x:TypeArguments=\"ns0:Object\" />
</Sequence.Variables>
</Sequence>
</Activity>
[/code:1]

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 14 ans 4 mois #10824 par xyz
Réponse de xyz sur le sujet Re:workflow et powershell3
L'équipe de dev de Powershell fournit une documenttion sur l'usage des Workflows.

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 14 ans 4 mois #10848 par jojo
Réponse de jojo sur le sujet Re:workflow et powershell3
merci Laurent,

je vais voir de plus près le fichier d'aide fourni par l'équipe de dev de ps

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 13 ans 11 mois #12042 par Matthew BETTON
Réponse de Matthew BETTON sur le sujet Re:workflow et powershell3
Encore de la lecture à propos du Workflow :

High Level Architecture of Windows PowerShell Workflow (Part 1)

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 13 ans 11 mois #12043 par SiSMik
Réponse de SiSMik sur le sujet Re:workflow et powershell3
Vivement que PSv3 passe en qualif chez nous !! ça donne l'eau à la bouche ce genre de truc !

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 13 ans 11 mois #12097 par Matthew BETTON

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.050 secondes
Propulsé par Kunena