這篇來說說 Windows 工作排程設定的執行身分,不同設定有什麼影響。

排程的執行身分有幾個選項。主選項是「只有使用者登入時才執行」或「不論使用者登入與否均執行」,前者使用者必須在登入狀態才會執行,後者則不限使用者是否登入,但需輸入使用者帳號及密碼,它還有一個附加選項「不要儲存密碼。工作將只有本機電腦資源的存取權」(Do not store password. The task will only have access to local computer resources.);除此之外,還有一個獨立選項「以最高權限執行」,可配合前述三個選項使用。

上面說的選項實際會對映到 Task Scheduler / LogonType (principalType) Element 屬性,有以下設定:

  • Interactive:使用者必須已登入,排程將在當下的互動 Session 執行,排程執行時視窗會出現在桌面
  • Password:儲存密碼,另起 Session 執行
  • S4U:Service for User,不需提供密碼,可存取本機資源,不能存取網路資源及加密檔案

Interactive 跟 Password 很直覺,分別對映「只有使用者登入時才執行」及「不論使用者登入與否均執行」,而 S4U 對映的是「不要儲存密碼。工作將只有本機電腦資源的存取權」,需要花點時間了解。S4U 源自 S4U Kerberos Extensions,是一種伺服器不需提供密碼就代替使用者登入取得 Service Ticket 的做法,後續可依藉此判斷使用者是否有權限存取該伺服器資源。參考:S4U2Self

我們可以透過 PowerShell 觀察不同設定對映的屬性變化,重點放在 Principal.LogonType 及 Principal.RunLevel。

RunLevel 一般為 Limited,勾選「以最高權限執行」後會變成 Highest。LogonType 對映如下:

  • 只有使用者登入時才執行:Interactive
  • 不論使用者登入與否均執行:Password
  • 不要儲存密碼。工作將只有本機電腦資源的存取權:S4U

我寫了一個 PowerShell 驗證不同設定下的存取權限,測試以下動作:

  1. 查詢 IIS AppPool (需要最高權限)
  2. Invoke-WebRequest 取得 Google HTML (證明 S4U 的網路指的是 AD 網域遠端資源,不是一般 TCP/IP)
  3. 查詢本機 UNC 網路分享 (驗證是否能讀取本機資源)
  4. 查詢 AD DC NetLogon 分享 (驗證是否能讀取遠端網域資源)

程式碼如下:

$curUserName = [Security.Principal.WindowsIdentity]::GetCurrent().Name
$task = Get-ScheduledTask -TaskName '排程身分測試'
$principle = $task.Principal
$logonType = $principle.LogonType
$runLevel = $principle.RunLevel
try {
    $appPoolCnt = (Get-IISAppPool).Count
    $adminTest = "Pass ($appPoolCnt)"
}
catch {
    $adminTest = "Fail"
}
try {
    $htmlLen = (Invoke-WebRequest -Uri "http://www.google.com").Content.Length
    $curlTest = "Pass ($htmlLen)"
}
catch {
    $curlTest = "Fail"
}
try {
    $dirCnt = (Get-ChildItem \\LocalComputerName\C$\Lab -ErrorAction Stop).Count
    $localUncTest = "Pass ($dirCnt)"
}
catch {
    $localUncTest = "Fail"
}
try {
    $dirCnt = (Get-ChildItem \\WIN-LP5NBDSS0UJ\NetLogon -ErrorAction Stop).Count
    $remoteUncTest = "Pass ($dirCnt)"
}
catch {
    $remoteUncTest = "Fail"
}
@"
LogonType: $logonType / RunLvel: $runLevel / Current User: $curUserName 
 * Admin Test: $adminTest 
 * curl Test: $curlTest 
 * Local UNC Test: $localUncTest
 * Remote UNC Test: $remoteUncTest
"@ | Out-File -FilePath "$PSScriptRoot\trace.log" -Append

實測結果:

// 只有使用者登入時才執行
LogonType: Interactive / RunLvel: Limited / Current User: UTOPIA\jeffrey 
 * Admin Test: Fail // 無權限
 * curl Test: Pass (50088) 
 * Local UNC Test: Pass (3)
 * Remote UNC Test: Pass (1)
 
// 不論使用者登入與否均執行
LogonType: Password / RunLvel: Limited / Current User: UTOPIA\jeffrey 
 * Admin Test: Pass (5) 
 * curl Test: Pass (47896) 
 * Local UNC Test: Pass (3)
 * Remote UNC Test: Pass (1)
 
// 不要儲存密碼。工作將只有本機電腦資源的存取權
LogonType: S4U / RunLvel: Limited / Current User: UTOPIA\jeffrey 
 * Admin Test: Pass (5) 
 * curl Test: Pass (50067) 
 * Local UNC Test: Pass (3)
 * Remote UNC Test: Fail // 無權限
 
// 只有使用者登入時才執行 + 以最高權限執行
LogonType: Interactive / RunLvel: Highest / Current User: UTOPIA\jeffrey 
 * Admin Test: Pass (5) // 成功
 * curl Test: Pass (50072) 
 * Local UNC Test: Pass (3)
 * Remote UNC Test: Pass (1)
 
// 不論使用者登入與否均執行 + 以最高權限執行
LogonType: Password / RunLvel: Highest / Current User: UTOPIA\jeffrey 
 * Admin Test: Pass (5) 
 * curl Test: Pass (47956) 
 * Local UNC Test: Pass (3)
 * Remote UNC Test: Pass (1)
 
// 不要儲存密碼。工作將只有本機電腦資源的存取權 + 以最高權限執行
LogonType: S4U / RunLvel: Highest / Current User: UTOPIA\jeffrey 
 * Admin Test: Pass (5) 
 * curl Test: Pass (47956) 
 * Local UNC Test: Pass (3)
 * Remote UNC Test: Fail // 無權限

【小結】

  1. Get-IISAppPool 這種需要管理者權限執行的動作,在互動 Session 下會失敗,需靠勾選「以最高權限執行」克服
  2. Invoke-WebRequest 存取網路及存取本機資源不受影響,全部設定下都成功
  3. 勾選「不要儲存密碼。工作將只有本機電腦資源的存取權」時無法存取網域的遠端主機


Comments

# by Jerrymow

請問我有一個排程,單獨執行程式是可以正常執行,但是透過排程呼叫(排程與手動)都會無法正常產出執行結果,有執行卻不正確 設定了 "不論使用者登入與否均執行 + 以最高權限執行" 及 改用 local admin 執行都一樣 請教這可能是哪一個地方的權限出了問題? 感謝

# by Jeffrey

to Jerrymow,單由描述很難推測原因,可能要由錯誤訊息、埋 Log 或試試用 ProcMon 抓原因。

# by Jerrymow

Hi Jeffrey, 謝謝您的說明,目前先埋 log 察看是哪一個階段造成錯誤,再來追查可能是什麼權限的差異

# by Albert

我也有一個排程,單獨執行程式(vba or python)是可以正常執行,但是透過排程呼叫(排程與手動)都會無法正常產出執行結果,都卡在建立outlook這一步驟,請問如何解決?

Post a comment