Windows窗体中的Powershell进度条
我正在尝试向powershell中的窗体添加进度条。我不想使用PowerShell的Write Progress cmdlet(因为当我从命令行运行脚本时,它会显示一个基于文本的进度条,而我总是希望看到一个基于表单/图形的进度条) 我试过这个,它似乎有效(在线找到): 但是,我不希望事件更新进度条(正如上面示例中的$timer1_OnTic一样),我希望通过在整个脚本中调用来更新进度条,例如:Windows窗体中的Powershell进度条,powershell,Powershell,我正在尝试向powershell中的窗体添加进度条。我不想使用PowerShell的Write Progress cmdlet(因为当我从命令行运行脚本时,它会显示一个基于文本的进度条,而我总是希望看到一个基于表单/图形的进度条) 我试过这个,它似乎有效(在线找到): 但是,我不希望事件更新进度条(正如上面示例中的$timer1_OnTic一样),我希望通过在整个脚本中调用来更新进度条,例如: $progressBar1.PerformStep() 或 因此,每当我调用PerformStep(
$progressBar1.PerformStep()
或
因此,每当我调用PerformStep()或更改progressBar的值时,我似乎需要某种后台工作程序来更新进度条
调用ShowDialog将停止脚本内的所有处理,直到表单关闭。如果我理解正确,您应该能够将ShowDialog()更改为Show(),这样将显示对话框而不会阻止脚本。然后可以继续执行并更新进度条
不过,您可能会对表单缺乏交互性感到失望 我成功使用的一种方法是为GUI(在本例中为WPF)使用子运行空间,这样它就不会锁定脚本。可以通过会话状态代理在父运行空间和子运行空间中访问数据 e、 g
#定义共享变量
$sharedData=[HashTable]::已同步(@{});
$sharedData.Progress=0;
$sharedData.state=0;
$sharedData.EnableTimer=$true;
#设置运行空间(WPF需要STA)
$rs=[RunSpaceFactory]::CreateRunSpace();
$rs.ApartmentState=“STA”;
$rs.ThreadOptions=“ReuseThread”;
$rs.Open();
#将共享变量配置为可从两侧访问(父运行空间和子运行空间)
$rs.SessionStateProxy.setVariable(“sharedData”,$sharedData);
#定义要在子运行空间中运行的代码
$script={
添加类型-程序集表示框架;
添加类型-组件表示核心;
添加类型-组装WindowsBase;
[xml]$xaml=@”
你好,世界
"@
#处理上面的xaml
$reader=New Object System.Xml.XmlNodeReader$xaml;
$dialog=[Windows.Markup.XamlReader]::加载($reader);
#获取进度条的句柄
$progBar=$dialog.FindName(“ProgressComplete”);
$progBar.Value=0;
#定义要在每个间隔运行的代码(更新条形图)
#别忘了包括一种停止脚本的方法
$scriptBlock={
如果($sharedData.EnableTimer=$false){
$timer.IsEnabled=$false;
$dialog.Close();
}
$progBar.value=$sharedData.Progress;
}
#在计时器上,在每个“滴答声”上运行脚本
$dialog.Add_SourceInitialized({
$timer=新对象System.Windows.Threading.DispatherTimer;
$timer.Interface=[TimeSpan]“0:0:0.50”;
$timer.Add_Tick($scriptBlock);
$timer.Start();
如果(!$timer.IsEnabled){
$dialog.Close();
}
});
#启动计时器并显示对话框
&$scriptBlock;
$dialog.ShowDialog()| out null;
}
$ps=[PowerShell]::Create();
$ps.Runspace=$rs;
$ps.AddScript($script).BeginInvoke();
#如果需要GUI中的数据,可以通过$sharedData变量进行访问
写入输出$sharedData;
如果您尝试此代码,在显示对话框后,您可以通过设置$sharedData.progress
这使我能够为工具编写大量对话框,我受我们的基础设施的限制,无法在运行空间中使用powershell,WPF似乎比表单工作得更好。看看它有水平、垂直和圆形进度条。谢谢,Show()方法做到了这一点。非常感谢。虽然此链接可以回答问题,但最好在此处包含答案的基本部分,并提供链接供参考。如果链接页面发生更改,则仅链接的答案可能无效。
$progressBar1.PerformStep()
$progressBar1.Value = 10
# define the shared variable
$sharedData = [HashTable]::Synchronized(@{});
$sharedData.Progress = 0;
$sharedData.state = 0;
$sharedData.EnableTimer = $true;
# Set up the runspace (STA is required for WPF)
$rs = [RunSpaceFactory]::CreateRunSpace();
$rs.ApartmentState = "STA";
$rs.ThreadOptions = "ReuseThread";
$rs.Open();
# configure the shared variable as accessible from both sides (parent and child runspace)
$rs.SessionStateProxy.setVariable("sharedData", $sharedData);
# define the code to run in the child runspace
$script = {
add-Type -assembly PresentationFramework;
add-Type -assembly PresentationCore;
add-Type -assembly WindowsBase;
[xml]$xaml = @"
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
MaxHeight="100" MinHeight="100" Height="100"
MaxWidth="320" MinWidth="320" Width="320"
WindowStyle="ToolWindow">
<Canvas Grid.Row="1">
<TextBlock Name="ProgressText" Canvas.Top="10" Canvas.Left="20">Hello world</TextBlock>
<ProgressBar Name="ProgressComplete" Canvas.Top="30" Canvas.Left="20" Width="260" Height="20" HorizontalAlignment="Center" Value="20" />
</Canvas>
</Window>
"@
# process the xaml above
$reader = New-Object System.Xml.XmlNodeReader $xaml;
$dialog = [Windows.Markup.XamlReader]::Load($reader);
# get an handle for the progress bar
$progBar = $dialog.FindName("ProgressComplete");
$progBar.Value = 0;
# define the code to run at each interval (update the bar)
# DON'T forget to include a way to stop the script
$scriptBlock = {
if ($sharedData.EnableTimer = $false) {
$timer.IsEnabled = $false;
$dialog.Close();
}
$progBar.value = $sharedData.Progress;
}
# at the timer to run the script on each 'tick'
$dialog.Add_SourceInitialized( {
$timer = new-Object System.Windows.Threading.DispatherTimer;
$timer.Interface = [TimeSpan]"0:0:0.50";
$timer.Add_Tick($scriptBlock);
$timer.Start();
if (!$timer.IsEnabled) {
$dialog.Close();
}
});
# Start the timer and show the dialog
&$scriptBlock;
$dialog.ShowDialog() | out-null;
}
$ps = [PowerShell]::Create();
$ps.Runspace = $rs;
$ps.AddScript($script).BeginInvoke();
# if you want data from your GUI, you can access it through the $sharedData variable
Write-Output $sharedData;