概述: 我有一个脚本用于通过WMI在SCCM中查询新的应用程序请求。在PowerShell控制台中手动启动时,该脚本可以正常工作(无论是否提升,都无关紧要)。我需要通过Task Scheduler运行脚本。目前设置为使用管理员凭据运行,并选中“以最高权限运行”复选框。
问题: 无法从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>
答案 0 :(得分:2)
您的意思是将Get-WmiObject ... | Foreach-Object {
行的结果分配给 $ 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 {
...
答案 1 :(得分:-1)
选中“仅在用户登录时运行”并且未选中隐藏复选框。