【发布时间】:2022-12-16 06:21:36
【问题描述】:
我有一个相当大的 PowerShell 脚本,我已将其分成两个单独的脚本。第一个脚本以调用异步函数结束,然后退出。
该函数检查在前面的脚本中生成的电子邮件导出的状态,执行一个 WHILE 循环,它每六十秒调用一次 Google 以查看导出是否准备就绪。导出准备就绪后,它会更新几个 SQL 数据库,我的第二个脚本知道接管。
当我在 shell/控制台中运行“第一个脚本”时,这 100% 的时间都有效。但我已经开始注意到,当我的计划任务在任务计划程序中被触发时……什么也没有发生。我有大量的日志记录,所以我知道参数正在被发送到异步函数,但它似乎只是弹出而不是继续循环遍历 WHILE 并每六十秒检查一次。
我觉得我已经在这里进行了谷歌搜索的尽职调查,但是......我是否缺少任务计划程序作业以确保包含 WHILE 循环的函数能够正常运行?
在下方编辑
为了更好地解释我在做什么,我将包括从我的函数中剥离的代码以及从下面的主脚本调用函数。
首先,调用“script_01”末尾的函数。
# Let's send the Google Vault export information over to our function.
Try {
$VaultParameters = @{
employee_name = "$employee_name"
export_name = "$export_name"
sql_id = "$sql_id"
vault_status_id = "$vault_status_id"
}
VaultExport @VaultParameters
$LoggingParameters = @{
logfile = "C:\script_logs\log.log"
log = "INFO: Sent the Google Vault export information over to our async function."
}
EventLogging @LoggingParameters
} Catch {
$LoggingParameters = @{
logfile = "C:\script_logs\log.log"
log = "ERROR: Could not send the Google Vault export information over to our async function.`n$_"
}
EventLogging @LoggingParameters
}
现在是功能本身。它很大...
function VaultExport {
param (
[cmdletbinding()]
[parameter()]
[string]$employee_name,
[parameter()]
[string]$export_name,
[parameter()]
[string]$sql_id,
[parameter()]
[string]$vault_status_id
)
$scriptBlock = {
param ($employee_name,$export_name,$sql_id,$vault_status_id)
Import-Module SimplySQL
$logfile = "C:\script_logs\log.log"
$now = (Get-Date).tostring("MM-dd-yyyy hh:mm:ss")
# Let's define our MySQL database credentials for later use.
# DEFINING SQL CREDS HERE
# Let's generate secure credentials for our MySQL 'terms' db.
# GENERATING SECURE CREDS HERE
# And now we'll connect to our SQL db...
# CONNECTING TO SQL HERE
$vault_ready = "no"
Add-Content $logfile "$now INFO: Beginning the WHILE loop while $export_name completes..."
while ($vault_ready -eq "no") {
$vault_status = gam info export "Email Exports" "$export_name"
$vault_status = $vault_status -Match "COMPLETED"
$vault_status = $vault_status -split(": ")
$vault_status = $vault_status[1]
if ($vault_status -eq "COMPLETED") {
$vault_ready = "yes"
$completed = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Invoke-SqlUpdate -Query "UPDATE ``table`` SET ``vault_status`` = '$vault_status', ``vault_completed`` = '$completed' WHERE ``id`` = '$vault_status_id'"
Invoke-SqlUpdate -Query "UPDATE ``table`` SET ``vault_status`` = '1' WHERE ``id`` = '$sql_id'"
$now = (Get-Date).tostring("MM-dd-yyyy hh:mm:ss")
Add-Content $logfile "$now INFO: $export_name is ready to download. Updated vault_status in our dbs."
} else {
$vault_status = gam info export "Email Exports" "$export_name"
$vault_status = $vault_status -Match "IN_PROGRESS"
$vault_status = $vault_status -split(": ")
$vault_status = $vault_status[1]
Invoke-SqlUpdate -Query "UPDATE ``table`` SET ``vault_status`` = '$vault_status' WHERE ``id`` = '$vault_status_id'"
$now = (Get-Date).tostring("MM-dd-yyyy hh:mm:ss")
Add-Content $logfile "$now INFO: $export_name is not yet ready: ($vault_status). Checking again in sixty seconds."
Start-Sleep 60
}
}
}
Start-Job -ScriptBlock $scriptBlock -ArgumentList @($employee_name,$export_name,$sql_id,$vault_status_id)
}
exit
【问题讨论】:
-
如果您从 cmd 调用您的脚本,它会起作用吗?如果你从现有的 Powershell 会话运行它,我假设你在说 shell / 控制台时这样做,那么会话将保持打开状态并且异步过程将继续。从任务调度程序中,您的异步调用已完成,但由于它在另一个线程上,您需要保持主线程打开(例如:While / Start-Sleep -miliseconds 10 until the async function complete)。如果不这样做,主线程将在运行时退出并杀死子线程和异步函数。至少,这是我从你的帖子中得到的感觉。
-
好的。超级有帮助……有点像我“不善于解释”的大脑在想什么。所以我需要找出当任务计划程序触发我的脚本时如何保持主线程/外壳打开......
标签: powershell function asynchronous windows-task-scheduler