2016-04-27 132 views
1

概述: 我有一個腳本,用於通過WMI在SCCM中查詢新的應用程序請求。當在PowerShell控制檯中手動啓動時(無論是否升高,無關緊要),該腳本完美工作。我需要通過任務計劃程序運行腳本。目前設置爲使用管理員憑據運行,並選中「以最高權限運行」複選框。PowerShell腳本無法從Windows任務計劃程序正常工作

問題: 無法從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 = "[email protected]" 
$to = "[email protected]" 
$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

,沒有在其他提供的解決方案的*我的PS腳本將不能作爲計劃任務運行*問題幫助?我在右邊的相關列表中統計了7個潛在的重複數據,甚至沒有搜索其他數據。你有沒有調查過其他問題的解決方案? –

+0

是的,我讀過這些。沒有什麼是有幫助的,因爲他們傾向於關聯那些沒有交互式會話或高程的情況下無法調用的事物。我已經打高程,因爲我正在用最高級別的priv和管理員credentails跑步。至於交互會話,這只是一個WMI查詢,所以它應該工作?如果您發現某些您認爲會有幫助的內容,請將其指向我的方向。 – Mokilok

+0

我建議你添加一個'陷阱'來捕獲任何異常。你可以在你的日誌函數後添加'trap {log -message($ _ | fl * -f | out-string)-type「Exception」}並檢查日誌是否拋出異常? –

回答

2

您是不是要將Get-WmiObject ... | Foreach-Object {行的結果賦值給$ GetAppRequest變量?我的意思是Foreach-Object循環的輸出被該賦值所捕獲,這看起來不是有意的,因爲你不再使用該變量。

我建議您對變量執行賦值,然後將變量單獨傳遞給Foreach-Object cmdlet,並將其間的某些日誌記錄分別傳遞給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 { 
    ... 
+0

您是否在elseif測試中遺漏了'-not'? –

+0

很有可能。是寫這個「盲目」而不是測試我提交的一切!將編輯... –

+0

我遵循你的建議@CharlieJoynt。從任務管理器運行時,日誌文件現在會導致「無法檢索WMI數據」。仍然不確定爲什麼這會發生。我認爲其他人對配置文件中的獨特內容所說的話可能是對的,但我沒有在該服務器上使用任何$ PROFILE文檔。此外,無論在計劃任務的操作中是否具有-noprofile開關,我都會得到相同的錯誤,因爲我沒有看到加載用戶配置文件的一個要點,所以我選擇將其包含在內。 – Mokilok

-1

請與「運行,只有當用戶登錄」和hidd未選中複選框。

+0

你能解釋一下爲什麼你認爲這將是必需的嗎?我使用不同於我的用戶帳戶的憑據在服務器上運行腳本。 – Mokilok

+0

好吧,我遇到了罕見腳本的相同問題,仍然以服務器上的登錄用戶身份運行。甚至看到一些使用adobe reader命令行的.net服務需要登錄用戶才能工作。所以請試試看,並給我們反饋。 –

相關問題