Question Runspace et click event
- Marc
- Auteur du sujet
- Hors Ligne
- Membre premium
Réduire
Plus d'informations
- Messages : 90
- Remerciements reçus 0
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...
Merci.
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...
Merci.
Connexion ou Créer un compte pour participer à la conversation.
- Philippe
- Hors Ligne
- Modérateur
Réduire
Plus d'informations
- Messages : 1778
- Remerciements reçus 21
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
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.
- Laurent Dardenne
- Hors Ligne
- Modérateur
Réduire
Plus d'informations
- Messages : 6300
- Remerciements reçus 68
il y a 6 ans 7 mois #24056
par Laurent Dardenne
Tutoriels PowerShell
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
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
Mais je suis curieux de connaitre le pourquoi du comment
[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
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
Mais je suis curieux de connaitre le pourquoi du comment
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Marc
- Auteur du sujet
- Hors Ligne
- Membre premium
Réduire
Plus d'informations
- Messages : 90
- Remerciements reçus 0
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
et qu'il faut faire attention avec les runspace, powershell plante violement si on fait une cagade .
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
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
et qu'il faut faire attention avec les runspace, powershell plante violement si on fait une cagade .
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.
- Laurent Dardenne
- Hors Ligne
- Modérateur
Réduire
Plus d'informations
- Messages : 6300
- Remerciements reçus 68
il y a 6 ans 7 mois #24062
par Laurent Dardenne
Tutoriels PowerShell
Réponse de Laurent Dardenne sur le sujet Re:Runspace et click event
marcci écrit:
Ainsi on peut par exemple débugger une règle PSScriptAnalyzer codée avec PS ou afficher les traces d'un job (runspace inside)
Avec Log4Posh tu peux avoir un appender Console, les traces de debug sont affichées dans la console.Les fichiers de logs, ce n'est pas pratique.
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
- Vous êtes ici :
- Accueil
- forum
- PowerShell
- Entraide pour les initiés
- Runspace et click event