从Windows任务计划程序PowerShell脚本无法正常工作

概述:我有一个脚本,用于通过WMI在SCCM中查询新的应用程序请求。 当在PowerShell控制台中手动启动时(无论是否boost,无关紧要),该脚本都可以正常工作。 我需要通过任务计划程序运行脚本。 目前设置为使用pipe理员凭据运行,并选中“以最高权限运行”checkbox。

问题:无法从Windows Server 2008 R2中的任务计划程序正确运行。 没有报告错误(任务计划程序返回错误代码0),但它似乎没有继续行,读取:

$GetAppRequest = Get-WmiObject -Class SMS_UserApplicationRequest -Namespace root/SMS/site_$SiteCode | Where-Object {$_.CurrentState -like "1"} | ForEach-Object { 

这是完整的脚本:

 #Hard-coded variables $SiteCode = "MySiteCode" $ComputerName = "My-SCCM-Server" $GUIDFilePath = "C:\Scripts\SCCM\GUIDList.txt" $FilePath = "C:\Scripts\SCCM" $smtpServers = "smtp1.domainname.com","smtp2.domainname.com" $reliableSmtpServer = $null $logpath = "C:\Scripts\SCCM\RequestLog.txt" #logging functionality function log($message, $type){ $date = get-date $string = "$date $type : $message" | Out-File $logpath -Append } #does log exist? if (gi -Path $logpath -ErrorAction SilentlyContinue){ #yep, the log exists! $logContent = cat $logpath log -message "Script called and log opened for writing." -type "Info" } else { #nope, the log doesn't exist, let's make one. write "Can't find log file, creating a new one." $newFileResult = New-Item -Path $logpath -ItemType File -ErrorAction Stop if ($newFileResult.Exists){ log -message "new log file created" -type "Info" } #end if } #end else #Email variables $from = "no.reply@domainname.com" $to = "sccm-admin@domainname.com" $subject = "New SCCM Application Approval Requests" #Determine which SMTP to use. $smtpServers | ForEach-Object { if ($reliableSmtpServer -eq $null){ if (Test-Connection -ComputerName $_ -ErrorAction SilentlyContinue){ write "Reliable SMTP server found: $_" $reliableSmtpServer = $_ } #end if test-connection } #end if reliableSmtpServer exists } #end foreach SMTP server if ($reliableSmtpServer){ log -message "Reliable SMTP server found, $reliableSmtpServer" -type "Info" } else { log -message "No reliable SMTP server could be found" -type "Error" } #Get the entries from GUIDList.txt if ($GetGUID = Get-Content -Path $GUIDFilePath -ErrorVariable guidReadError { write "Successfully read $GUIDFilePath" log -message "Successfully read $GUIDFilePath" -type "Info" } else { Write-Error -Message "Couldn't read GUIDfile..." log -message "Failed to read GUIDFile" -type "Error" } #Get all Application Requests with a CurrentState of "1" log -message 'Attempting to get all Application Requests with a CurrentState of 1' -type "Info" $GetAppRequest = Get-WmiObject -Class SMS_UserApplicationRequest -Namespace root/SMS/site_$SiteCode | Where-Object {$_.CurrentState -like "1"} | ForEach-Object { log -message "App found, $_.Application" -type "Info" if ($GetGUID -contains $_.RequestGuid) { Write-Host "Application request $($_.RequestGuid) already present" log -message "Application request $($_.RequestGuid) already present" -type "Info" } else { $appUser = $_.User $appName = $_.Application $appComment = $_.Comments $Body = @" Application request: $appName User: $appUser Comment: $appComment "@ #This row can't contain any blank spaces or tabs log -message "New record found: $appUser, $appName, $appComment" -type "Info" #Email configuration Send-MailMessage -SmtpServer $reliableSmtpServer -From $from -To $to -Subject $subject -Body $body -ErrorVariable mailError if (!($mailError)){ write "Message successfully sent to : $to" log -message "Message successfully sent to : $to" -type "Info" } else { Write-Error -message "Failed to send email!" log -message "Failed to send email!" -type "Error" } #end else #Append the current objects GUID to GUIDList.txt Write "Appending $($_.RequestGUID) to $GUIDFilePath" log -message "Appending $($_.RequestGUID) to $GUIDFilePath" -type "Info" $_.RequestGuid | Out-File $GUIDFilePath -Append } #end else statement } #end forEach #Remove the GUIDList.txt file and re-create it when there's more than 100 entries $GUIDCount = $GetGUID.Count if ($GUIDCount -gt 100) { log -message "Greater than 100 GUID entries, clearing list." -type "Info" Get-Item $GUIDFilePath | Remove-Item New-Item -Path $FilePath -Name GUIDList.txt -ItemType file } #Create a new log once the log file exceeds 1000 lines. $logCount = $logContent.Count if ($logCount -gt 1000) { log -message "Log file is too long, removing log" -type "Warning" Remove-Item $logpath } 

这是预定的任务XML:

 <?xml version="1.0" encoding="UTF-16"?> <Task version="1.3" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> <RegistrationInfo> <Date>2014-05-09T17:10:48.6636926</Date> <Author>domainname\myUserAccount</Author> <Description>Runs a script located at C:\scripts\SCCM to determine if there are any new application requests and notify IT staff via Email.</Description> </RegistrationInfo> <Triggers> <TimeTrigger> <Repetition> <Interval>PT15M</Interval> <StopAtDurationEnd>false</StopAtDurationEnd> </Repetition> <StartBoundary>2014-05-09T17:12:04</StartBoundary> <ExecutionTimeLimit>PT1H</ExecutionTimeLimit> <Enabled>true</Enabled> </TimeTrigger> </Triggers> <Principals> <Principal id="Author"> <UserId>domain\AdminAccount</UserId> <LogonType>Password</LogonType> <RunLevel>HighestAvailable</RunLevel> </Principal> </Principals> <Settings> <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries> <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries> <AllowHardTerminate>true</AllowHardTerminate> <StartWhenAvailable>false</StartWhenAvailable> <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable> <IdleSettings> <StopOnIdleEnd>true</StopOnIdleEnd> <RestartOnIdle>false</RestartOnIdle> </IdleSettings> <AllowStartOnDemand>true</AllowStartOnDemand> <Enabled>true</Enabled> <Hidden>false</Hidden> <RunOnlyIfIdle>false</RunOnlyIfIdle> <DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession> <UseUnifiedSchedulingEngine>false</UseUnifiedSchedulingEngine> <WakeToRun>false</WakeToRun> <ExecutionTimeLimit>P3D</ExecutionTimeLimit> <Priority>7</Priority> </Settings> <Actions Context="Author"> <Exec> <Command>powershell.exe</Command> <Arguments>-noprofile -file "C:\scripts\sccm\Notify.ps1"</Arguments> </Exec> </Actions> </Task> 

Solutions Collecting From Web of "从Windows任务计划程序PowerShell脚本无法正常工作"

你的意思是分配Get-WmiObject ... | Foreach-Object { Get-WmiObject ... | Foreach-Object { line到$ GetAppRequest变量? 我的意思是Foreach-Object循环的输出被该赋值所捕获,这看起来不是有意的,因为你不再使用该变量。

我建议你执行赋值给变量,然后将变量单独传递给Foreach-Object cmdlet,并在其间进行一些记录。 另外,我们可以将Get-WmiObject封装在try{}catch{}结构中,以捕获cmdlet可能抛出的任何错误。 为了确保错误被​​捕获,我们设置-ErrorAction Stop

 try { $GetAppRequest = Get-WmiObject -Class SMS_UserApplicationRequest -Namespace root/SMS/site_$SiteCode -ErrorAction Stop } catch { log -message "Get-WmiObject cmdlet failed" -type "Error" log -message $_.Exception.Message.ToString() -type "Error" } if(-not $GetAppRequest) { log -message "Failed to retrieve WMI data" -type "Error" } elseif(-not ($GetAppRequest = $GetAppRequest | Where-Object {$_.CurrentState -like "1"})) { log -message "No results with CurrentState = 1" -type "Info" } $GetAppRequest | ForEach-Object { ... 

选中“仅在用户登录时运行”和未选中隐藏复选框。