用于生成后台作业报告的 PowerShell 切换按钮

问题描述 投票:0回答:1

我想创建一个

Generate-SummaryReports-CalculateAtIntervals
切换按钮,它是一个后台作业,可以像一个可以打开和关闭的开关,允许
Generate-SummaryReports-CalculateAtIntervals
像后台应用程序一样运行,但它仍然可以允许用户执行以下操作但目前我面临的问题是无论我如何触发
Function Toggle-ReportGeneration
它都不会触发
Generate-SummaryReports-CalculateAtIntervals
运行,但它会显示
"Report generation is now turned ON.1"
"Report generation is now turned ON.3"
。有什么办法可以修复或解决问题吗

功能切换-报告生成

$global:reportGenerationEnabled = $false
$global:reportJob = $null

# Function to toggle report generation on or off
Function Toggle-ReportGeneration {

    # Invert the current state of reportGenerationEnabled
    $global:reportGenerationEnabled = -not $global:reportGenerationEnabled

    if ($global:reportGenerationEnabled) {
        if ($global:reportJob -eq $null -or $global:reportJob.State -eq 'Completed') {
            Write-Host "Report generation is now turned ON.1"
            # If report generation is turned on, start the background job
            $global:reportJob = Start-Job -ScriptBlock {
                # Call the function directly within the background job
                param($baselineFilePath)
                while ($global:reportGenerationEnabled) {
                    Generate-SummaryReports-CalculateAtIntervals -baselineFilePath $baselineFilePath
                    Write-Host "Report generation is now turned ON.2"
                    Start-Sleep -Seconds 1  # Add a delay to prevent the loop from running too quickly
                }
            } -ArgumentList $global:baselineFilePath

            # Display the message outside the background job's script block
            Write-Host "Report generation is now turned ON.3"
        } else {
            Write-Host "Report generation is already running."
        }
    } else {
        Write-Host "Report generation is now turned OFF."
        # If report generation is turned off, stop the background job
        if ($global:reportJob -ne $null) {
            $global:reportJob | Stop-Job -PassThru | Remove-Job
            $global:reportJob = $null
        }
    }
}
Generate-SummaryReports-CalculateAtIntervals
Function Generate-SummaryReports-CalculateAtIntervals {
    param (
        [string]$baselineFilePath,
        [int]$lowSensitivityInterval = 15,     # Time interval for low sensitivity in seconds
        [int]$mediumSensitivityInterval = 10,  # Time interval for medium sensitivity in seconds
        [int]$highSensitivityInterval = 5      # Time interval for high sensitivity in seconds
    )
    Write-Host "Inside Generate-SummaryReports-CalculateAtIntervals function"

    # Define start time
    $startTime = Get-Date
    Write-host "1"
    # Infinite loop for continuous background job
    while ($true) {
        $currentTime = Get-Date

        # Calculate elapsed time since start
        $elapsedTime = $currentTime - $startTime

        # Calculate the number of intervals completed for each sensitivity level
        $lowIntervalsCompleted = [math]::Floor($elapsedTime.TotalSeconds / $lowSensitivityInterval)
        $mediumIntervalsCompleted = [math]::Floor($elapsedTime.TotalSeconds / $mediumSensitivityInterval)
        $highIntervalsCompleted = [math]::Floor($elapsedTime.TotalSeconds / $highSensitivityInterval)

        # Calculate the next scheduled time for each sensitivity level
        $nextLowReportTime = $startTime.AddSeconds(($lowIntervalsCompleted + 1) * $lowSensitivityInterval)
        $nextMediumReportTime = $startTime.AddSeconds(($mediumIntervalsCompleted + 1) * $mediumSensitivityInterval)
        $nextHighReportTime = $startTime.AddSeconds(($highIntervalsCompleted + 1) * $highSensitivityInterval)

        # Find the next earliest report time
        $nextReportTime = $nextLowReportTime
        if ($nextMediumReportTime -lt $nextReportTime) {
            $nextReportTime = $nextMediumReportTime
        }
        if ($nextHighReportTime -lt $nextReportTime) {
            $nextReportTime = $nextHighReportTime
        }

        # Wait until the next report time for the earliest sensitivity level
        $waitTime = $nextReportTime - $currentTime
        if ($waitTime.TotalMilliseconds -gt 0) {
            Start-Sleep -Milliseconds $waitTime.TotalMilliseconds
        }

        # Generate summary report for the sensitivity level that has reached its interval
        if ($nextReportTime -eq $nextLowReportTime) {
            # Log the start of the report generation
            Write-Output "Generating Low sensitivity summary report at $(Get-Date)" | Out-File -Append -FilePath "summary_reports.log"
            Generate-SummaryReport-AtIntervals -baselineFilePath $baselineFilePath -sensitivity "Low"
            # Log the completion of the report generation
            Write-Output "Low sensitivity summary report generation complete at $(Get-Date)" | Out-File -Append -FilePath "summary_reports.log"
        }
        if ($nextReportTime -eq $nextMediumReportTime) {
            # Log the start of the report generation
            Write-Output "Generating Medium sensitivity summary report at $(Get-Date)" | Out-File -Append -FilePath "summary_reports.log"
            Generate-SummaryReport-AtIntervals -baselineFilePath $baselineFilePath -sensitivity "Medium"
            # Log the completion of the report generation
            Write-Output "Medium sensitivity summary report generation complete at $(Get-Date)" | Out-File -Append -FilePath "summary_reports.log"
        }
        if ($nextReportTime -eq $nextHighReportTime) {
            # Log the start of the report generation
            Write-Output "Generating High sensitivity summary report at $(Get-Date)" | Out-File -Append -FilePath "summary_reports.log"
            Generate-SummaryReport-AtIntervals -baselineFilePath $baselineFilePath -sensitivity "High"
            # Log the completion of the report generation
            Write-Output "High sensitivity summary report generation complete at $(Get-Date)" | Out-File -Append -FilePath "summary_reports.log"
        }
    }
}
multithreading powershell jobs runspace
1个回答
0
投票

