我真的很喜欢你的解决方案,但正如你所说,这个问题不适用于 PS2.0,包括我需要的 Win7 服务包 1。
我的 GUI 更新解决方案适用于 PS2(win7) 和 PS3(win10),它基于 Windows Presentation Framework(WPF) 而不是 Windows 窗体,因为有了 WPF,我们可以使用 Data Binding 和 @987654322 @ 界面。我的工作基于 Trevor Jones 网络 How-To,并提供了一些工作技巧。
关于取消注册系统的问题,我已从 VB 翻译为 PS,Mike Ober 在SpiceWorks 的帖子中,他基于全局变量和可能的错误注册和取消注册系统的概念启发了我。
这是我的代码:
Add-Type -AssemblyName PresentationFramework,PresentationCore,WindowsBase
Function Create-WPFWindow {
Param($Hash)
# Create a window object
$Window = New-Object System.Windows.Window
$Window.Width = '600'
$Window.Height = '300'
$Window.Title = 'WPF-CONTROL'
$window.WindowStartupLocation = [System.Windows.WindowStartupLocation]::CenterScreen
$Window.ResizeMode = [System.Windows.ResizeMode]::NoResize
# Create a Label object
$Label = New-Object System.Windows.Controls.Label
$Label.Height = 40
$Label.HorizontalContentAlignment = 'Left'
$Label.VerticalContentAlignment = 'Center'
$Label.FontSize = 15
$Label.Content = 'Actividad:'
$Hash.Label = $Label
# Create a TextBlock object
$TextBlock = New-Object System.Windows.Controls.TextBlock
$TextBlock.Height = 150
$TextBlock.FontSize = 20
$TextBlock.TextWrapping = 'Wrap'
$Hash.TextBlock = $TextBlock
# Create a Button1 object
$Button1 = New-Object System.Windows.Controls.Button
$Button1.Width = 300
$Button1.Height = 35
$Button1.HorizontalContentAlignment = 'Center'
$Button1.VerticalContentAlignment = 'Center'
$Button1.FontSize = 20
$Button1.Content = 'Iniciar'
$Hash.Button1 = $Button1
# Assemble the window
$StackPanel1 = New-Object System.Windows.Controls.StackPanel
$StackPanel1.Margin = '150,20,5,5'
$StackPanel1.Orientation = 'Horizontal'
$StackPanel1.Children.Add($Button1)
$StackPanel2 = New-Object System.Windows.Controls.StackPanel
$StackPanel2.Margin = '5,5,5,5'
$StackPanel2.Orientation = 'Vertical'
$StackPanel2.Children.Add($Label)
$StackPanel2.Children.Add($TextBlock)
$StackPanel = New-Object System.Windows.Controls.StackPanel
$StackPanel.Margin = '5,5,5,5'
$StackPanel.Children.Add($StackPanel1)
$StackPanel.Children.Add($StackPanel2)
$Window.Content = $StackPanel
# Stop the service and release the resources
$Window.Add_Closing({
$Hash.On = $false
$global:p.BeginInvoke()
$global:p.Dispose()})
$Hash.Window = $Window
}
$Hash = [hashtable]::Synchronized(@{})
# Create a WPF window and add it to a Hash table
Create-WPFWindow $Hash | Out-Null
# Create a datacontext for the TextBlock, we add it to the synchronized $Hash to update the GUI from the FileSystemWatcher Event.
$DataContext = New-Object System.Collections.ObjectModel.ObservableCollection[Object]
$Text = [string]'Pulse el botón para iniciar el sistema.'
$DataContext.Add($Text)
$Hash.TextBlock.DataContext = $DataContext
$Hash.DataContext = $DataContext
$Hash.path='C:\POWERSHELL_PROJECT\Result'
# These two vars are for my needs, you can obviate them or delete
$Hash.urlLOGIN=''
$Hash.urlLOTE=''
$Hash.fileWatcher = $null
$Hash.LOG='C:\POWERSHELL_PROJECT\Result\LOG.log'
$Hash.firstEvent = $false
$Hash.On=$false
$Hash.msg=''
# Create and set a binding on the TextBlock object
$Binding = New-Object System.Windows.Data.Binding -ArgumentList '[0]'
$Binding.Mode = [System.Windows.Data.BindingMode]::OneWay
[void][System.Windows.Data.BindingOperations]::SetBinding($Hash.TextBlock,[System.Windows.Controls.TextBlock]::TextProperty, $Binding)
# Add an event for the Button1 click to Register FileSystemWatcher and Unregister it
$Hash.Button1.Add_Click({
if ($Hash.On -eq $true){
$Hash.On = $false
$Hash.Button1.Background = 'Green'
$Hash.Button1.Content = 'Iniciar'
}else{
$Hash.On = $true
$Hash.Button1.Background = 'Red'
$Hash.Button1.Content = 'Detener'
}
$p.BeginInvoke() | Out-Null
})
# Multithreading runspaces for FileSystemWatcher
$rs_dForm = [Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace()
$rs_dForm.ApartmentState = 'STA'
$rs_dForm.ThreadOptions = 'ReuseThread'
$rs_dForm.Open()
$rs_dForm.SessionStateProxy.SetVariable('Hash', $Hash)
$p = [PowerShell]::Create().AddScript({
Function global:OnFileSystemWatcherError {
FileEventListener -Path $Hash.path
}
# With simple function we can refresh the Textbox and Log
Function global:Refresh-WPF-and-LOG {
$Hash.DataContext[0] = $Hash.msg
echo $Hash.msg >> $Hash.LOG
}
Function global:FileEventListener ($Path){
if ($Hash.On){
$Hash.fileWatcher = New-Object System.IO.FileSystemWatcher
$Hash.fileWatcher.Path = $Path
$Hash.fileWatcher.Filter = '*.xml'
$Hash.fileWatcher.IncludeSubdirectories = $false
$Hash.fileWatcher.InternalBufferSize = 32768
$Hash.fileWatcher.EnableRaisingEvents=$true
Register-ObjectEvent -InputObject $Hash.fileWatcher -EventName Changed -SourceIdentifier File.Changed -Action {
$Global:t = $event
if (!$Hash.firstEvent){
try{
# For example you can:
$Hash.msg = '[' + $(Get-Date -Format u | foreach {$_ -replace ' ','-'}).ToString() + ']--' + $event.SourceEventArgs.Name
}catch{
$Hash.msg = '[' + $(Get-Date -Format u | foreach {$_ -replace ' ','-'}).ToString() + ']--' + $_.Exception.Message + ' ' + $_.Exception.ItemName
}finally{
Refresh-WPF-and-LOG
}
$Hash.firstEvent=$true
}else{
$Hash.firstEvent=$false
}
}
# With this Register we control the errors from the FileSystemWatcher system, and reinit it this case
Register-ObjectEvent -InputObject $Hash.fileWatcher -EventName Error -SourceIdentifier File.Error -Action {
$Global:t = $event
$Hash.On = $false
OnFileSystemWatcherError
}
$Hash.msg = '[' + $(Get-Date -Format u | foreach {$_ -replace ' ','-'}).ToString() + ']--' + 'Servicio INICIADO.'
}else{
if ( $Hash.fileWatcher -ne $null ){
$Hash.fileWatcher.EnableRaisingEvents=$false
Unregister-Event File.Changed
Unregister-Event File.Error
$Hash.fileWatcher.Dispose()
$Hash.fileWatcher=$null
$Hash.msg='[' + $(Get-Date -Format u | foreach {$_ -replace ' ','-'}).ToString() + ']--' + 'Sistema DETENIDO.'
}
}
Refresh-WPF-and-LOG
}
FileEventListener -Path $Hash.path
})
$p.Runspace = $rs_dForm
# Show the window
$Hash.Window.ShowDialog() | Out-Null
希望能帮到你。