Question Runspace et click event

Plus d'informations
il y a 6 ans 7 mois #24053 par Marc
Runspace et click event a été créé par Marc
Bonjour à tous,

voila un petit bout de code:
[code:1]
Add-Type -AssemblyName PresentationFramework, PresentationCore, WindowsBase

[xml]$Main =@'
<Window
xmlns=\"schemas.microsoft.com/winfx/2006/xaml/presentation\";
xmlns:«»x=\"schemas.microsoft.com/winfx/2006/xaml\";
xmlns:d=\"schemas.microsoft.com/expression/blend/2008\";
xmlns:mc=\"schemas.openxmlformats.org/markup-compatibility/2006\";
Title=\"MainWindow\" Height=\"154\" Width=\"270\">
<Grid>
<Button Name=\"button\" Content=\"Button\" HorizontalAlignment=\"Left\" Margin=\"88,60,0,0\" VerticalAlignment=\"Top\" Width=\"75\"/>
<TextBox Name=\"txtBox\" Text=\"{Binding Col1}\" HorizontalAlignment=\"Left\" Height=\"23\" Margin=\"62,5,0,0\" TextWrapping=\"Wrap\" VerticalAlignment=\"Top\" Width=\"120\"/>
<TextBox Name=\"txtBox2\" HorizontalAlignment=\"Left\" IsEnabled=\"False\" Height=\"23\" Margin=\"62,30,0,0\" TextWrapping=\"Wrap\" VerticalAlignment=\"Top\" Width=\"120\"/>
</Grid>
</Window>
'@

$reader = New-Object System.Xml.XmlNodeReader $Main
$MainForm = [Windows.Markup.XamlReader]::Load($reader)