您的代码的主要问题是使用

Start-Job
,作业不在进程中,因此,不可能看到
$global:reportGenerationEnabled
被更新以停止该
while
循环。下一个问题是,由于前面提到的内容,作业永远不会知道
Generate-SummaryReports-CalculateAtIntervals
Generate-SummaryReport-AtIntervals
是什么。您可以使用
runspace
来完成此任务,因为它们在不同线程的同一进程中运行,但是您的代码将需要许多修改。我将分享一个最小的示例,说明您的代码如何使用它来工作排除之前提到的功能

$iss = [initialsessionstate]::CreateDefault2()
$iss.Commands.Add(
    [System.Management.Automation.Runspaces.SessionStateFunctionEntry]::new(
        'Generate-SummaryReports-CalculateAtIntervals',
        'definition for the function here'))
$iss.Commands.Add(
    [System.Management.Automation.Runspaces.SessionStateFunctionEntry]::new(
        'Generate-SummaryReport-AtIntervals',
        'definition for the function here'))

这两个函数都必须以一种或另一种方式传递到运行空间,有很多不同的方法来执行此操作,上面将函数添加到运行空间初始会话状态,但是为了简单起见,您可以在脚本内定义它们(在

.AddScript
内) ).

$script:reportGenerationEnabled = [System.Threading.ManualResetEventSlim]::new()
$script:reportJob = $null

# Function to toggle report generation on or off
function Toggle-ReportGeneration {
    # Invert the current state of reportGenerationEnabled
    if (-not $script:reportGenerationEnabled.IsSet) {
        $script:reportGenerationEnabled.Set()
    }
    else {
        $script:reportGenerationEnabled.Reset()
    }

    if ($script:reportGenerationEnabled.IsSet) {
        if (-not $script:reportJob -or $script:reportJob.iasyncresult.IsCompleted) {
            Write-Host 'Report generation is now turned ON.1'
            $iss = [initialsessionstate]::CreateDefault2()
            $iss.Commands.Add(
                [System.Management.Automation.Runspaces.SessionStateFunctionEntry]::new(
                    'Generate-SummaryReports-CalculateAtIntervals',
                    'definition for the function here'))
            $iss.Commands.Add(
                [System.Management.Automation.Runspaces.SessionStateFunctionEntry]::new(
                    'Generate-SummaryReport-AtIntervals',
                    'definition for the function here'))

            $rs = [runspacefactory]::CreateRunspace($Host, $iss)
            $rs.Open()
            $rs.SessionStateProxy.SetVariable('reportGenerationEnabled', $script:reportGenerationEnabled)

            $ps = [powershell]::Create().AddScript{
                # Call the function directly within the background job
                param($baselineFilePath)

                while ($reportGenerationEnabled.IsSet) {
                    Get-Random              # some output data for testing
                    Write-Host 'Report generation is now turned ON.2'
                    Start-Sleep -Seconds 1  # Add a delay to prevent the loop from running too quickly
                }
            }.AddParameter('baselineFilePath', $script:baselineFilePath)

            $ps.Runspace = $rs

            $script:reportJob = @{
                instance     = $ps
                iasyncresult = $ps.BeginInvoke()
            }

            # Display the message outside the background job's script block
            Write-Host 'Report generation is now turned ON.3'
        }
        else {
            Write-Host 'Report generation is already running.'
        }
    }
    else {
        Write-Host 'Report generation is now turned OFF.'
        # If report generation is turned off, stop the background job
        if ($script:reportJob) {
            try {
                $script:reportJob.instance.EndInvoke($reportJob.iasyncresult)
                if ($reportJob.instance.HadErrors) {
                    foreach ($e in $reportJob.instance.Streams.Error) {
                        Write-Error $e
                    }
                }
                $script:reportJob = $null
            }
            finally {
                if ($rs) { $rs.Dispose() }
                if ($ps) { $ps.Dispose() }
            }
        }
    }
}

Toggle-ReportGeneration
© www.soinside.com 2019 - 2024. All rights reserved.