【问题标题】:Launch a script in an infinite loop with the possibility to stop it在无限循环中启动脚本,并有可能停止它
【发布时间】:2019-10-24 07:36:24
【问题描述】:

我正在尝试从 PowerShell 开发一个表单,用于控制和监视无限循环中脚本(在我的例子中是 vbs,但它可以是任何其他)的执行。

我是 PowerShell 的新手,所以我对代码结构表示歉意。英语不是我的佟妈,所以我也为错误道歉。

我使用 PowerShell 是因为我希望我的表单在 Windows 通知任务栏中有一个图标和一个菜单。到目前为止,我唯一得到的是图标,但我也会得到菜单。这不是问题。

我需要我的表单,在单击按钮后,每 3 秒在无限循环中启动 VisualBasic 脚本,直到我再次按下按钮(或其他按钮)。但我得到的是无限的无法停止的循环,因为一旦按下按钮,表单就会冻结,因为它在 do while 循环内。

有谁知道我该如何解决我的问题?主要目的是每 3 秒启动一次相同的 VBS,直到我希望它停止...

作为测试,我尝试使用我的 PowerShell 程序启动的 VisualBasic 脚本是一个简单的 MsgBox,我称之为“hello.vbs”:

MsgBox "hello world"

为此,我创建了 3 个代码文件。它以一个名为“program.vbs”的 VisualBasic 脚本开始,该脚本调用 PowerShell 命令:

Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "C:\Users\XXX\Desktop\Program\program.bat" & Chr(34), 0
Set WshShell = Nothing

其次,它会执行一个名为“program.bat”的 bat,它调用 PowerShell 脚本:

powershell -executionpolicy bypass -file "C:\Users\XXX\Desktop\Program\program.ps1"

最后,名为“program.ps1”的主脚本创建了带有控制和监控指令的表单:

[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

$functions = {
    function Test() 
    {
        do
        {
            Invoke-Expression "C:\Users\XXX\Desktop\Programita\hello.vbs"
            Start-Sleep -Seconds 2
        }while ($Label2.Text -ne 0)
    }
}

Function Principal {
    $ProgIcon1 = "C:\Users\XXX\Desktop\Program\icon1.ico"
    $ProgIcon2 = "C:\Users\XXX\Desktop\Program\icon2.ico"
    $Form = New-Object System.Windows.Forms.Form
    $ContextMenuProg = New-Object System.Windows.Forms.ContextMenu
    $Menu = New-Object System.Windows.Forms.MenuItem
    $Icon1 = New-Object System.Drawing.Icon ($ProgIcon1)
    $Icon2 = New-Object System.Drawing.Icon ($ProgIcon2)
    $Label1 = New-Object System.Windows.Forms.Label
    $Label2 = New-Object System.Windows.Forms.Label
    $ComButt1 = New-Object System.Windows.Forms.Button
    $ComButt2 = New-Object System.Windows.Forms.Button
    $objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon

    $Form.Text = "Application stopped"

    $Form.Controls.Add($Label1)
    $Form.Controls.Add($Label2)
    $Form.Controls.Add($ComButt1)
    $Form.Controls.Add($ComButt2)

    $Form.Width = 260
    $Form.Height = 180
    $Form.FormBorderStyle = "FixedSingle"
    $Form.MaximizeBox = $False
    $Form.StartPosition = "CenterScreen"
    $Form.Icon = $Icon2

    $Label1.Text = "My first form with icon inside task bar"
    $Label1.Left = 30
    $Label1.Top = 20
    $Label1.AutoSize = $True

    $ComButt1.Text = "Start application"
    $ComButt1.Left = 12
    $ComButt1.Top = 100
    $ComButt1.Width = 102

    $ComButt2.Text = "Close application"
    $ComButt2.Left = 124
    $ComButt2.Top = 100
    $ComButt2.Width = 102
    $ComButt2.Add_Click({
        [System.Windows.Forms.DialogResult]::Cancel
    })
    $ComButt2.DialogResult = [System.Windows.Forms.DialogResult]::Cancel

    $Label2.Text=0
    $ComButt1.Add_Click(
        {
            if ($Label2.Text -eq 0)
            {
                $Form.Text = "Active application"
                $ComButt1.Text = "Application paused"
                $Label2.Text = 1
                $objNotifyIcon.Icon = $ProgIcon1
                $Form.Icon = $ProgIcon1
                #####
                Start-Job -InitializationScript $functions -ScriptBlock {Test} -Name MyJob
                #####
            }else {
                $Form.Text = "Application stopped"
                $ComButt1.Text = "Launch application"
                $Label2.Text = 0
                $objNotifyIcon.Icon = $ProgIcon2
                $Form.Icon = $ProgIcon2
                Remove-Job -Name MyJob -Force
            }
        }
    )

    $Label2.Left = 30
    $Label2.Top = 50
    $Label2.AutoSize = $True

    $objNotifyIcon.Icon = $ProgIcon2
    $objNotifyIcon.ContextMenu = $ContextMenuProg

    $objNotifyIcon.Visible = $True
    $Form.ShowDialog()
    $objNotifyIcon.Visible = $False
}

Principal

【问题讨论】:

  • 你可以使用Start-Job。因此,您的 gui 在作业运行时不会冻结。您可以使用 Stop-Job / Remove-Job 停止/删除作业
  • 嗯嗯。看起来很好。我做了一些实际可行的事情,但我不确定代码是否正确实现,因为我必须使用补码'-Force'
  • 您可以添加更新后的代码吗?
  • 首先将函数'Test'封装成一种函数变量:$functions = { function Test (){...}}
  • 请将您的新代码添加到您的初始帖子中,否则我们将在这里获得大量 cmets。在删除作业之前,您应该使用 Stop-Job 停止它。

标签: winforms powershell loops


【解决方案1】:

你可以使用Start-Job。因此,您的 gui 在作业运行时不会冻结。您可以使用 Stop-Job / Remove-Job` 停止/删除作业。

【讨论】:

    【解决方案2】:

    试试这个:

    Class Surrounding_Class
        Private Stop_Flag As Boolean = False
    
        Private Sub Btn_Handler(ByVal Sender As Object, ByVal e As EventArgs)
            Stop_Flag = Not Stop_Flag
            DoAction()
        End Sub
    
        Private Sub DoAction()
            Do
            Loop While Stop_Flag = False
        End Sub
    End Class
    

    【讨论】:

    • 我真的不知道如何在我的中使用/插入这段代码。我在 PowerShell 中出现的问题,而不是在 VisualBasic 中
    • 我的错。尽管主体可能仍适用于 PowerShell,即。使用变量来控制循环。我不确定它具体是如何工作的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-04
    • 2011-10-31
    • 1970-01-01
    • 1970-01-01
    • 2022-12-02
    • 1970-01-01
    相关资源
    最近更新 更多