user-interface - 在脚本运行时刷新表单上的数据的后台作业?

标签 user-interface powershell timer powershell-2.0 powershell-3.0

希望有大侠帮帮我!

几天前,我正在使用 Powershell 工具,该工具在屏幕角落显示仪表板,以提供计算机的一些网络“实时”诊断。此仪表板可以在通知区域中最小化。

首先,我创建了一个获取诊断信息并在表单上显示状态的函数。我试图用计时器刷新数据(参见:Real Time Data With Powershell GUI)。

问题是我的函数执行时间太长,它卡住了界面。所以表单上的按钮不再可用……(参见:Mouse event don't work after first timer Tick)。

现在,我尝试使用后台作业。我的想法是在循环模式下启动一个工作,并在一个计时器间隔内获取他的状态。

首先,Job 无法调用在我的主脚本中声明的函数(第 361 行)。我知道我可以使用全局和/或不使用函数,而是直接在 ScriptBlock 上编写代码但是......即使这样,我也不知道如何让工作循环并按间隔获取他的状态(第 368 行)…

你可以看到我并没有真正在 PowerShell 和 GUI 中进行过实验......我已经有一段时间没有开发它了,它是用另一种语言......

预先感谢您的帮助

如果你想运行它,我已经在这里上传了图像文件夹:
https://omerta.is/2A1L

下面是我的代码

 ####################################### FUNCTIONS   ########################################

#Get diagnostics status
function GetStatus
{

    #Create a return table
    [hashtable]$Return = @{}

    ###Test LAN adapter###
    $EthernetAdapter = (Get-WMIObject Win32_NetworkAdapter | Select Name, NetConnectionStatus | Where Name -like "*Gigabit*")

    If ($EthernetAdapter -ne $null)
    {
        If ($EthernetAdapter.NetConnectionStatus -eq 2)
            {$Return.LANOnStatus = $True}
        else
            {$Return.LANOnStatus = $False}
    }
    else
    {
        $Return.LANOnStatus = $False
    }



    ###Test Wi-Fi adapter###
    $WiFiAdapter = (Get-WMIObject Win32_NetworkAdapter | Select Name, NetConnectionStatus | Where Name -like "*Wireless*")

    If ($WiFiAdapter -ne $null)
    {
        If ($WiFiAdapter.NetConnectionStatus -eq 2)
            {$Return.WiFiOnStatus = $True}
        else
            {$Return.WiFiOnStatus = $False}
    }
    else
    {
        $Return.WiFiOnStatus = $False
    }



    ###Test Network (Default Gateway Reachable)###
    $DefaultGateway = (Get-WmiObject -Class Win32_IP4RouteTable | where { $_.destination -eq '0.0.0.0' -and $_.mask -eq '0.0.0.0'} | Sort-Object metric1 | select nexthop, metric1, interfaceindex).nexthop

    If ($DefaultGateway -ne $null)
    {
        If (Test-Connection -ComputerName $DefaultGateway -Count 1 -TTL 4 -Quiet)
            {$Return.NetworkStatus = $True}
        else
            {$Return.NetworkStatus = $False}
    }   
    else 
    {
        $Return.NetworkStatus = $False
    }          


    #Test Internet connection
    $GoogleWebSite = "www.google.com"

    Try
        {$Return.GoogleStatus = Test-Connection -ComputerName $GoogleWebSite -Count 1 -TTL 64 -Quiet}
    Catch
        {$Return.GoogleStatus = $False}


    ###DontReplyToo###
    $DontReplyTooWebSite = "mdm.pictet.com"

    Try
        {$Return.DontReplyTooStatus = Test-Connection -ComputerName $DontReplyTooWebSite -Count 1 -TTL 64 -Quiet}
    Catch
        {$Return.DontReplyTooStatus = $False}


    ###DONT REPLY###
    $DontReplyWebsite = "www.idontreply.com"

    Try
        {$Return.DontReplyStatus = Test-Connection -ComputerName $DontReplyWebsite -Count 1 -TTL 64 -Quiet}
    Catch
        {$Return.DontReplyStatus = $False}       


    #Return the table
    Return $Return

}


########################################### EVENTS ###########################################


#Manual Synchronization
function ManualSync
{
    Sync-Content

}


#Open Browser from dashboard
function Open-Browser
{
    &($BrowserExe)      
}


#Open a help message on click on help icon
function Open-Help($HelpText)
{

    [System.Windows.Forms.MessageBox]::Show($HelpText,"Hotlines",0,32)
}


#Close Dashboard form on click on minimize icon
function Minimize-Dashboard
{

    #Close Dashboard on click minimize
    $Form.WindowState = "Minimize"
    $Form.Visible = $False
    $objNotifyIcon.Visible = $True 

    #!!!!! TO CHECK !!!!!
    Wait-Event -Timeout 15 -SourceIdentifier NotifyIcon_Event
    Remove-Event -SourceIdentifier NotifyIcon_Event

}


#Open Dashboard form on double click on agent icon in notification area
function OpenDashboard
{

    #Open Dashboard on double-click
    $Form.Visible = $True
    $Form.WindowState = "Normal"

}

######################################### ASSEMBLIES #########################################


[void] [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")    
[void] [Reflection.Assembly]::LoadWithPartialName("System.Drawing")  
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Timers")
[void] [System.Windows.Forms.Application]::EnableVisualStyles()


######################################### VAR & CONST ########################################

#Screen placement
$Screen = [system.windows.forms.screen]::PrimaryScreen
$FormPos = $Screen.Bounds.Width - 160

#Dashboard Timer
$Timer = New-Object 'System.Windows.Forms.Timer'
$Timer.Interval = 3000

#Home directory of the program
$HomeDir = Split-Path $script:MyInvocation.MyCommand.Path

#Dashboard Images
$Background = [system.drawing.image]::FromFile("$HomeDir\img\interface.png")
$GreenLight = [system.drawing.image]::FromFile("$HomeDir\img\greenlight.png")
$RedLight = [system.drawing.image]::FromFile("$HomeDir\img\redlight.png")
$SyncImg = [system.drawing.image]::FromFile("$HomeDir\img\sync.png")
$BrowserImg = [system.drawing.image]::FromFile("$HomeDir\img\browser.png")
$HelpImg = [system.drawing.image]::FromFile("$HomeDir\img\help.png")
$MinimizeImg = [system.drawing.image]::FromFile("$HomeDir\img\minimize.png")

#Agent Images
$IconStd = New-Object system.drawing.icon ("$HomeDir\img\icon.ico")
$IconFocus = New-Object system.drawing.icon ("$HomeDir\img\icon_focus.ico")

#Log files
$LogLastSync = ("$HomeDir\Logs\LastSync.log")
$LogSyncAgent = ("$HomeDir\Logs\SyncAgentError.log")

#Browser Module
$BrowserExe = "$HomeDir\bin\Browser.exe"

#Free File Sync Module
$SyncAgentExe = "$HomeDir\bin\SyncAgent.exe"
$SyncJob = "$HomeDir\bin\SyncSettings.xml"

#Strings
$HelpText = "Hotline: 432423432423423"


########################################### FORMS ###########################################


#Dashboard Windows Forms
$Form = New-Object System.Windows.Forms.Form
$Font = New-Object System.Drawing.Font("Arial Unicode MS",10,[System.Drawing.FontStyle]::Bold)
$Lb_LANOn = New-Object System.Windows.Forms.Label
$Lb_WiFiOn = New-Object System.Windows.Forms.Label
$Lb_Network = New-Object System.Windows.Forms.Label
$Lb_Google = New-Object System.Windows.Forms.Label
$Lb_DontReplyToo = New-Object System.Windows.Forms.Label
$Lb_DontReply = New-Object System.Windows.Forms.Label
$Pb_LANOn = New-Object System.Windows.Forms.PictureBox
$Pb_WiFiOn = New-Object System.Windows.Forms.PictureBox
$Pb_Network = New-Object System.Windows.Forms.PictureBox
$Pb_Google = New-Object System.Windows.Forms.PictureBox
$Pb_DontReplyToo = New-Object System.Windows.Forms.PictureBox
$Pb_DontReply = New-Object System.Windows.Forms.PictureBox
$Pb_Sync = New-Object System.Windows.Forms.PictureBox
$Pb_Browser = New-Object System.Windows.Forms.PictureBox
$Pb_Help = New-Object System.Windows.Forms.PictureBox
$Pb_Minimize = New-Object System.Windows.Forms.PictureBox

#Agent Windows Form
$objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon
$objNotifyIcon.Add_Click({OpenDashboard})
Register-ObjectEvent $objNotifyIcon Click NotifyIcon_Event


#Dashboard Interface Generation
$Form.Size = '150, 220'
$Form.FormBorderStyle = 'None'
$Form.Name = "Form"
$Form.StartPosition = 'Manual'
$Form.Location = $FormPos.ToString()+', 10'
$Form.Text = "Dashboard"
$Form.Font = $Font
$Form.BackgroundImage = $Background
$Form.BackgroundImageLayout = "None"
$Form.TransparencyKey = "White"
$Form.BackColor = "White"
#$Form.Opacity = '.85'

$Form.Controls.Add($Lb_LANOn)
$Lb_LANOn.Location = '10, 30'
$Lb_LANOn.Size = '75, 20'
$Lb_LANOn.Text = "LAN On"
$Lb_LANOn.ForeColor = 'Gray'
$Lb_LANOn.BackColor = "Transparent"

$Form.Controls.Add($Lb_WiFiOn)
$Lb_WiFiOn.Location = '10, 55'
$Lb_WiFiOn.Size = '75, 20'
$Lb_WiFiOn.Text = "Wi-Fi On"
$Lb_WiFiOn.ForeColor = 'Gray'
$Lb_WiFiOn.BackColor = "Transparent"

$Form.Controls.Add($Lb_Network)
$Lb_Network.Location = '10, 80'
$Lb_Network.Size = '75, 20'
$Lb_Network.Text = "Network"
$Lb_Network.ForeColor = 'Gray'
$Lb_Network.BackColor = "Transparent"

$Form.Controls.Add($Lb_Google)
$Lb_Google.Location = '10, 105'
$Lb_Google.Size = '75, 20'
$Lb_Google.Text = "Google"
$Lb_Google.ForeColor = 'Gray'
$Lb_Google.BackColor = "Transparent"

$Form.Controls.Add($Lb_DontReplyToo)
$Lb_DontReplyToo.Location = '10, 130'
$Lb_DontReplyToo.Size = '75, 20'
$Lb_DontReplyToo.Text = "DontReplyToo"
$Lb_DontReplyToo.ForeColor = 'Gray'
$Lb_DontReplyToo.BackColor = "Transparent"

$Form.Controls.Add($Lb_DontReply)
$Lb_DontReply.Location = '10, 155'
$Lb_DontReply.Size = '75, 20'
$Lb_DontReply.Text = "Dont Reply"
$Lb_DontReply.ForeColor = 'Gray'
$Lb_DontReply.BackColor = "Transparent"

$Form.Controls.Add($Pb_LANOn)
$Pb_LANOn.Location = '115, 33'
$Pb_LANOn.Size = '15, 15'
$Pb_LANOn.Image = $RedLight
$Pb_LANOn.BackColor = "Transparent"

$Form.Controls.Add($Pb_WiFiOn)
$Pb_WiFiOn.Location = '115, 58'
$Pb_WiFiOn.Size = '15, 15'
$Pb_WiFiOn.Image = $RedLight
$Pb_WiFiOn.BackColor = "Transparent"

$Form.Controls.Add($Pb_Network)
$Pb_Network.Location = '115, 83'
$Pb_Network.Size = '15, 15'
$Pb_Network.Image = $RedLight
$Pb_Network.BackColor = "Transparent"

$Form.Controls.Add($Pb_Google)
$Pb_Google.Location = '115, 108'
$Pb_Google.Size = '15, 15'
$Pb_Google.Image = $RedLight
$Pb_Google.BackColor = "Transparent"

$Form.Controls.Add($Pb_DontReplyToo)
$Pb_DontReplyToo.Location = '115, 133'
$Pb_DontReplyToo.Size = '15, 15'
$Pb_DontReplyToo.Image = $RedLight
$Pb_DontReplyToo.BackColor = "Transparent"

$Form.Controls.Add($Pb_DontReply)
$Pb_DontReply.Location = '115, 158'
$Pb_DontReply.Size = '15, 15'
$Pb_DontReply.Image = $RedLight
$Pb_DontReply.BackColor = "Transparent"

#Toolbar

$Form.Controls.Add($Pb_Sync)
$Pb_Sync.Location = '20, 195'
$Pb_Sync.Size = '20, 20'
$Pb_Sync.Image = $SyncImg
$Pb_Sync.BackColor = "Transparent"
$Pb_Sync.Add_Click({Sync-Content})

$Form.Controls.Add($Pb_Browser)
$Pb_Browser.Location = '51, 195'
$Pb_Browser.Size = '20, 20'
$Pb_Browser.Image = $BrowserImg
$Pb_Browser.BackColor = "Transparent"
$Pb_Browser.Add_Click({Open-Browser})

$Form.Controls.Add($Pb_Help)
$Pb_Help.Location = '82, 195'
$Pb_Help.Size = '20, 20'
$Pb_Help.Image = $HelpImg
$Pb_Help.BackColor = "Transparent"
$Pb_Help.Add_Click({Open-Help($HelpText)})

$Form.Controls.Add($Pb_Minimize)
$Pb_Minimize.Location = '113, 195'
$Pb_Minimize.Size = '20, 20'
$Pb_Minimize.Image = $MinimizeImg
$Pb_Minimize.BackColor = "Transparent"
$Pb_Minimize.Add_Click({Minimize-Dashboard})

   ########## MAIN

#Status Init
#$Status = GetStatus 

#Create the Status Background Job 
Start-Job -Name "jobGetStatus" -ScriptBlock {$Status = GetStatus} #function not recognized by Background Job

#Wait for job result
While (Get-Job -Name "jobGetStatus" | where { $_.State -eq "Running" })
    {Start-Sleep 1}

#Get Status on Timer Tick
$Timer.Add_Tick({Get-Job -Name "jobGetStatus" | Receive-Job}) #job not updated

#Display new status on tick
$Timer.Add_Tick({
                        #LAN
                        If ($Status.LANOnStatus -eq $True)
                            {$Pb_LANOn.Image = $GreenLight}
                        else
                            {$Pb_LANOn.Image = $RedLight}

                        #WIFI
                        If ($Status.WiFiOnStatus -eq $True)
                            {$Pb_WiFiOn.Image = $GreenLight}
                        else
                            {$Pb_WiFiOn.Image = $RedLight}

                        #NETWORK
                        If ($Status.NetworkStatus -eq $True)
                            {$Pb_Network.Image = $GreenLight}
                        else
                            {$Pb_Network.Image = $RedLight}

                        #GOOGLE
                        If ($Status.GoogleStatus -eq $True)
                            {$Pb_Google.Image = $GreenLight}
                        else
                            {$Pb_Google.Image = $RedLight}

                        #DontReplyToo
                        If ($Status.DontReplyTooStatus -eq $True)
                            {$Pb_DontReplyToo.Image = $GreenLight}
                        else
                            {$Pb_DontReplyToo.Image = $RedLight}            

                        #BING
                        If ($Status.DontReplyStatus -eq $True)
                            {$Pb_DontReply.Image = $GreenLight}
                        else
                            {$Pb_DontReply.Image = $RedLight}         

})

#Start Timer
$Timer.Enabled = $True

#Agent Init
$objNotifyIcon.Icon = $IconStd
$objNotifyIcon.Text = "Dashboard"
$objNotifyIcon.Visible = $True 

#Show Interface
$Form.ShowDialog() 

  ############## END

最佳答案

不错的小工具。

我删除了对 Job 的所有引用,并将作业中的代码添加到 Tick 本身中:

$Timer.Add_Tick({
   $Status = GetStatus
   #LAN
   If ($Status.LANOnStatus -eq $True)
      {$Pb_LANOn.Image = $GreenLight}
   else
      {$Pb_LANOn.Image = $RedLight}
   ...
})

由于您提到该功能花费了太多时间,因此我还将 Tick 间隔从 3 秒增加到 10 秒。这在我的 PC 上似乎运行良好。

关于user-interface - 在脚本运行时刷新表单上的数据的后台作业?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33639213/

相关文章:

java - Android 中的 slider 控件... SeekBar 真的是我最好/唯一的选择吗?

python - 如何更改 Powershell 中的路径?

powershell - 逐行处理HereString

multithreading - 如何多线程 PowerShell Ping 脚本

javascript - 超时功能完成后如何调用功能?

Android创建一个每秒递增一次的变量

java - TextView 不使用 Html.fromHtml 应用 HTML 样式

javascript - 带悬垂的jquery滑动抽屉

javascript - 在 HTML/CSS 中创建 float 标签

java - 如何禁用 Wildfly 10 中的计时器服务?