Я начал размышлять о пространствах выполнения в powershell, и я смог сделать следующее
- Создать RunSpace
- Передать переменные
- Passпредустановленная функция
- GUI / WPF появляется, и я даже могу манипулировать элементами на нем (например, изменение текста в текстовом блоке)
Проблема заключается вкнопки (BTN_Exit) ... Я хотел бы добиться этого при нажатии, это не только закрывает графический интерфейс, но закрывает RunSpace, где он запускается.Я дошел до того, что мне удалось закрыть графический интерфейс и даже вызвать последовательность закрытия для Runspace, но (я предполагаю), поскольку вызываемая функция выполняется в самом RunSpace, она просто зависает (RunSpace остается в «закрытии»)состояние) - по-видимому, Powershell не может убить себя :) К счастью, я все еще могу удалить его из основного потока с помощью $(Get-Runspace)[-1].Dispose()
(Вручную)
Я считаю, что мне нужно подключиться к основному потоку, гдеGUI Runspace был создан и закройте его оттуда, но я не могу вернуться туда в функции.Вручную, если окно открыто, я могу выполнить все командлеты в функции close-runspace, и она достигает желаемой цели.
Я попытался добавить $rs.connect($(Get-Runspace).Name -eq "Runspace1")
& $RS.disconnect()
Если я попробую то же самое на«Ручка» или Экземпляр дает тот же результат.Также я не смог вызвать оригинальную функцию по нажатию кнопки, не передав функцию в RunSpace.
Как мне программно добраться до такой степени, что при нажатии кнопки она закрывает графический интерфейс и удаляет пространство выполнения?
Вот код:
#===[___VARIABLES___]===
$GUI = [hashtable]::Synchronized(@{})
$GUI.Host = $host
#===[___FUNCTIONS___]===
function Close-RunSpace {
if(!($RSI01H.Iscompleted)){
$GUI.BS.Dispatcher.invoke([action]{
$GUI.BS.Close()
})
}
$RSI01.EndInvoke($RSI01H)
$RS.Close()
$RS.Dispose()
}
#===[__RunSpaceCfg__]===
$RS_ISS = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
$RS_ISS.Commands.Add((New-Object System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList 'Close-RunSpace', (Get-Content Function:\Close-RunSpace -ErrorAction Stop)))
$RS = [runspacefactory]::CreateRunspace($RS_ISS)
$RS.ApartmentState = "STA"
$RS.ThreadOptions = "ReuseThread"
$RS.Open()
$RS.SessionStateProxy.SetVariable("GUI",$GUI)
$RS.SessionStateProxy.SetVariable("RS",$RS)
$RS.SessionStateProxy.SetVariable("RSI01",$RSI01)
$RS.SessionStateProxy.SetVariable("RSI01H",$RSI01H)
#===[___EXECUTION___]===
$RSI01 = [powershell]::Create().AddScript(
{
[void][System.Reflection.Assembly]::LoadWithPartialName("PresentationCore")
[void][System.Reflection.Assembly]::LoadWithPartialName("PresentationFramework")
[void][System.Reflection.Assembly]::LoadWithPartialName("WindowsBase")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$Def_XAML = DATA {'
<Window x:Name="BS" x:Class="PST.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PST"
mc:Ignorable="d"
Title="BootStrapR"
Height="450"
Width="800"
ResizeMode="NoResize"
Topmost="True"
FontFamily="Arial"
WindowStartupLocation="CenterScreen"
WindowStyle="None">
<Grid>
<Button x:Name="BTN_Update"
Content="Update"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="109,352,0,0"
Width="75"/>
<Button x:Name="BTN_Exit"
Content="exit"
HorizontalAlignment="Left"
Margin="431,352,0,0"
VerticalAlignment="Top"
Width="75"/>
<ProgressBar x:Name="pb"
HorizontalAlignment="Left"
Height="29"
Margin="10,150,0,0"
VerticalAlignment="Top"
Width="780"
Background="White"
Foreground="Black"
BorderBrush="White"
Value="0" />
<TextBlock x:Name="pstext"
HorizontalAlignment="Left"
Height="266"
Margin="26,22,0,0"
TextWrapping="Wrap"
Text="TextBlock"
VerticalAlignment="Top"
Width="223"/>
</Grid>
</Window>
'}
[xml]$XAML = $Def_XAML -replace 'x:Class=*.*','' `
-replace 'mc:Ignorable="d"','' `
-replace "x:Name",'Name'
$WPF = [Windows.Markup.XamlReader]::Load((New-Object System.Xml.XmlNodeReader $XAML))
$XAML.SelectNodes("//*[@Name]") | ForEach-Object{
$GUI."$($_.Name)" = $WPF.FindName($_.Name)
}
$GUI.Error = $Error
$GUI.BTN_Exit.Add_Click({
#$GUI.BS.Close()
Close-RunSpace
})
$GUI.BTN_Update.Add_Click({
$GUI.pb.Value+=1
})
$GUI.BS.ShowDialog() | Out-Null
}
)
$RSI01.Runspace = $RS
$RSI01.Runspace.Name = "GUI"
$RSI01H = $RSI01.BeginInvoke()