#---- Initialise GUI Object
$Main.SelectNodes(\"//*[@Name]\"«») | ForEach-Object { Set-Variable -Name ($_.Name) -Value $MainForm.FindName($_.Name) }

#Initialisation d'une DataTable pour l'exemple
$DataTable = New-Object System.Data.DataTable
[void]$DataTable.Columns.Add('Col1')
$DataTable.Rows.Add('Coucou')
$MainForm.DataContext = $DataTable

[System.Windows.RoutedEventHandler]$ClickEvent =
{
[scriptblock]$script =
{
param
(
[System.Data.DataTable]$scriptdata
)
#Pour être sur le script fait quelque chose dans le runspace
$scriptdata.Rows[0].Col1 = 'Hello'
}

[scriptblock]$action =
{
if($Sender.RunspaceAvailability -eq 'Available')
{
#Je passe la txtbox2 à IsEnable
$txtbox2.IsEnabled = $true
Write-Host 'fini'
$Sender.Close()
}
}

$RunspaceFactory = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace()
$Powershell=[System.Management.Automation.PowerShell]::Create()

#Je rajoute mon script avec les arguments associé
[void]$Powershell.AddScript($script).AddArgument($DataTable)
$Powershell.Runspace = $RunspaceFactory
$RunspaceFactory.Open()

# Je passe le txtbox2 au runspace
$RunspaceFactory.SessionStateProxy.SetVariable(\"txtbox2\",$txtBox2)

# Je créer un evenement pour checker le déroulement du runspace
Register-ObjectEvent -InputObject $RunspaceFactory -EventName 'AvailabilityChanged' -Action $action

# Je démarre mon runspace
$Powershell.BeginInvoke()
}

$button.add_Click($ClickEvent)

$MainForm.ShowDialog()
[/code:1]

Je clique sur le bouton, des actions sont mené.
Une fois que le runspace devient dispo il doit exécuter d'autres actions.

Le problème et qu'il ne les exécute pas lors du premier clique. Il le fait lors d'un second clique sur le bouton.

Une âme charitable pour me dire ce que j'ai mal fait s'il vous plait... :unsure:
Merci.

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

Plus d'informations
il y a 6 ans 7 mois #24055 par Philippe
Réponse de Philippe sur le sujet Re:Runspace et click event
salut macci

je n'y connaît rien en runspace mais il me semble que l'initialisation du runspace ce place en dehors d'un event un tuto ici

plus un exemple

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

Plus d'informations
il y a 6 ans 7 mois #24056 par Laurent Dardenne
Réponse de Laurent Dardenne sur le sujet Re:Runspace et click event
Avec ces traces on comprend un peu mieux ce qui se passe :
[code:1]
[System.Windows.RoutedEventHandler]$ClickEvent =
{
Write-Warning \"ClickEvent\"
Write-Warning \"$(Get-EventSubscriber |out-string)\"

[scriptblock]$script =
{
param
(
[System.Data.DataTable]$scriptdata
)
#Pour être sur le script fait quelque chose dans le runspace
$scriptdata.Rows[0].Col1 = 'Hello'
}

[scriptblock]$action =
{
Write-Warning \"Action Event\"
Write-Warning \"$($EventSubscriber |out-string)\"
if($Sender.RunspaceAvailability -eq 'Available')
{
#Je passe la txtbox2 à IsEnable
$txtbox2.IsEnabled = $true
Write-Host 'fini'
$Sender.Close()
}
}

$RunspaceFactory = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace()
$Powershell=[System.Management.Automation.PowerShell]::Create()

#Je rajoute mon script avec les arguments associé
[void]$Powershell.AddScript($script).AddArgument($DataTable)
$Powershell.Runspace = $RunspaceFactory
$RunspaceFactory.Open()

# Je passe le txtbox2 au runspace
$RunspaceFactory.SessionStateProxy.SetVariable(\"txtbox2\",$txtBox2)

# Je créer un evenement pour checker le déroulement du runspace
Register-ObjectEvent -InputObject $RunspaceFactory -EventName 'AvailabilityChanged' -Action $action

Write-Warning \"Je démarre mon runspace\"
$Powershell.BeginInvoke()
}

[/code:1]
Le premier appel fonctionne, mais le gestionnaire d'event Powershell ($Action) est quel part où n'est pas le thread du GUI lorsque le code de $ClickEvent est terminé.

Lorsqu'on clique une seconde fois, le gestionnaire d'event de PS ($action) se déclenche, puis c'est le code de $ClickEvent qui s'exécute.
Quelqu'un 'bloque' qq chose :P

Ensuite on constate que la 'queue' d'event de PS ($action) contient un event supplémentaire à chaque fois que l'on clique sur le bouton.

De plus il me semble que des appels à dispose ou close manquent...

Je ne suis pas allé plus loin pour te fournir une explication plus détaillée :woohoo:
Mais je suis curieux de connaitre le pourquoi du comment :silly:

Tutoriels PowerShell

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

Plus d'informations
il y a 6 ans 7 mois #24061 par Marc
Réponse de Marc sur le sujet Re:Runspace et click event
Salut à tous,
alors...

Merci 6ratgus pour les lien, car c'est bien là qu'était la solution.

Pour faire marcher mon code, il faut que l'UI soit instancié dans un runspace défini et que le click_event lance ses actions dans un autre runspace.
Et la tout marche au premier clique.

Ce que je retient, c'est qu'il doit y des restrictions sur le runspace qui contient l'instance principale de powershell, ce n'est qu'un sentiment et je n'ai pas le courage ni les compétences pour fouiller :whistle:
et qu'il faut faire attention avec les runspace, powershell plante violement si on fait une cagade :lol: .

Le petit bout de code pour ceux que ça intéresse.
Ce n'est qu'un brouillon...
[code:1]
Add-Type -AssemblyName PresentationFramework, PresentationCore, WindowsBase

$syncHash = [hashtable]::«»Synchronized(@{}) #<---- Object conteneur /!\

#Pincipal runspace
$newRunspace =[runspacefactory]::CreateRunspace()
$newRunspace.ApartmentState = \"STA\"
$newRunspace.ThreadOptions = \"ReuseThread\"
$newRunspace.Open()
$newRunspace.SessionStateProxy.SetVariable(\"syncHash\",$syncHash)
$psCmd = [PowerShell]::Create().AddScript({

#<
UI construction
[xml]$Main =@'
<Window
xmlns=\"schemas.microsoft.com/winfx/2006/xaml/presentation\";
xmlns:«»x=\"schemas.microsoft.com/winfx/2006/xaml\";
xmlns:d=\"schemas.microsoft.com/expression/blend/2008\";
xmlns:mc=\"schemas.openxmlformats.org/markup-compatibility/2006\";
Title=\"MainWindow\" Height=\"154\" Width=\"270\">
<Grid>
<Button Name=\"button\" Content=\"Button\" HorizontalAlignment=\"Left\" Margin=\"88,60,0,0\" VerticalAlignment=\"Top\" Width=\"75\"/>
<TextBox Name=\"txtBox\" Text=\"{Binding Col1}\" HorizontalAlignment=\"Left\" Height=\"23\" Margin=\"62,5,0,0\" TextWrapping=\"Wrap\" VerticalAlignment=\"Top\" Width=\"120\"/>
<TextBox Name=\"txtBox2\" HorizontalAlignment=\"Left\" IsEnabled=\"false\" Height=\"23\" Margin=\"62,30,0,0\" TextWrapping=\"Wrap\" VerticalAlignment=\"Top\" Width=\"120\"/>
</Grid>
</Window>
'@
$reader = New-Object System.Xml.XmlNodeReader $Main

#<
fill Object conteneur
$syncHash.MainForm = [Windows.Markup.XamlReader]::Load($reader)
$syncHash.txtBox = $syncHash.MainForm.FindName(\"txtBox\"«»)
$syncHash.txtBox2 = $syncHash.MainForm.FindName(\"txtBox2\"«»)
$syncHash.Button = $syncHash.MainForm.FindName(\"button\"«»)
$syncHash.Error = $Error
$syncHash.Data = New-Object System.Data.DataTable
[void]$syncHash.Data.Columns.Add('Col1')
[void]$syncHash.Data.Rows.Add('Coucou')
$syncHash.MainForm.DataContext = $syncHash.Data

#<---- ClickEvent definition
[System.Windows.RoutedEventHandler]$ClickEvent =
{
Add-Content -Value 'Click Event' -Path C:\temp\log.txt

#<
Click action
[scriptblock]$script =
{
#Pour être sur le script fait quelque chose dans le runspace
Add-Content -Value 'Déroulement du click' -path c:\temp\log.txt
$hash.Data.Rows[0].Col1 = 'Hello'
$hash.txtBox2.Dispatcher.invoke([action]{$hash.txtBox2.IsEnabled=$true},\"Normal\"«»)
}
#<---- Runspace Availability change action
[scriptblock]$action =
{
if($Sender.RunspaceAvailability -eq 'Available')
{
Add-Content \"$(Get-EventSubscriber |out-string)\" -path c:\temp\log.txt
$Sender.Close()
Add-Content -Value 'Action Closed' -path c:\temp\log.txt
}
}

#<---- Click runspace definition
$RunspaceFactory = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace()
$RunspaceFactory.ApartmentState = \"MTA\"
$RunspaceFactory.Open()
$RunspaceFactory.SessionStateProxy.SetVariable(\"hash\",$syncHash)
Register-ObjectEvent -InputObject $RunspaceFactory -EventName 'AvailabilityChanged' -Action $action -MessageData $hash
$Powershell=[System.Management.Automation.PowerShell]::Create()
[void]$Powershell.AddScript($script)
$Powershell.Runspace = $RunspaceFactory
Add-Content \"Je démarre mon runspace\" -path c:\temp\log.txt
$Powershell.BeginInvoke() |Out-Null
}
#<--- Add click
$syncHash.Button.Add_Click($ClickEvent)

$syncHash.MainForm.ShowDialog() |Out-Null
})


$psCmd.Runspace = $newRunspace
$Gui = $psCmd.BeginInvoke()
[/code:1]


Tant que je suis dans les runspace...
Savez vous comment faire pour voir ce qu'il se passe à l'intérieur ?
Les fichiers de logs, ce n'est pas pratique.<br><br>Message édité par: marcci, à: 2/08/17 13:46

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

Plus d'informations
il y a 6 ans 7 mois #24062 par Laurent Dardenne
Réponse de Laurent Dardenne sur le sujet Re:Runspace et click event
marcci écrit:

Les fichiers de logs, ce n'est pas pratique.

Avec Log4Posh tu peux avoir un appender Console, les traces de debug sont affichées dans la console.
Ainsi on peut par exemple débugger une règle PSScriptAnalyzer codée avec PS ou afficher les traces d'un job (runspace inside)

Tutoriels PowerShell

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

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