共用方式為


使用者帳戶控制相容性的 Windows Vista 應用程式開發需求

 

Jennifer Allen

更新日期:2007 年 6 月

總結: 本白皮書旨在協助應用程式開發人員設計符合使用者帳戶控制規範的 Windows Vista 功能應用程式。 包含設計程式的詳細步驟,以及程式碼範例、需求和最佳做法。 本文也會詳細說明 Windows Vista 中使用者體驗的技術更新和變更。 (71 個列印的頁面。)

目錄

為何要控制使用者帳戶?
Windows Vista 更新
Windows Vista 的新技術
UAC 架構
UAC 是否會影響您的應用程式?
設計 Windows Vista 的應用程式
部署和修補標準使用者的應用程式
針對常見問題進行疑難排解
參考資料

為何要控制使用者帳戶?

應用程式開發人員已持續建立需要過多使用者權限和 Windows 許可權的 Windows 應用程式,通常需要執行中的使用者是系統管理員。 因此,少數 Windows 使用者會以最少的使用者權限和所需的 Windows 許可權來執行。 許多企業,想要平衡部署的便利性,以及與安全性搭配使用的便利性,通常因為標準使用者應用程式相容性問題而以系統管理員身分部署其桌面。

下列清單詳述在 Microsoft Windows Vista 前電腦上,難以以標準使用者身分執行的其他原因:

  1. 許多 Windows 應用程式要求登入的使用者是系統管理員,但實際上不需要系統管理員層級的存取權。 這些應用程式會在允許執行之前執行各種系統管理員存取檢查,包括:
    • 系統管理員存取權杖檢查。
    • 系統受保護位置的「所有存取」存取要求。
    • 將資料寫入受保護的位置,例如 %ProgramFiles、%WinDir%和 HKLM\Software。
  2. 許多 Windows 應用程式並非以最低許可權的概念設計,而且不會將使用者和系統管理員功能分成兩個不同的程式。
  3. Windows 2000 和 Windows XP 預設會以系統管理員身分建立每個新的使用者帳戶;因此,主要 Windows 元件,例如日期和時間和電源管理控制台不適用於標準使用者
  4. Windows 2000 和 Windows XP 系統管理員必須建立兩個不同的使用者帳戶,一個用於系統管理工作,另一個是標準使用者帳戶來執行日常工作。 因此,使用者必須登出其標準使用者帳戶,並以系統管理員身分登入,或使用執行身分來執行任何系統管理工作。

透過使用者帳戶控制 (UAC) ,Microsoft 提供一種技術來簡化在企業和家中部署標準使用者桌面的技術。

從原本設計于 Microsoft Windows NT 3.1 作業系統的 Windows 安全性架構建置,UAC 小組嘗試實作彈性且更安全的標準使用者模型。 在舊版 Windows 中,會在登入程式期間為系統管理員建立一個存取權杖。 系統管理員的存取權杖包含大部分的 Windows 許可權,以及大部分的系統管理安全性識別碼, (SID) 。 此存取權杖可確保系統管理員可以安裝應用程式、設定作業系統,以及存取任何資源。

UAC 小組對 Windows Vista 中的存取權杖建立程式採取大幅不同的方法。 當系統管理員使用者登入 Windows Vista 電腦時,會建立兩個存取權杖:已篩選的標準使用者存取權杖,以及完整的系統管理員存取權杖。 不使用系統管理員存取權杖啟動桌面 (Explorer.exe) ,而是使用標準使用者存取權杖。 所有子進程都會繼承自桌面 (explorer.exe進程) 的初始啟動,這有助於限制 Windows Vistas 攻擊面。 根據預設,所有使用者,包括系統管理員,都會以標準使用者身分登入 Windows Vista 電腦。

注意 上述語句有一個例外:來賓登入具有比標準使用者較少的使用者權限和許可權的電腦。

當系統管理員嘗試執行系統管理工作,例如安裝應用程式時,UAC 會提示使用者核准動作。 當使用者核准動作時,工作會以系統管理員的完整系統管理員存取權杖啟動。 這是預設的系統管理員提示行為,而且可在本機安全性原則管理員嵌入式管理單元中設定, (secpol.msc) 和 群組原則 (gpedit.msc) 。

注意在已啟用 UAC 的 Windows Vista 電腦上,系統管理員帳戶也稱為管理員核准模式中的系統管理員帳戶。 管理員核准模式可識別系統管理員的預設使用者體驗。

每個系統管理提高許可權也是特定的程式,這可防止其他進程使用存取權杖,而不會提示使用者核准。 因此,系統管理員使用者更細微地控制應用程式安裝,同時大幅影響預期已登入使用者以完整系統管理員存取權杖執行之惡意軟體。

標準使用者也有機會提升流程,並使用 UAC 基礎結構來執行系統管理工作。 當標準使用者嘗試執行系統管理工作時,UAC 會提示使用者輸入系統管理員帳戶的有效認證。 這是預設的標準使用者提示行為,而且可在本機安全性原則管理員嵌入式管理單元中設定, (secpol.msc) 和 群組原則 (gpedit.msc) 。

Windows Vista 更新

下列更新反映 Windows Vista 中發生的功能累積核心變更。

預設會啟用 UAC

因此,您可能會遇到某些相容性問題,這些應用程式尚未針對 Windows Vista UAC 元件更新。 如果應用程式需要系統管理員存取權杖 (當您嘗試執行應用程式) 時傳回的「拒絕存取」錯誤,您可以在操作功能表上使用 [以系統管理員身分執行] 選項來執行程式, (以滑鼠右鍵按一下) 。 本檔稍後的一節會說明如何執行此動作。

所有後續使用者帳戶都會建立為標準使用者

標準使用者帳戶和系統管理員使用者帳戶都可以利用 UAC 增強的安全性。 在新的安裝上,根據預設,第一個建立的使用者帳戶是啟用 UAC) 管理員核准 (模式的本機系統管理員帳戶。 然後,所有後續帳戶都會建立為標準使用者。

預設會在安全桌面上顯示提高許可權提示

預設會在 Windows Vista 的安全桌面上顯示同意和認證提示。

背景應用程式的提高許可權提示會最小化到工作列

背景應用程式會自動提示使用者在工作列上提高許可權,而不是自動移至安全桌面以提升許可權。 提高許可權提示會顯示在工作列上最小化,並閃爍以通知使用者應用程式已要求提高許可權。 當使用者流覽至網站並開始下載安裝檔案時,就會發生背景提高許可權的範例。 使用者接著會在背景下載安裝時,檢查電子郵件。 下載在背景完成且安裝開始之後,就會偵測到提高許可權做為背景工作,而不是前景工作。 此偵測可防止安裝在使用者執行另一項工作時突然竊取使用者畫面的焦點,也就是讀取電子郵件。 此行為會為提高許可權提示建立更好的使用者體驗。 應用程式開發人員如何在本文稍後提供要求提高許可權時,確保其應用程式不會最小化到工作列。

使用者登入路徑中會封鎖提高許可權

當使用者登入且需要提高許可權時啟動的應用程式現在會在登入路徑中遭到封鎖。 若未封鎖應用程式在使用者的登入路徑中提示提高許可權,標準使用者和系統管理員都必須在每個登入時回應 [使用者帳戶控制] 對話方塊。 Windows Vista 會將圖示放在系統匣中,通知使用者應用程式是否已遭到封鎖。 然後,使用者可以以滑鼠右鍵按一下此圖示,以執行封鎖的應用程式,以在使用者登入時提示提高許可權。 使用者可以按兩下匣圖示,以管理已停用或移除此清單中的啟動應用程式。

新安裝上的內建系統管理員帳戶預設為停用

Windows Vista 中預設會停用內建的系統管理員帳戶。 如果 Windows Vista 在從 Windows XP 升級期間判斷內建系統管理員是唯一有效的本機系統管理員帳戶,Windows Vista 就會讓帳戶保持啟用狀態,並將帳戶置於管理員核准模式。 根據預設,內建系統管理員帳戶無法以安全模式登入電腦。 如需詳細資訊,請參閱下列各節。 內建的系統管理員帳戶會在安裝期間使用使用者名稱 系統管理員建立。

未加入網域

當至少有一個啟用的本機系統管理員帳戶時,安全模式不允許使用停用的內建系統管理員帳戶登入。 相反地,任何本機系統管理員帳戶都可以用來登入。 如果最後一個本機系統管理員帳戶不小心降級、停用或刪除,則安全模式會允許停用的內建系統管理員帳戶登入災害復原。

已加入網域

所有情況下停用的內建系統管理員帳戶都無法以安全模式登入。 屬於 Domain Admins 群組成員的使用者帳戶可以登入電腦,以在不存在的情況下建立本機系統管理員。

注意 如果網域系統管理帳戶之前從未登入過,則電腦必須以網路安全模式啟動,因為不會快取認證。

注意 一旦電腦脫離,它會還原回先前描述的非已加入網域的行為。

使用者帳戶控制和遠端案例

當系統管理員透過遠端桌面從遠端登入 Windows Vista 電腦時,使用者預設會以標準使用者身分登入電腦。 遠端系統管理已修改為線上路上受到限制。 如果使用者正在執行具有系統管理可能性,這可協助防止惡意軟體執行應用程式「回送」。

本機使用者帳戶

當 Windows Vista 電腦的本機安全性帳戶管理員中的使用者 (SAM) 資料庫遠端連線到 Windows Vista 電腦時,該使用者在遠端電腦上沒有提高許可權的可能性,而且無法執行系統管理工作。 如果使用者想要使用 SAM 帳戶管理工作站,使用者必須以互動方式登入要管理的電腦上。

網域使用者帳戶

當具有網域使用者帳戶的使用者從遠端登入使用者是 Administrators 群組成員的 Windows Vista 電腦時,網域使用者將會在遠端電腦上以完整的系統管理員存取權杖執行,而 UAC 將不會生效。

新的預設存取控制清單 (ACL) 設定

某些 Windows 目錄中的 ACL 已變更,以在資料目錄和使用者受保護的目錄之外啟用資料共用和共同作業。 使用者的受保護目錄是其使用者設定檔 (例如 C:\Users\Denise\Pictures\) ,而資料目錄的範例則是資料磁片磁碟機上作業系統分割區以外的位置 (,例如 D:\Pictures\) 。 由於此實例中的根目錄 C 受到更嚴格的 ACL 保護,因此使用者無法在舊版 Windows Vista 中使用資料目錄。

這些 ACL 變更可確保使用者可以共用和編輯檔案,而不需要對 [使用者帳戶控制] 對話方塊提供核准。 此外,使用者現在可以讓資料夾成為私人資料夾。 這項變更可確保使用者仍然可以輕鬆地維護資料磁片磁碟機上的資料機密性和完整性。 如果其他系統管理員提高許可權,而且應該用來讓資料從標準使用者保持私人,這些私人資料夾仍可供其他系統管理員讀取。

以下是 %systemroot% 上的預設 ACL 設定,以及 Windows XP 中的資料磁片磁碟機。

Windows XP %systemroot% 和資料磁片磁碟機 ACL 設定

使用者或群組 存取控制專案
BUILTIN\Administrators 完整控制
NT AUTHORITY\SYSTEM 完整控制
CREATOR OWNER 完整控制
BUILTIN\Users 讀取

特殊存取:FILE_APPEND_DATA

特殊存取:FILE_WRITE_DATA

所有人 讀取

下表詳細說明使用 format.exe 建立之資料磁片磁碟機的新 Windows Vista 資料磁片磁碟機 ACL 設定。

Windows Vista 資料磁片磁碟機 ACL 設定

使用者或群組 存取控制專案
BUILTIN\Administrators 完整控制
NT AUTHORITY\SYSTEM 完整控制
NT AUTHORITY\Authenticated Users 修改
BUILTIN\Users 讀取及執行

泛型讀取、泛型執行

下表詳述新的 Windows Vista 作業系統根目錄 (%systemroot%) ACL 設定。

Windows Vista %systemroot% ACL 設定

使用者或群組 存取控制專案
BUILTIN\Administrators 完整控制
NT AUTHORITY\SYSTEM 完整控制
BUILTIN\Users 讀取及執行
NT AUTHORITY\Authenticated Users 修改

附加資料

強制標籤\高強制層級 無寫入

新的 UAC 安全性設定和安全性設定名稱變更

本檔的參考一節會詳細說明新的安全性設定和安全性設定名稱更新。

Windows Vista 的新技術

下列各節詳細說明 Windows Vista 的新技術,包括安裝程式偵測、使用 Windows Installer 4.0 的標準使用者修補、使用者介面許可權隔離和虛擬化。

ActiveX 安裝程式服務

ActiveX 安裝程式服務可讓企業委派標準使用者的 ActiveX 控制項安裝。 此服務可確保例行商務工作不會受到失敗的 ActiveX 控制安裝和更新所阻礙。 Windows Vista 也包含群組原則設定,可讓 IT 專業人員定義標準使用者可以安裝 ActiveX 控制項的主機 URL。 ActiveX Installer Service 包含 Windows 服務、群組原則系統管理範本,以及 Internet Explorer 中的一些變更,而且是只能在安裝它的用戶端上啟用的選擇性元件。

安裝程式偵測

安裝程式是設計用來部署軟體的應用程式,而且大部分寫入系統目錄和登錄機碼。 這些受保護的系統位置通常只能由系統管理員使用者寫入;這表示標準使用者沒有足夠的存取權可安裝程式。 Windows Vista 啟發學習會偵測安裝程式,並要求系統管理員認證或系統管理員使用者核准,以使用存取權限執行。 Windows Vista 也會啟發式偵測更新程式和未安裝程式。 請注意,UAC 的設計目標是防止在沒有使用者的知識和同意的情況下執行安裝,因為它們會寫入檔案系統和登錄的受保護區域。

重要 開發新的安裝程式時,就像開發 Windows Vista 的程式一樣,請務必使用適當的 requestedExecutionLevel 元素來內嵌應用程式資訊清單, (請參閱步驟六:使用您的應用程式建立和內嵌應用程式資訊清單一節) 。 當 requestedExecutionLevel 出現在內嵌的應用程式資訊清單中時,它會覆寫安裝程式偵測。

安裝程式偵測僅適用于:

  • 32 位可執行檔
  • 沒有 requestedExecutionLevel 的應用程式
  • 以啟用 LUA 的標準使用者身分執行的互動式進程

建立 32 位進程之前,會檢查下列屬性,以判斷它是否為安裝程式:

  • 檔案名包含關鍵字,例如 「install」、「setup」、「update」等等。
  • 下列版本設定資源欄位中的關鍵字:廠商、公司名稱、產品名稱、檔案描述、原始檔案名、內部名稱和匯出名稱。
  • 內嵌在可執行檔中並存資訊清單中的關鍵字。
  • 在可執行檔中連結的特定 StringTable 專案中的關鍵字。
  • RC 資料中連結在可執行檔中的索引鍵屬性。
  • 可執行檔內的目標位元組序列。

注意 位元組的關鍵字和序列衍生自各種安裝程式技術觀察到的常見特性。

請確定您已徹底檢閱本檔的完整內容,包括步驟六:使用您的應用程式建立和內嵌應用程式資訊清單一節。

注意使用者帳戶控制:偵測應用程式安裝並提示提高許可權設定必須啟用,安裝程式偵測才能偵測安裝程式。 預設會啟用此設定,而且可以使用安全性原則管理員嵌入式管理單元 (secpol.msc) 或 群組原則 (gpedit.msc) 進行設定。

您可以在 MSDN Library 中找到 Microsoft Windows Installer 的一般資訊和概觀。

修補 UAC 環境中的應用程式

Microsoft Windows Installer 4.0 是以 UAC 設計,以便讓應用程式安裝和修補更容易。 透過 Windows Installer 4.0 的引進,修補程式可以套用至應用程式,而不需要重新安裝較新版本的應用程式。 當應用程式部署在每部電腦安裝中,且需要使用者部署修補程式,而不需要系統管理存取權杖時,這個方法很理想。 如需如何建立和套用修補程式至應用程式的詳細資訊,請參閱 修補Per-User受控應用程式

資訊安全中心整合

在 Windows Vista 電腦上停用 UAC 時,資訊安全中心會建立警示,並提示使用者重新啟用 UAC。 當電腦在 UAC 設定變更之後重新開機之後,資訊安全中心就會顯示此警示。

使用者介面許可權隔離

使用者介面許可權隔離 (UIPI) 是一種機制,可協助隔離以完整系統管理員身分執行的應用程式,以及以低於相同互動式桌面系統管理員身分執行之帳戶的程式。 UIPI 專屬於視窗處理和圖形子系統,稱為支援視窗和使用者介面控制項的 USER。 UIPI 可防止較低的許可權應用程式使用 Windows 訊息,將輸入從一個進程傳送至較高的許可權進程。 將輸入從某個進程傳送到另一個進程,可讓進程將輸入插入另一個進程,而不需要使用者提供鍵盤或滑鼠動作。

UIPI 背後的概念很簡單。 Windows Vista 會以階層式方式定義一組使用者介面許可權層級。 層級的本質是,較高的許可權等級可以將視窗訊息傳送至較低層級執行的應用程式。 不過,較低層級無法將視窗訊息傳送至較高層級的應用程式視窗。

使用者介面許可權層級位於進程層級。 初始化進程時,使用者子系統會呼叫安全性子系統,以判斷進程安全性存取權杖中指派的桌面完整性層級。 建立程式且不會變更時,桌面完整性層級是由安全性子系統所設定。 因此,建立進程且不會變更時,使用者子系統也會設定使用者介面許可權等級。

標準使用者執行的所有應用程式都有相同的使用者介面許可權等級。 身為標準使用者,應用程式會以單一許可權層級執行。 UIPI 不會干擾或變更相同許可權層級的應用程式之間的視窗訊息行為。 UIPI 對屬於系統管理員群組成員的使用者生效,而且可能會以標準使用者身分執行應用程式, (有時稱為具有篩選存取權杖的程式) ,也會在相同桌面上以完整系統管理員存取權杖執行進程。 UIPI 會封鎖下列行為,防止較低許可權進程存取較高的許可權進程。

較低的許可權進程無法:

  • 執行較高進程許可權的視窗控制碼驗證。
  • SendMessage 或 PostMessage 至較高的許可權應用程式視窗。 這些應用程式程式設計介面 (API) 傳回成功,但以無訊息方式卸載視窗訊息。
  • 使用執行緒勾點附加至較高的許可權進程。
  • 使用日誌勾點來監視較高的許可權程式。
  • 將動態連結程式庫 (DLL) 插入至較高的許可權進程。

啟用 UIPI 後,下列共用的使用者資源仍會在不同許可權層級的進程之間共用:

  • 實際擁有螢幕介面的桌面視窗
  • 桌面堆積唯讀共用記憶體
  • 全域 Atom 資料表
  • 剪貼簿

繪製到畫面是 UIPI 未封鎖的另一個動作。 繪製到畫面是指使用 Paint 方法在外部輸出上顯示內容的程式,例如監視器。 使用者/圖形裝置介面 (GDI) 模型不允許控制繪製表面;因此,較低的許可權應用程式可能會繪製在較高許可權應用程式視窗的介面區域上。

注意 因為 Windows Shell (Explorer) 是以標準使用者進程的形式執行,所以以標準使用者身分執行的任何其他進程仍然可以傳送按鍵。 這是管理員核准模式中系統管理員帳戶在起始系統管理動作時提示提高許可權同意的主要原因,例如按兩下Setup.exe或按一下提高許可權防護圖示。

虛擬化

重要 虛擬化是實作,以改善在 Windows Vista 上以標準使用者身分執行之應用程式的應用程式相容性問題。 開發人員不得依賴在後續版本的 Windows 中存在的虛擬化。

在 Windows Vista 之前,許多應用程式通常會由系統管理員執行。 因此,應用程式可以自由讀取和寫入系統檔案和登錄機碼。 如果這些應用程式是由標準使用者執行,它們會因為存取不足而失敗。 Windows Vista 藉由將寫入 (和後續的檔案或登錄作業重新導向至使用者設定檔內的每個使用者位置,) 以改善這些使用者的應用程式相容性。 例如,如果應用程式嘗試寫入 C:\Program Files\Contoso\Settings.ini,而且使用者沒有寫入該目錄的許可權,則寫入將會重新導向至 C:\Users\ < user name > \AppData\Local\VirtualStore\Program Files\contoso\settings.ini。 針對登錄,如果應用程式嘗試寫入HKEY_LOCAL_MACHINE\Software\Contoso\它會自動重新導向至 HKEY_CURRENT_USER\Software\Classes\VirtualStore\MACHINE\Software\Contoso 或 HKEY_USERS\ < User SID > _Classes\VirtualStore\Machine\Software\Contoso。

下圖詳細說明 Windows Vista 中的虛擬化程式。 在此範例中,Denise 是管理員核准模式的系統管理員,而 Brian 是標準使用者。 虛擬化是由兩個元件所組成:檔案虛擬化和登錄虛擬化。

Bb530410.vistauacreqs01 (en-us,MSDN.10) .gif

圖 1. 虛擬化程式

重要 開發 Windows Vista 程式時,若要減少虛擬化檔案和登錄機碼的複雜性,請務必使用適當的 requestedExecutionLevel 來內嵌應用程式資訊清單,以關閉檔案和登錄虛擬化。

虛擬化僅適用于:

  • 32 位互動式進程
  • 系統管理員可寫入的檔案/資料夾和登錄機碼

虛擬化已停用:

  • 64 位進程
  • 非互動式進程
  • 模擬的進程
  • 核心模式呼叫端
  • 具有 requestedExecutionLevel 的可執行檔

虛擬化和漫遊:

  • 虛擬化檔案/資料夾和登錄機碼不會漫遊 (請參閱漫遊設定檔)
  • 與未漫遊的全域物件相關聯

檔案虛擬化

檔案虛擬化可解決應用程式依賴儲存檔案的能力,例如組態檔,通常只能由系統管理員寫入系統位置。 在此情況下,以標準使用者身分執行程式可能會導致程式失敗,因為存取層級不足。

當應用程式只寫入系統管理員可寫入的系統位置時,Windows 會將所有後續的檔案作業寫入虛擬市集目錄下的使用者特定路徑,其位於 %LOCALAPPDATA%\VirtualStore。 稍後,當應用程式讀取此檔案時,系統會在虛擬存放區中提供檔案。 因為 Windows 安全性基礎結構會處理虛擬化,而不需要應用程式的協助,所以應用程式認為能夠成功讀取和寫入 Program Files。 檔案虛擬化的透明度可讓應用程式在事實上存取虛擬化版本時,知道他們正在寫入和讀取受保護的資源。

注意 當您列舉資料夾和登錄中的資源時,Windows Vista 會將全域檔案/資料夾和登錄機碼合併成單一清單。 在此合併檢視中,全域 (受保護的) 資源會連同虛擬化資源一起列出。

重要 虛擬複本一律會先存在應用程式。 例如,config.ini可在 \PF\App\config.ini 和 %LOCALAPPDATA%\VirtualStore\config.ini中使用,而虛擬存放區中的config.ini一律是讀取的,即使更新\PF\App\config.ini也一樣。

下圖詳細說明如何針對不同使用者顯示虛擬化資源的全域和合併檢視。

Bb530410.vistauacreqs02 (en-us,MSDN.10) .gif

圖 2. 虛擬化資源和檢視

以下是檔案虛擬化程式的範例:

Woodgrove Bank 的銷售代表 Syed 在與其他銷售代表共用的電腦上,以標準使用者帳戶執行。 Syed 通常會使用試算表應用程式,在 Program Files\SalesV1\ 目錄下更新並儲存檔案:\Program Files\SalesV1\SalesData.txt。 雖然 Program Files\SalesV1\ 受到保護,但由於 Windows Vista 檔案虛擬化,檔案會從試算表應用程式的檢視點成功儲存。 若要達到此目的,檔案寫入會重新導向至 Users\username\appdata\Virtual Store\Program Files\SalesV1\SalesData.txt。 當 Syed 開啟 Windows 檔案總管並流覽至 Program Files 目錄時,他會看到SalesData.txt檔案的全域檢視。

注意 若要讓 Syed 探索其虛擬化檔案,他必須流覽至虛擬存放區,並在 [總管] 工具列上使用 [相容性檔案 ] 按鈕。

不過,在 Stuart Munson 的另一位銷售代表登入工作站之後,他不會在 Program Files\SalesV1\ 目錄中看到檔案SalesData.txt。 如果不同的使用者使用電腦並寫入 \Program files\SalesV1\SalesData.txt 檔案,該寫入也會虛擬化至該使用者的虛擬存放區。 檔案 Syed 更新和儲存會與系統上的其他虛擬化檔案無關。

登錄虛擬化

登錄虛擬化類似于檔案虛擬化,但適用于HKEY_LOCAL_MACHINE\SOFTWARE下的登錄機碼。 此功能允許依賴將組態資訊儲存在 HKEY_LOCAL_MACHINE\SOFTWARE 的應用程式在標準使用者帳戶下執行時繼續執行。 索引鍵和資料會重新導向至HKEY_CLASSES_ROOT\VirtualStore\SOFTWARE。 如同檔案虛擬化案例,每個使用者都有應用程式儲存在 HKLM 中的任何值的虛擬化複本。

登錄虛擬化詳細資料

  • 可以在軟體 Hive 中開啟/關閉個別金鑰
  • 金鑰層級虛擬化控制reg.exe中的新 FLAGS 選項:允許遞迴啟用/停用虛擬化,並控制「開放存取權限原則」
  • ZwQueryKey:以程式設計方式查詢金鑰的虛擬化旗標。
  • 虛擬化會在 WoW64 重新導向之上發生
  • 在 64 位和 32 位登錄檢視中啟用:HKU\{SID}_Classes\VirtualStore\Machine\Software 和 HKU\{SID}_Classes\VirtualStore\Machine\Software\SYSWOW3264
  • 大部分舊版 32 位應用程式都會使用 32 位檢視

虛擬化僅供協助應用程式與現有程式相容。 針對 Windows Vista 設計的應用程式不應該對敏感性系統區域執行寫入,也不應該依賴虛擬化來提供不正確的應用程式行為。 更新現有程式碼以在 Windows Vista 上執行時,開發人員應該確保,在執行時間期間,應用程式只會將資料儲存在每個使用者位置或 %alluserprofile% 內的電腦位置, (CSIDL_COMMON_APPDATA) 具有正確設定的存取控制清單 (ACL) 設定。

重要 Microsoft 想要從未來的 Windows 作業系統版本中移除虛擬化,因為更多應用程式會移轉至 Windows Vista。 例如,64 位應用程式上會停用虛擬化。

虛擬化建議

虛擬化僅供協助應用程式與現有程式的相容性。 針對 Windows Vista 設計的應用程式不應該對敏感性系統區域執行寫入,也不應該依賴虛擬化來提供不正確的應用程式行為。 更新現有程式碼以在 Windows Vista 上執行時,開發人員應該確保,在執行時間期間,應用程式只會將資料儲存在個別使用者位置,或在 %alluserprofile% 內已正確設定存取控制清單的 %alluserprofile% 中儲存資料 (ACL) 設定。

重要 Microsoft 想要從未來的 Windows 作業系統版本中移除虛擬化,因為更多應用程式會移轉至 Windows Vista。 例如,64 位應用程式上會停用虛擬化。

  • 為互動式應用程式新增具有適當 requestedExecutionLevel 的應用程式資訊清單。 這會關閉資訊清單應用程式的虛擬化。
  • 請勿使用登錄作為處理序間通訊機制。 服務和使用者應用程式會有不同的金鑰檢視。
  • 在 Windows Vista 上測試您的應用程式:確定以標準使用者身分執行的進程不會寫入 %systemroot% 之類的全域命名空間。
  • 針對篩選驅動程式開發人員:檢查您的高度範圍。 請參閱檔案系統篩選器。 這些必須高於 FSFilter 虛擬化。
  • 請記住,虛擬化資源是全域資源的每個使用者複本。

存取權杖變更

當使用者登入 Windows Vista 電腦時,Windows 會查看使用者帳戶擁有的系統管理 Windows 許可權和相對識別碼 (RID,) 以判斷使用者帳戶是否應該收到兩個存取權杖, (篩選的存取權杖和完整存取權杖) 。 如果下列任一項成立,Windows 會為使用者建立兩個存取權杖:

  1. 使用者帳戶包含下列任何 RID。
    • DOMAIN_GROUP_RID_ADMINS
    • DOMAIN_GROUP_RID_CONTROLLERS
    • DOMAIN_GROUP_RID_CERT_ADMINS
    • DOMAIN_GROUP_RID_SCHEMA_ADMINS
    • DOMAIN_GROUP_RID_ENTERPRISE_ADMINS
    • DOMAIN_GROUP_RID_POLICY_ADMINS
    • DOMAIN_ALIAS_RID_ADMINS
    • DOMAIN_ALIAS_RID_POWER_USERS
    • DOMAIN_ALIAS_RID_ACCOUNT_OPS
    • DOMAIN_ALIAS_RID_SYSTEM_OPS
    • DOMAIN_ALIAS_RID_PRINT_OPS
    • DOMAIN_ALIAS_RID_BACKUP_OPS
    • DOMAIN_ALIAS_RID_RAS_SERVERS
    • DOMAIN_ALIAS_RID_PREW2KCOMPACCESS
    • DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS
    • DOMAIN_ALIAS_RID_CRYPTO_OPERATORS
  2. 使用者帳戶包含標準使用者帳戶以外的任何許可權。 標準使用者帳戶只包含下列許可權。
    • SeChangeNotifyPrivilege
    • SeShutdownPrivilege
    • SeUndockPrivilege
    • SeIncreaseWorkingSetPrivilege
    • SeTimeZonePrivilege

篩選權杖所包含的許可權取決於原始權杖是否包含上述任何受限制的 RIDS。 如果權杖中有任何受限制的 RID,則會移除擁有權限,但下列除外:

  • SeChangeNotifyPrivilege
  • SeShutdownPrivilege
  • SeUndockPrivilege
  • SeReserveProcessorPrivilege
  • SeTimeZonePrivilege

如果權杖中沒有受限制的 RID,則只會移除下列許可權:

  • SeCreateTokenPrivilege
  • SeTcbPrivilege
  • SeTakeOwnershipPrivilege
  • SeBackupPrivilege
  • SeRestorePrivilege
  • SeDebugPrivilege
  • SeImpersonatePrivilege
  • SeRelabelPrivilege

第一個稱為篩選存取權杖的存取權杖,如果存取權杖中有標示為USE_FOR_DENY_ONLY,且先前未列出的系統管理 Windows 許可權) ,則具有先前的 RID (。 當使用者啟動應用程式時,預設會使用篩選的存取權杖。 未修改的完整存取權杖稱為連結存取權杖,會附加至篩選的存取權杖,並在提出要求以完整系統管理存取權杖啟動應用程式時使用。

如需 RID 的詳細資訊,請參閱 MSDN 程式庫文章SID 字串 [安全性]。

如需 Windows 許可權的詳細資訊,請參閱 MSDN Library 文章 授權常數 [安全性]

UAC 架構

下圖代表 Windows Vista 中可執行檔啟動的進程流程。

Bb530410.vistauacreqs03 (en-us,MSDN.10) .gif

圖 3. UAC 架構

以下是 UAC 架構圖中顯示的進程流程描述,以及可執行檔嘗試啟動時如何實作 UAC。

標準使用者啟動路徑

Windows Vista 標準使用者啟動路徑類似于 Windows XP 啟動路徑,但包含一些修改。

  • ShellExecute () 會呼叫 CreateProcess () 。
  • CreateProcess () 會呼叫 AppCompat、Fusion 和 Installer 偵測,以評估應用程式是否需要提高許可權。 接著會檢查可執行檔,以判斷其 requestedExecutionLevel,其儲存在可執行檔的應用程式資訊清單中。 AppCompat 資料庫會儲存應用程式應用程式相容性修正專案的資訊。 安裝程式偵測會偵測安裝程式可執行檔。
  • CreateProcess () 會傳回 Win32 錯誤碼,指出ERROR_ELE加值稅ION_REQUIRED。
  • ShellExecute () 會特別尋找這個新錯誤,並在收到錯誤時,呼叫應用程式資訊服務, (AIS) 嘗試提高許可權的啟動。

提升許可權的啟動路徑

Windows Vista 提升許可權的啟動路徑是新的 Windows 啟動路徑。

  • AIS 會從 ShellExecute () 接收呼叫,並重新評估所要求的執行層級,並群組原則判斷是否允許提高許可權,以及定義提高許可權使用者體驗。
  • 如果要求的執行層級需要提高許可權,服務會根據群組原則) ,使用從 ShellExecute () 傳入的 HWND,在呼叫端的互動式桌面上啟動提高許可權提示 (。
  • 一旦使用者已授與同意或有效認證,AIS 會視需要擷取與適當使用者相關聯的對應存取權杖。 例如,要求 highestAvailable 之 requestedExecutionLevel 的應用程式會針對只有備份操作員群組成員的使用者擷取不同的存取權杖,而不是本機 Administrators 群組的成員。
  • AIS 會重新發出 CreateProcessAsUser () 呼叫,並提供系統管理員存取權杖,並指定呼叫者的互動式桌面。

UAC 是否會影響您的應用程式?

您的應用程式是否會受到 UAC 影響,取決於應用程式的目前狀態。 在許多情況下,不需要任何變更才能符合 Microsoft Windows 安全性 需求。 不過,某些應用程式包括企業營運 (LOB) 應用程式,可能需要變更其安裝、功能和更新程式,才能在 Windows Vista UAC 環境中正常運作。

注意 如果應用程式在 Windows XP 上運作良好且標準使用者,則會在 Windows Vista 上與標準使用者搭配運作。

為什麼我需要移除應用程式的系統管理相依性?

增加整體運算環境安全性的其中一個基本步驟,就是允許使用者在不使用其系統管理存取權杖的情況下執行。 如果應用程式只在使用者是系統管理員時運作或安裝,使用者就會強制執行具有不必要的提高存取權的應用程式。 基本問題是,當使用者一律強制使用提升許可權的存取權杖來執行應用程式時,可輕易地修改作業系統,或更糟地影響其他使用者。

Microsoft 的目標是讓客戶瞭解應用程式不應該以系統管理員身分執行,而且每當系統要求他們核准應用程式以系統管理員身分執行的要求時,就會提出問題。 UAC 是協助達成此目標的基本元件,對於為所有使用者還原更安全的運算環境將會有很長的時間。

降低應用程式的擁有權總成本

標準使用者帳戶非常吸引 IT 系統管理員,想要提高其受管理電腦的安全性和控制,同時降低 TCO) (擁有權總成本。 由於標準使用者帳戶無法進行系統變更,因此與減少 TCO 有直接關聯性,並更妥善地控制應用程式安裝和全系統修改。 標準使用者帳戶也適用于父系與子系共用電腦的主使用者。 Microsoft Windows Vista 包含整合式家長監護,只有藉由建立兒童使用者帳戶作為標準使用者,才能成功實作。 標準使用者帳戶也無法變更或刪除其他使用者建立的檔案。 他們無法讀取其他使用者設定檔中的檔案、感染系統檔案,或不小心或刻意改變系統共用可執行檔。 標準使用者帳戶會導致電腦安全性性和家長監護的整體改善。

預設保護

在 Microsoft,Microsoft 的 Trustworthy Computing Initiative 原則已深入開發軟體發展。 因此,改善的安全性是 Windows Vista 開發程式不可或缺的一部分。

Trustworthy Computing 的安全性要素包含三個基本概念:依設計保護、預設安全,以及在部署中安全。 您和其他 ISV 如何開發應用程式,以貢獻作業系統的整體安全性,將是在 Windows Vista 中達成可信任運算的關鍵因素。

本指南其餘部分的目標是協助教導開發人員如何:

  • 撰寫不需要使用者成為系統管理員來執行例行工作的應用程式
  • 使用 Windows® Installer 4.0 UAC 修補技術建立安裝套件,以妥善部署到企業中的標準使用者桌面,並在首頁中正確更新。
  • 識別標準使用者和系統管理功能,並推斷 UAC 相容性的系統管理工作
  • 撰寫利用 UAC 功能的應用程式使用者介面

應用程式開發人員必須採用最低許可權的原理,並在以標準使用者帳戶執行時正確運作,才能成功 UAC。

Windows Vista 版本的其中一個目標是向所有開發人員推廣及鼓勵在管理員核准模式中為標準使用者和系統管理員設計的原則。 達成此目標可協助防止對個別應用程式進行各種攻擊,並減輕這類攻擊會危害系統安全性的可能性。 雖然這些目標目前可以透過要求系統管理員使用兩個帳戶來達成,但通常會因為下列原因而失敗:

  • 幾乎不可能控制具有完整系統管理員存取權杖的使用者。 系統管理員可以安裝應用程式,並執行他們想要的任何應用程式或腳本。 IT 管理員一律會尋求建立「標準桌面」的方式,讓使用者以標準使用者身分登入。 標準桌面可大幅降低技術支援中心成本,並減少 IT 額外負荷。
  • 每當使用者想要執行系統管理作業時,在帳戶之間切換時,會有相當多的額外負荷。
  • 執行系統管理作業之後,使用者可能會忘記切換回其標準使用者帳戶,或決定切換回太多心力。

因此,使用者可能會決定一律登入其系統管理帳戶,進而破壞安全性措施。 為了協助減輕這種情況,UAC 引進了管理員核准模式的概念。 管理員核准模式使用者帳戶是已啟用 UAC 之系統上本機系統管理員群組成員的使用者帳戶。

在企業中,管理員核准模式將作為移轉至 Windows Vista 的橋接器技術。 在理想情況下,企業會以標準使用者身分執行所有使用者,並停用標準使用者的提高許可權提示。 此設定會啟用受控標準桌面,其中會使用軟體部署技術來部署安裝,例如 Microsoft Systems Management Server (SMS) 。

重要 Microsoft 仍建議 Domain Admins 群組的成員繼續在 Windows Vista 中維護兩個不同的使用者帳戶:標準使用者帳戶和網域系統管理員使用者帳戶。 所有網域管理都應該使用網域系統管理員帳戶來完成。 若要進一步增強安全性,請考慮在網域環境中部署智慧卡解決方案。 如需詳細資訊,請參閱 使用智慧卡的安全存取規劃指南

以下是管理員核准模式的 Windows Vista 設計目標:

  • 為系統管理員群組成員的使用者消除兩個不同的帳戶需求:除非使用者提供使用完整系統管理存取權杖的核准,否則執行程式時,只能使用標準使用者存取權杖來完成此目標。
  • 保護以完整系統管理存取權杖執行的進程,以防止以標準使用者身分執行的進程存取或修改。
  • 提供系統管理員與標準使用者工作區之間的順暢轉換。

目前,大部分的 Windows 應用程式都必須以系統管理員身分執行,但實際上不會執行系統管理作業。 這些應用程式是 Microsoft Windows 9x 作業系統原理的副產品:「每個人都是系統管理員」。

以下是有問題的應用程式的範例:

  • 不必要地寫入HKEY_LOCAL_MACHINE (HKLM 的應用程式) 或檔案系統內的系統檔案。
  • ActiveX 安裝,可協助使用 Web 介面的企業營運應用程式。
  • 不必要地要求存取需要完整系統管理存取權杖之資源的應用程式。

下一節針對影響 ISV 的 Windows Vista 提供新技術。

如何判斷我的應用程式是否有系統管理相依性?

為了協助開發人員、ISV 和組織評估其應用程式,Microsoft 提供 Microsoft 標準使用者分析器。 標準使用者分析器可用來協助身分識別不符合 UAC 規範的應用程式行為。 Microsoft 建議開發人員執行此工具,以識別在標準使用者帳戶下執行應用程式的問題。 即使應用程式已在 Windows XP 的標準使用者帳戶下正確安裝並執行,也應該執行這些測試。 應用程式可能會執行作業,例如嘗試寫入系統登錄位置,並根據系統的行為做出決策,例如尋找錯誤回應。 由於新增應用程式相容性支援,Windows Vista 的行為可能與舊版 Windows 作業系統不同。 因此,建議使用新版本的標準使用者分析器測試所有應用程式。

標準使用者分析器會記錄應用程式遇到的所有系統管理作業,包括登錄/檔案系統存取和提升許可權的 API 呼叫。 此資料會儲存在記錄檔中,並顯示在工具內。 除了許多其他相依性之外,標準使用者分析器還會識別下列常見的相依性:

  • 僅限制受信任使用者存取權的物件相依性。

    例如,HKEY_LOCAL_MACHINE只會將KEY_WRITE授與系統管理員和 SYSTEM—要求KEY_WRITE給HKEY_LOCAL_MACHINE的應用程式將無法與啟用 UAC 搭配運作。

  • 使用具有安全性影響的 Windows 許可權,例如SE_DEBUG_PRIVILEGE,這允許對其他使用者的進程進行偵錯,而且只會授與系統管理員。

如果我有合法的系統管理員應用程式,有哪些需求?

對於依設計執行合法系統管理作業的應用程式,Microsoft 已實作目前 Windows XP 應用程式資訊清單架構之 trustInfo 區段的擴充功能。 您可以使用這些新屬性,向系統指出您有合法的系統管理應用程式;系統會自動要求使用者核准,以完整的系統管理存取權杖啟動應用程式。 如需如何擴充應用程式資訊清單的資訊,請參閱本檔中的一節。

設計 Windows Vista 的應用程式

下列清單代表設計 Windows Vista 應用程式的工作流程:

  1. 測試您的應用程式是否有 Windows Vista 應用程式相容性
  2. 將您的應用程式分類為標準使用者、系統管理員或混合使用者應用程式
  3. 重新設計應用程式的 UAC 相容性功能
  4. 重新設計應用程式的使用者介面
  5. 重新設計應用程式的安裝程式
  6. 使用系統管理應用程式建立和內嵌應用程式資訊清單
  7. 測試應用程式
  8. 簽署您的應用程式
  9. 判斷是否要採用 Windows Vista 標誌計畫

1.測試您的應用程式是否有應用程式相容性

安裝標準使用者分析器,即可輕鬆地執行與 UAC 的應用程式相容性測試。

若要利用標準使用者分析器的圖形化記錄顯示,您必須安裝 Microsoft 應用程式驗證器。 應用程式驗證程式 是 Microsoft 網站上的免費下載。

下列程式說明如何使用標準使用者分析器,識別未正確在 Windows Vista 上執行之預先 Windows Vista 系統管理應用程式。

您可以使用兩種方法來利用標準使用者分析器:以標準使用者身分啟動您的應用程式,或以系統管理員身分啟動您的應用程式:

以標準使用者身分啟動您的應用程式。

在此實例中,標準使用者分析器正在診斷模式中執行。 應用程式會在發生第一個錯誤時失敗,而標準使用者分析器會報告失敗的原因。

以系統管理員身分啟動您的應用程式。

在此實例中,標準使用者分析器正在預測模式中執行。 應用程式將能夠執行其課程,而標準使用者分析器將會預測,並在應用程式以標準使用者身分執行時,提供應用程式可能會遇到的錯誤概觀。

修正並解決 Bug 之後,請再次以沒有標準使用者分析器的標準使用者執行此程式,以確保您的應用程式在 Windows Vista 上如預期般運作。

識別 Windows Vista 前應用程式的應用程式相容性問題

  1. 以管理員核准模式的系統管理員身分登入 Windows Vista 電腦。
  2. 依序按一下 [開始]、[ 所有程式] 和 [ 標準使用者分析器]。
  3. 在 [標準使用者分析器] 中,針對 [目標應用程式] 指定要測試的應用程式完整目錄路徑,或按一下 [ 流覽 ] 按鈕,以尋找具有 Windows 檔案總管的程式可執行檔。
  4. 按一下 [啟動 ],然後按一下 [使用者帳戶控制] 對話方塊中的 [ 繼續 ]。
  5. 測試應用程式啟動之後,請在應用程式中執行標準系統管理工作,並在您完成時關閉應用程式。
  6. 在標準使用者分析器中,檢查每個索引標籤上的輸出。使用此資料來識別程式可能具有的相容性問題。

2.將您的應用程式分類為標準使用者、系統管理員或混合使用者應用程式

Windows Vista 中的系統管理應用程式通常會混用系統管理與標準使用者功能。 因此,決定應用程式在 Windows Vista 中的運作方式時,必須考慮一些選項。 系統管理功能可以藉由提示使用者進行核准,完全移除或與標準使用者帳戶功能分開。

協助分類應用程式的問題

回答下列問題,以判斷您的應用程式是否需要任何重新設計才能使用 Windows Vista 相容性:

  • 您的應用程式是以標準使用者身分執行嗎?
  • 系統管理功能是否可以修正為不再需要系統管理員存取權杖?
  • 系統管理區段是否可以從程式的功能中移除?

您的應用程式是以標準使用者身分執行嗎?

若要回答這個問題,請確定標準使用者完全使用應用程式或功能。 如果您的功能有任何部分需要使用者是系統管理員,則此問題的答案為「否」。

如何確認標準使用者可以使用應用程式或控制台:

  • 以標準使用者和系統管理員身分徹底測試應用程式或控制台。 確認標準使用者和系統管理員的使用者互動完全相同。
  • 檢查設定儲存在登錄中的位置。 如果有任何設定儲存在 HKLM 中,應用程式或控制台很可能需要系統管理員存取權杖。
  • 如果每部電腦有任何設定,應用程式或控制台將需要系統管理員存取權杖。
  • 如果有任何設定在其他使用者的設定檔中執行任何動作,應用程式或控制台將需要系統管理員存取權杖。

系統管理功能可以修正為不再需要系統管理員存取權杖嗎?

如果您的應用程式或控制台具有需要完整系統管理員存取權杖的設定或互動,是否可以變更為以標準使用者身分正常運作? 具體而言,程式是否可以改為將資訊儲存在個別使用者設定中? 如果無法,這個問題的答案是「否」。

Windows 計算機) Calc.exe (可以修正的功能/設定類型範例。 在 Windows XP 中,「科學」與「標準」的設定是每部電腦設定,這表示需要完整的系統管理存取權杖才能變更設定。 在 Windows Vista 中,此設定會儲存在使用者設定檔中。

如何確認系統管理區段可以從程式的功能中移除:

  • 以標準使用者和系統管理員身分徹底測試應用程式或控制台。 這兩種類型的使用者體驗是否可以相同?

  • 是否可以降低寫入 HKLM 金鑰所需的存取控制清單 (ACL) ?

    注意 此課程不應淺加注意。 藉由降低 ACL 所提供的控制,請小心不要危害系統的整體安全性。

  • 是否可以變更使用者介面來設定個別使用者狀態,而不是全域狀態 (,而且不會透過使用者介面公開全域狀態修改) ?

系統管理區段是否可以從程式的功能中移除?

您的功能絕對必須具備這項功能嗎? 如果您無法剪下系統管理功能/功能,此問題的答案為「否」。

若要判斷是否可以從程式的功能中移除系統管理區段,請執行下列動作:

  • 以標準使用者和系統管理員身分測試控制台。 保留此功能的使用者案例為何?
  • 此設定/功能是否公開于其他地方? 或許控制台中的功能是多餘的。

分析要分類應用程式的答案

如果您對上述任何問題回答「是」

如果有任何) 排除需要使用者擁有完整系統管理存取權杖的專案,請在應用程式或控制台 (進行必要的變更。

下列清單詳細說明擁有真實標準使用者應用程式的優點:

  • 您的功能同樣可供所有使用者使用。 這是理想的狀態,因為大部分的功能都不應該需要完整的系統管理員存取權杖。
  • 您的使用者永遠不會看到具有您功能的提高許可權提示。
  • 您不需要系統管理員存取權杖,您的功能會更安全。

如果您對上述所有問題回答「否」

應用程式或控制台必須經過修改,才能讓功能與 UAC 搭配運作。

確認應用程式或主控台可與 UAC 搭配運作:

最後,以標準使用者和系統管理員身分測試應用程式或控制台。 請確定 (先前的問題) 無法用於這個特定應用程式或控制台的其他選項。

3.重新設計應用程式的 UAC 相容性功能

在您分類應用程式並判斷它是否必須針對 UAC 重新設計之後,請使用本節中的資訊。

重新設計 Windows Vista 應用程式的大型元件將會檢查應用程式的核心使用者存取模型。

所有 Windows Vista 應用程式的需求

指定 requestedExecutionLevel

若要讓 UAC 正常運作,作業系統必須能夠識別哪些程式碼需要提高的許可權,以及哪些程式碼沒有。

在 Windows Vista 中,這些變更會要求應用程式標示資訊,讓作業系統能夠判斷應該啟動應用程式的內容。 例如,標準使用者應用程式必須標示為以叫用者身分執行,且啟用協助工具的應用程式必須由系統識別。

請勿向 Rundll32 註冊元件

某些應用程式會使用 Windows Rundll32 可執行檔來執行元件。 不過,此方法不符合 Windows Vista 開發需求。 直接呼叫 Rundll32 會導致 UAC 相容性問題。 當應用程式依賴 Rundll32 可執行檔來執行其執行時,Rundll32 會代表應用程式呼叫 Application Information Service (AIS) ,以起始 UAC 提高許可權提示。 因此,UAC 提高許可權提示不知道原始應用程式,並將要求提高許可權的應用程式顯示為「Windows 主機進程 (Rundll32) 」。若沒有要求提高許可權之應用程式的清楚描述和圖示,使用者就無法識別應用程式,並判斷它是否安全提高許可權。

如果您的應用程式呼叫 Rundll32 以執行元件,請使用下列工作流程重新設計執行呼叫。

  1. 為您的應用程式建立新的個別可執行檔。
  2. 在新可執行檔中,呼叫 DLL 中您已使用 Rundll32 指定的匯出函式。 如果沒有 .lib,您可能需要 LoadLibrary DLL。
  3. 在資源檔中,建立並新增可執行檔的新圖示。 當應用程式要求提高許可權時,此圖示會顯示在使用者帳戶控制提高許可權提示中。
  4. 為可執行檔提供簡短且有意義的名稱。 當應用程式要求提高許可權時,此名稱會顯示在使用者帳戶控制提高許可權提示中。
  5. 建立並內嵌可執行檔的應用程式資訊清單檔,並以 requested execution level of requireAdministrator 標記它。 此程式詳述于使用您的應用程式建立和內嵌應用程式資訊清單一節。
  6. Authenticode 會簽署新的可執行檔。 此程式詳述于 Authenticode 簽署您的應用程式一節。

在取消安裝應用程式之後,使用者應該能夠重新安裝應用程式,而不會發生錯誤。

標準使用者應用程式的需求

以下是設計在標準使用者帳戶下正確運作的應用程式時所要記住的事項摘要。 開發人員應該在應用程式的設計階段記住這些需求。

安裝程式

  • 請勿執行系統管理動作 (,例如在第一次執行時完成安裝程式) ;它應該在初始安裝程式中完成。
  • 絕對不要直接寫入 Windows 目錄或子目錄。 使用正確的方法來安裝字型之類的檔案。
  • 如果您需要自動更新應用程式,請使用適合標準使用者使用的機制,例如 Windows Installer 4.0 使用者帳戶控制修補來完成更新。

儲存狀態

  • 請勿將每個使用者資訊或使用者可寫入的資訊寫入 Program Files 或 Program 目錄。
  • 請勿在檔案系統中使用硬式編碼路徑。 利用 KnownFolders API 和 ShGetFolder 來尋找寫入資料的位置。

在標準使用者帳戶下執行和測試

如果您要撰寫非系統管理應用程式,例如 LOB 應用程式或遊戲之類的使用者應用程式,您一律必須將應用程式資料寫入標準使用者可存取的位置。 以下是一些建議的需求。

  • 將每個使用者的資料寫入使用者設定檔:CSIDL_APPDATA。
  • 將每部電腦資料寫入 Users\All Users\Application Data:CSIDL_COMMON_APPDATA。
  • 應用程式無法相依于任何系統管理 API。 例如,預期成功呼叫 SetTokenInformation () Windows 函式的程式會在標準使用者帳戶下失敗。

快速使用者切換 (FUS) 感知

應用程式通常會由執行應用程式的使用者以外的使用者安裝。 例如,在首頁中,這表示父系會安裝子系的應用程式。 在企業中,SMS 或群組原則公告等部署系統將會使用系統管理員帳戶安裝應用程式。

如果初次執行時不存在每個使用者設定,請重建它們。 請勿假設安裝程式負責設定。

系統管理員應用程式的需求

使用 HWND 屬性來確認為前景應用程式

背景應用程式會自動提示使用者在工作列上提高許可權,而不是自動移至安全桌面以提升許可權。 提高許可權提示會顯示在工作列上最小化,並閃爍以通知使用者應用程式已要求提高許可權。 當使用者流覽至網站並開始下載安裝檔案時,就會發生背景提高許可權的範例。 使用者接著會在背景下載安裝時,檢查電子郵件。 下載在背景完成且安裝開始之後,就會偵測到提高許可權做為背景工作,而不是前景工作。 此偵測可防止安裝在使用者執行另一個工作--讀取電子郵件時,突然竊取使用者畫面的焦點。 此行為會為提高許可權提示建立更好的使用者體驗。

不過,某些前景應用程式目前會在 Windows Vista 上提示為背景應用程式。 此行為是不存在父 HWND 的結果。 為了確保 Windows Vista 將您的應用程式認可為前景應用程式,您必須使用 ShellExecute、CreateElevatedComObject (COM) 或 Managed 程式碼呼叫傳遞父 HWND。

UAC 提高許可權機制會使用 HWND 做為判斷提高許可權是背景或前景提高許可權的一部分。 如果應用程式判定為背景應用程式,則會將提高許可權放在工作列上做為閃爍按鈕。 使用者必須按一下按鈕,如同要求前景存取的任何應用程式,才能繼續提高許可權。 若未傳遞 HWND,即使應用程式可能真的有前景,仍會發生此狀況。

下列程式碼範例說明如何使用 ShellExecute 傳遞 HWND:

BOOL RunAsAdmin( HWND hWnd, LPTSTR lpFile, LPTSTR lpParameters )
{
    SHELLEXECUTEINFO   sei;
    ZeroMemory ( &sei, sizeof(sei) );

    sei.cbSize          = sizeof(SHELLEXECUTEINFOW);
    sei.hwnd            = hWnd;
    sei.fMask           = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI;
    sei.lpVerb          = _TEXT("runas");
    sei.lpFile          = lpFile;
    sei.lpParameters    = lpParameters;
    sei.nShow           = SW_SHOWNORMAL;

    if ( ! ShellExecuteEx ( &sei ) )
    {
        printf( "Error: ShellExecuteEx failed 0x%x\n", GetLastError() );
        return FALSE;
    }
    return TRUE;
}

下列程式碼範例說明如何使用提高許可權 Moniker 傳遞 HWND 與 CreateElevatedComObject。 它假設您已在目前線程上初始化 COM。 如需有關提高許可權 Moniker 的詳細資訊,請參閱本檔的步驟四。

HRESULT CreateElevatedComObject(HWND hwnd, REFCLSID rclsid, REFIID riid, __out void ** ppv)
{
    BIND_OPTS3 bo;
    WCHAR  wszCLSID[50];
    WCHAR  wszMonikerName[300];

    StringFromGUID2(rclsid, wszCLSID, sizeof(wszCLSID)/sizeof(wszCLSID[0])); 
    HRESULT hr = StringCchPrintf(wszMonikerName, sizeof(wszMonikerName)/sizeof(wszMonikerName[0]), L"Elevation:Administrator!new:%s", wszCLSID);
    if (FAILED(hr))
        return hr;
    memset(&bo, 0, sizeof(bo));
    bo.cbStruct = sizeof(bo);
    bo.hwnd = hwnd;
    bo.dwClassContext  = CLSCTX_LOCAL_SERVER;
    return CoGetObject(wszMonikerName, &bo, riid, ppv);

BIND_OPTS3是 Windows Vista 的新功能。 它衍生自 BIND_OPTS2。 其定義如下:

typedef struct tagBIND_OPTS3 : tagBIND_OPTS2
{
    HWND hwnd;
} BIND_OPTS3, * LPBIND_OPTS3;

唯一的新增專案是 HWND 欄位 hwnd。 此控制碼代表啟用安全桌面提示時,成為提高許可權 UI 擁有者的視窗。

下列程式碼範例說明如何在 Managed 程式碼中傳遞 HWND,以確保父對話方塊知道 HWND 及其用法。

System.Diagnostics.Process newProcess = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo("D:\SomeProgram.exe");
info.UseShellExecute = true;
info.ErrorDialog = true;
info.ErrorDialogParentHandle = this.Handle;
newProcess.StartInfo = info;
newProcess.Start();

請勿在使用者的登入路徑中提示提高許可權

當使用者登入且需要提高許可權時啟動的應用程式現在會在登入路徑中遭到封鎖。 若未封鎖應用程式在使用者的登入路徑中提示提高許可權,標準使用者和系統管理員都必須在每個登入時回應 [使用者帳戶控制] 對話方塊。 Windows Vista 會將圖示放在系統匣中,通知使用者應用程式是否已遭到封鎖。 然後,使用者可以以滑鼠右鍵按一下此圖示,以執行封鎖的應用程式,以在使用者登入時提示提高許可權。 使用者可以按兩下匣圖示,以管理已停用或移除此清單中的啟動應用程式。

說明如何使用工作排程器執行使用者提高許可權的 C++ 程式碼範例,請參閱本檔的參考一節。

請勿使用 Runas 啟動提升許可權的程式

當您在 Windows Vista 中以滑鼠右鍵按一下可執行檔) 時,Windows XP 和 Windows Server 2003 中的 [ 執行身分... ] 選項已取代為操作 (功能表上的 [以 系統管理員 身分執行] 選項。 當標準使用者選取 [ 以系統管理員身分執行 ] 選項時,使用者會顯示本機電腦上的作用中系統管理員清單。 也會顯示具有較高許可權的標準使用者,例如備份操作員群組的成員。 當系統管理員選取 [ 以系統管理員身分執行 ] 選項時,使用者帳戶控制對話方塊會立即提示使用者繼續執行應用程式。

使用者必須在命令提示字元中使用 runas 命令,才能以其他使用者身分執行應用程式。

重要 請注意,不論 Runas 是具有備份操作員或系統管理員等許可權的標準使用者,都無法啟動具有提升許可權存取權杖的應用程式。 runas 命令會授與使用者以不同認證啟動應用程式的能力。 使用不同帳戶啟動應用程式的最佳方法是使用服務以程式設計方式執行動作,而不依賴使用者以不同使用者身分執行元件。 如果您的程式以程式設計方式使用 runas 命令,請確定它不適合啟動提升許可權的程式。

如果您的應用程式需要使用者使用不同的使用者帳戶執行應用程式的元件,請確定會公開具有命令提示字元選項的 runas 命令。 下表詳細說明 runas 命令的可用參數。

Runas 參數

參數 Description
/noprofile 指定不應該載入使用者的設定檔。 這可讓應用程式更快速地載入,但可能會導致某些應用程式故障。
/配置 檔 指定應該載入使用者的設定檔。 這是預設值。
/Env 使用目前的環境,而不是使用者的 。
/netonly 如果指定的認證僅供遠端存取,請使用此參數。
/savecred 使用使用者先前儲存的認證。 此選項不適用於 Windows XP、Home Edition,而且將會忽略。
/智慧卡 如果要提供的認證來自智慧卡,請使用此參數。
/使用者 使用者的使用者名稱。 使用者名稱應以 USER\DOMAIN 或 USER@DOMAIN的形式提供。
/showtrustlevels 顯示可做為 /trustlevel 參數引數的信任層級。
/trustlevel 在 /showtrustlevels 中列舉的其中一個層級。
程式 可執行檔的命令列。

範例︰

runas /noprofile /user:mymachine\Denise cmd

注意:

  • 只有在出現提示時,才輸入使用者的密碼。
  • /profile 參數與 /netonly 參數不相容。
  • /savecred 參數與 /smartcard 參數不相容。

主控台應用程式的需求

主控台應用程式會在主控台視窗上呈現其輸出,而不是使用個別的使用者介面。 如果應用程式需要完整的系統管理員存取權杖才能執行,則必須從提升許可權的主控台視窗啟動該應用程式。

您必須針對主控台應用程式執行下列動作:

將您的應用程式標示為 「asInvoker」

您可以撰寫應用程式的資訊清單,在其中設定 RequestedExecutionLevel == asInvoker。 此設定可讓來自非提高許可權內容的呼叫端建立您的程式,以允許他們繼續進行步驟 2。

如果應用程式在沒有完整系統管理員存取權杖的情況下執行,請提供錯誤訊息

如果應用程式是在未提高許可權的主控台中啟動,您的應用程式應該提供簡短的訊息並結束。 建議的訊息為:

「拒絕存取。 需要系統管理員許可權才能使用選取的選項。 使用系統管理員命令提示字元來完成這些工作。」

應用程式也應該在啟動失敗時傳回錯誤碼ERROR_ELE加值稅ION_REQUIRED,以利編寫腳本。

腳本的需求

腳本可能會被視為一組應用程式以預先定義的循序執行,並將其中一個通道傳送到另一個應用程式的結果。

若要讓您的腳本符合 UAC 規範,請檢查腳本的邏輯,並新增「測試」以確保在腳本中執行動作之前,您 (或執行腳本的人員) 有足夠的許可權來執行該工作。

大量作業的需求

如果您的應用程式所執行的工作包含多個物件的動作,而其中某些工作可能需要使用者的系統管理存取權杖,則第一次需要提高許可權提示時顯示。 如果使用者核准提高許可權,請執行其餘的工作。 否則,請終止批次作業。 此行為會與目前的多重選取/複製/刪除作業一致。

協助識別系統管理員的 API

  • IsUserAnAdmin ()
  • GetTokenInformation ()

系統管理員與標準使用者之間原本不同的登錄/處理存取權限

  • MAXIMUM_ALLOWED
  • KEY_WRITE
  • 套用至登錄機碼) 時的 DELETE (
  • 在 XP) 上以MAXIMUM_ALLOWED開啟的其他 HKLM 類似關鍵字 (:
  • SHELLKEY_HKLM_EXPLORER
  • SHELLKEY_HKLM_SHELL

重新導向至 HKLM 登錄值和虛擬化的其他 API 將會套用

  • WritePrivateProfileString (,,,「system.ini」) ;
  • CheckSectionAccess (「system.ini」,...) ;

4.重新設計應用程式的使用者介面,以取得 UAC 相容性

使用本節中的指導方針來開發應用程式的使用者介面,以取得 UAC 相容性。 在應用程式的開發中密切遵守這些指導方針,可確保您的應用程式在 Windows Vista 中具有一致且可預測的使用者體驗。

  • UAC 對 Windows 使用者體驗的影響
  • UAC 使用者體驗的目標
  • 提高許可權提示
  • 使用者體驗程式流程
  • 提高許可權進入點
  • 使用者介面實作
  • 何時將防護圖示新增至應用程式的使用者介面
  • 僅限系統管理員應用程式的重要決策

重要 只要參考應用程式的使用者介面,就無法滿足 UAC 相容性的需求。 應用程式的核心功能必須符合 Windows Vista 標準使用者模型需求。 上述步驟已詳述這些需求:步驟三:重新設計應用程式的 UAC 相容性功能。

UAC 對 Windows 使用者體驗的影響

系統管理員將會對使用者體驗產生最大且最立即的影響。 系統管理員使用者現在必須提供完成系統管理工作的許可權。 此外,標準使用者現在能夠要求系統管理員授與目前登入會話內特定系統管理工作的許可權。

UAC 使用者體驗的目標

UAC 使用者體驗的整體目標是在使用者體驗中提供可預測性:

  • 對於系統管理員,這表示使用者一律知道何時需要授與許可權才能執行提升許可權的工作。

這是要求使用者自己系統管理員存取權杖的動作,讓他/她可以進行系統管理員必要的變更。

  • 對於標準使用者,這表示他們會知道何時:
    • 需要為系統管理工作提供系統管理員核准 (主環境和非受控環境)
    • 或 當 無法完成工作 (受管理環境時,明確不允許提高許可權) ,且必須連絡技術支援中心

設計目標

下列清單包含 UAC 設計目標。

消除不必要的提高許可權

使用者應該必須提高許可權,才能執行需要系統管理員存取權杖的工作。 所有其他工作都應該設計為消除提高許可權的需求。 Windows Vista 前軟體通常需要系統管理員存取權杖,方法是寫入 HKLM 或 HKCR 登錄區段或 Program Files 或 Windows 系統資料夾。

可預測

系統管理員必須知道哪些工作需要提高許可權。 如果無法正確預測提高許可權的需求,他們更可能會同意不應該執行系統管理工作。 標準使用者必須知道哪些工作需要系統管理員執行,或完全無法在 Managed 環境中執行。

需要最少的心力

需要較高特殊許可權存取權杖的工作應該設計為需要單一提高許可權。 需要多個提高許可權的工作很快就會變得繁瑣。

還原為標準使用者

一旦需要較高層級存取權杖的工作完成,程式應該會還原為標準使用者狀態。

提高許可權提示

提高許可權提示是以現有的 Windows 使用者介面為基礎所建置。 提高許可權提示會顯示有關要求提高許可權之可執行檔的內容資訊,而內容會根據應用程式是否已簽署 Authenticode 而有所不同。 提高許可權提示會顯示在兩種變化中:同意提示和認證提示。

同意提示會在系統管理員嘗試執行系統管理工作時,以管理員核准模式顯示。 這是管理員核准模式中系統管理員的預設使用者體驗,可以在本機安全性原則管理員嵌入式管理單元中設定, (secpol.msc) 和 群組原則。

下圖是使用者帳戶控制同意提示的範例。

Bb530410.vistauacreqs04 (en-us,MSDN.10) .gif

圖 4. [使用者帳戶控制] 同意提示

認證提示

認證提示會在使用者嘗試執行系統管理工作時顯示給標準使用者。 這是標準使用者的預設使用者體驗,可以在本機安全性原則管理員嵌入式管理單元中設定, (secpol.msc) 和 群組原則。

下圖是使用者帳戶控制認證提示的範例。

Bb530410.vistauacreqs05 (en-us,MSDN.10) .gif

圖 5. [使用者帳戶控制] 認證提示

下表概述 Windows Vista 中每個使用者帳戶類型的預設提示樣式。

預設提高許可權提示行為

使用者帳戶類型 提高許可權提示設定
標準使用者 提示輸入認證
管理員核准模式中的系統管理員帳戶 提示要求同意

使用者體驗程式流程

UAC 使用者體驗程式流程包含三個不同的元件:

  1. 例如,提高許可權進入點 (顯示 UAC 防護圖示的控制項或連結) 。
  2. 提高許可權提示 (要求同意或系統管理員認證) 。
  3. 提升許可權的進程。

下列範例工作流程摘要說明上述元件的相關方式:

  1. 管理員核准模式中的系統管理員登入 Windows Vista 電腦。
  2. 然後,使用者決定為電腦新增另一個系統管理員使用者。
  3. 使用者按一下 [開始]、按一下[主控台],然後按一下 [安全性] 區段中標題為[允許程式通過 Windows 防火牆] 的連結,其內嵌有防護圖示。
  4. 同意提示隨即出現,要求使用者進行核准。
  5. 使用者按一下 [ 繼續 ],並建立提升許可權的進程。
  6. 在 [Windows 防火牆設定] 中,使用者修改 Windows 防火牆設定,然後按一下 [ 確定],這會終止提升許可權的進程。
  7. 使用者會繼續以標準使用者身分在電腦上工作。

注意 提高許可權進入點不會記住狀態 (例如,從受防護的位置或工作) 巡覽時,以及進入點將不會記住已發生提高許可權。 因此,使用者必須重新提高許可權,才能再次輸入工作/連結/按鈕。

提高許可權進入點

針對進入點,防護圖示會附加至某些控制項 (,例如按鈕、命令連結、超連結) ,以指出下一個步驟需要提高許可權。

盾牌圖示

防護圖示是 UAC 提升點的主要使用者介面裝飾。 此圖示表示 Windows Vista 和舊版 Windows 中的安全性相關活動,而且此關聯性會在 Windows Vista 中繼續。

下圖是防護圖示的範例。

Bb530410.vistauacreqs06 (en-us,MSDN.10) .gif

圖 6. 保護盾圖示

防護圖示會在 UAC 使用者體驗的所有三個元件中扮演重要部分。

使用 Windows 檔案總管檢視系統時,任何標示為在啟動時要求系統管理員存取權杖的應用程式,都會自動以防護字元裝飾其圖示。 這可讓使用者知道啟動時哪些應用程式會要求提高許可權。

防護圖示屬性:

  • 整個 UAC 使用者體驗的一致外觀。
  • 不會反映任何視覺狀態 (例如使用中、暫留、停用等) 。
  • 不記得狀態。

有三個一致的控制項樣式,以防護圖示標示的進入點可以在使用者體驗中取得:

  • UAC 按鈕
  • UAC 超連結
  • UAC 命令連結

這些樣式適用于這些使用者介面元素可以顯示的所有案例,例如 Wizards、Property Pages、主控台 Framework、Explorers 等。每個樣式都表示在使用者按一下 UAC 使用者介面控制項之後,會立即顯示提高許可權提示。

本節也會討論第四個 UAC 使用者介面進入點 UAC 圖示重迭。 可執行檔是否會收到圖示重迭,不受應用程式開發人員控制。 Windows Vista 會在應用程式圖示上重迭已將 requestedExecutionLevel 設定為 requireAdministrator 的可執行檔上的防護圖示。

UAC 防護按鈕

UAC 防護按鈕應該用於按下時的任何使用者介面按鈕,將會要求提高許可權提示提示使用者進行核准或認證。

UAC 防護按鈕可用來做為認可按鈕 (,例如精靈 ) 或按鈕 來顯示其他設定使用者介面 (例如 ,在屬性 對話方塊中變更設定) 。

UAC 防護按鈕包含兩個使用者介面元件:

  • 保護盾圖示
  • 文字標籤

UAC 防護按鈕會以一種方式封裝,讓開發人員可以使用它來取代一般按鈕。 UAC 按鈕也支援在文字標籤的左側或右側呈現防護圖示。 此外,開發人員可以選擇在顯示 UAC 按鈕時隱藏/顯示防護圖示。

下列螢幕擷取畫面是 UAC 防護按鈕的範例。

Bb530410.vistauacreqs07 (en-us,MSDN.10) .gif

圖 7. UAC 防護按鈕

UAC 超連結

UAC 超連結應該用於按一下時的任何使用者介面超連結,將需要提高許可權提示來提示使用者核准或認證。

UAC 超連結包含下列元件:

  • 保護盾圖示
  • 超連結控制項

UAC 超連結未封裝為開發人員要使用的防護圖示。 開發人員必須取得防護圖示資源,並在超連結旁邊轉譯。

下列螢幕擷取畫面是 UAC 超連結的範例。

Bb530410.vistauacreqs08 (en-us,MSDN.10) .gif

圖 8. UAC 超連結

UAC 命令連結

UAC 命令連結應該用於按一下時的任何使用者介面按鈕,將需要提高許可權提示來提示使用者進行核准或認證。

UAC 命令連結應該只做為認可按鈕 (,例如對話方塊中的 [執行此選項]) 。

UAC 命令連結包含下列元件:

  • 保護盾圖示
  • 標準命令連結元件
  • 連結文字
  • 附注文字

UAC 命令連結的封裝方式是開發人員可以使用 UAC 命令連結取代一般命令連結的方式。 UAC 命令連結支援在命令連結的左側或右側轉譯防護圖示。

以下是 UAC 命令連結的範例。

Bb530410.vistauacreqs09 (en-us,MSDN.10) .gif

圖 9. UAC 命令連結

圖示重迭

在 Windows Vista 中,如果可執行檔需要提高許可權才能啟動,則可執行檔的圖示應該以防護圖示「戳記」來表示此事實。 可執行檔的應用程式資訊清單必須標示 「requireAdministrator」,才能將可執行檔指定為需要完整系統管理存取權杖。 根據安裝程式偵測啟發學習法,防護圖示重迭也會自動放置在被視為需要提高許可權的可執行檔上。 例如,名為 setup.exe 的檔案會自動收到防護圖示重迭,即使可執行檔沒有內嵌的應用程式資訊清單也一樣。

下圖是 UAC 圖示重迭的範例。

Bb530410.vistauacreqs10 (en-us,MSDN.10) .gif

圖 10. UAC 圖示重迭

注意 本檔的一節提供有關如何建立和內嵌可執行檔的應用程式資訊清單的指引。

使用者介面實作

防護圖示實作和 API

本節提供開發人員移轉或實作新系統管理應用程式功能時,可供開發人員使用之圖示和 API 的初步資訊。

防護圖示實作和 API

圖示 API
保護盾 使用者資源:IDI_SHIELD
按鈕 Button_SetElevationRequired (hwndButton)
Syslink/Hyperlink syslink 旁的版面配置IDI_SHIELD
命令連結 載入IDI_SHIELD並設定為命令連結圖示
捷徑功能表 適用于靜態命令的 DefCM 中的圖示支援

將防護圖示新增至使用者介面

新增小型圖示:

#include <shellapi.h>
SHSTOCKICONINFO sii;
sii.cbSize = sizeof(sii);
SHGetStockIconInfo(SIID_SHIELD, SHGSI_ICON | SHGSI_SMALLICON, &sii);
hiconShield  = sii.hIcon;

新增大型圖示:

SHSTOCKICONINFO sii;
sii.cbSize = sizeof(sii);
SHGetStockIconInfo(SIID_SHIELD, SHGSI_ICON | SHGSI_LARGEICON, &sii);
hiconShield  = sii.hIcon;

新增自訂大小的圖示:

SHSTOCKICONINFO sii;
sii.cbSize = sizeof(sii);
SHGetStockIconInfo(SIID_SHIELD, SHGSI_ICONLOCATION, &sii);
hiconShield  = ExtractIconEx(sii. ...);

注意 一般而言,您不應該直接將防護圖示新增至您的使用者介面。 建議使用其中一個繼續方法,在控制項中內嵌防護圖示。 此外,只要在使用者介面中新增防護圖示,就無法確保 UAC 相容性。 您也必須參考應用程式的使用者體驗, (新增 requestedExecutionLevel、修正任何標準使用者錯誤,並確保使用者介面是使用者易記且與 UAC 相容的) 。

將防護圖示新增至按鈕

已增強標準按鈕控制項 (PUSHBUTTON、DEFPUSHBUTTON) ,可讓您新增圖示以及顯示的文字,而不需要設定BS_ICON或BS_BITMAP樣式。

若要顯示防護圖示,請呼叫 commctrl.h) 中定義的下列宏 (:

Button_SetElevationRequiredState(hwndButton, fRequired);

注意 hwndButton 是按鈕的 HWND;fRequired 決定要在 UAC 防護圖示) 顯示 (TRUE) 或隱藏 (FALSE。

將防護圖示新增至 Windows Installer 按鈕

使用內部資料表支援撰寫的 Windows Installer 對話方塊,可以藉由在控制項上設定 ElevationShield 屬性,將防護板新增至使用者介面對話方塊順序的最後一個按鈕。

將防護圖示新增至精靈上的 [下一步] 按鈕

重要 顯示 UAC 防護圖示 [下一步] 按鈕僅支援在 (PSH_AEROWIZARD) (PSH_AEROWIZARD) 。

若要在「下一步」按鈕上顯示一個「下一步」按鈕,以在一個裝置上的特定頁面,請使用下列程式碼:

case WM_NOTIFY:
    if (reinterpret_cast<NMHDR*>(lParam)->code == PSN_SETACTIVE)
    {
        // Show next button
        //
        // Note new wParam flag -- when PSWIZBF_ELEVATIONREQUIRED flag
        // is specified, it indicates that the next page will require
        // elevation, so if the next button is being shown, show it as
        // a shield button.

        SendMessage(GetParent(hwndDlg), 
                    PSM_SETWIZBUTTONS, 
                    PSWIZBF_ELEVATIONREQUIRED, 
                    PSWIZBF_NEXT);

        // return 0 to accept the activation
        SetWindowLong(hwndDlg, DWLP_MSGRESULT, 0); 
    }
    break;

將防護圖示新增至工作對話方塊按鈕

謹慎 工作對話方塊按鈕絕對不需要 UAC 防護圖示。 工作對話方塊按鈕上的 [按下] 動作預期會認可/取消並關閉工作對話方塊。 這類按鈕接著向使用者顯示提高許可權提示會很奇怪。

提高強制回應對話方塊

使用提高許可權 Moniker 來提升代表強制回應對話方塊的 COM 物件。

工作:

  • 將對話方塊移至 COM 物件。
  • 公開 ShowDialog () 方法。
  • 使用 API CreateElevatedComObject () 建立 COM 物件並呼叫 ShowDialog () 。

此 API 會在通過提高許可權程式之後,以系統管理員身分執行 COM 物件的實例。

注意 此 API 的版本會比較複雜,可供使用。 較新版本的 Windows Vista 中將會提供簡化的版本。

使用者教育與協助指導方針

重新考慮使用者介面並放在按鈕後方時,ISV 應該評估是否保證變更按鈕名稱。 Microsoft 強烈建議您不要使用 [ 進階 ] 作為提高許可權工作的按鈕標籤。 請改用更描述性且更容易理解的標籤,例如 變更設定 或建議按鈕後置的字詞。

僅限系統管理員使用者介面的指導方針

如果應用程式一律由系統管理員啟動,則您不需要在應用程式的使用者介面內新增其他防護。 這是因為應用程式會提高許可權,而且其所做的一切都會提高,因此不需要進一步提高許可權。

注意 如果您在僅限系統管理員的使用者體驗中有其他系統管理員使用者介面的連結,則使用者介面會提高許可權啟動其目標。 因此,您不需要將任何防護功能放在完全管理的應用程式中。

何時將防護圖示新增至應用程式的使用者介面

系統管理選擇應用程式

提升許可權的進程或 COM 物件

初始應用程式會在不需要提高許可權的情況下啟動。 使用者介面中需要系統管理存取權杖的專案會以防護圖示裝飾為識別。 此裝飾向使用者指出,使用該功能需要系統管理員核准。 當應用程式偵測到其中一個按鈕已選取時,其有下列兩個選項。

  • 應用程式會使用 ShellExeucute () 啟動第二個程式來執行系統管理工作。 第二個程式會以 requireAdministrator 的 requestedExecutionLevel 標示,因此會提示使用者進行核准。 第二個程式會以完整的系統管理存取權杖執行,而且能夠執行所需的工作。
  • 應用程式會使用 CreateElevatedComObject () 啟動 COM 物件。 此 API 會在核准之後啟動具有完整系統管理存取權杖的 COM 物件,而且此 COM 物件能夠執行所需的工作。

此方法提供最豐富的使用者體驗,而且是處理系統管理功能的慣用方法。

下列清單詳細說明提升許可權的進程或 COM 物件的需求:

  • 控制台應該實作盾裝飾及其必要的架構。
  • 開發人員必須判斷防護應該在使用者介面上的位置。
  • 開發人員必須執行架構工作,才能將商務邏輯分隔成 COM 物件與使用者介面物件。
  • 偵測到防護圖示的 OnClick 事件時,開發人員必須呼叫 UAC 提高許可權程式。

下列清單詳細說明正確設計提升許可權的程式或 COM 物件的優點:

  • 這是這兩種使用者類型的最佳整體使用者體驗。 使用者介面將會啟動、可檢視給每個人,而且該使用者介面上的所有 UAC 功能都可供所有人存取。 只有在需要系統管理員工作時,使用者才會嘗試提高許可權以完成工作。
  • 現在,執行此工作可讓您完全符合 UAC 規範。
  • 使用者介面/COM 分隔是良好的架構做法。

按一下防護圖示會導致應用程式啟動提升許可權的程式或提升許可權的 COM 物件來執行工作。

僅限系統管理員的應用程式

在此實例中,應用程式的初始啟動需要系統管理員核准。 這個方法稱為「啟動前提示」。 啟動之後,應用程式會以完整的系統管理存取權杖執行,因此可以執行所需的系統管理工作。 這個方法對開發人員而言是最低的工作。 應用程式的資訊清單會以 requireAdministrator 的 requestedExecutionLevel 標示。

重要 雖然這需要開發人員最少的工作,但請注意,就像 Windows Vista 中的其他系統管理應用程式一樣,系統管理員必須提高許可權才能使用此應用程式,而且標準使用者將無法使用應用程式。

下列清單詳細說明僅限系統管理員應用程式的需求:

  • 應用程式資訊清單應該包含 requestedExecutionLevel 標記設定為 requireAdministrator。
  • 在 Windows 啟動具有完整系統管理存取權杖的應用程式之前,系統會提示使用者進行系統管理員核准。

下列清單詳細說明正確設計僅限系統管理員應用程式的優點:

  • 如果您的安裝應用程式是系統管理應用程式,則作業系統不需要「猜測」。
  • 系統會自動為標準使用者提供作業為系統管理作業的提示。 例如,當您看到標示為 requireAdministrator 之應用程式的圖示時,圖示會內嵌在圖示中。
  • 在 Windows Vista 上,如果您將應用程式標示為 requireAdministrator,您知道一旦啟動應用程式,它就會以完整的系統管理員存取權杖執行。 使用者必須提高許可權,才能以系統管理員身分執行應用程式 (管理員核准模式,或使用以系統管理員身分執行) 。

注意 將應用程式標示為 requireAdministrator 並不會以無訊息方式提高應用程式。 使用者仍然需要授與提高許可權同意,才能啟動應用程式。 沒有任何方法可以標示 Windows Vista 中的應用程式,以無訊息方式提高許可權。

下列清單詳細說明設計僅限系統管理員應用程式的考慮點:

  • 此使用者體驗表示所有使用者都會在認證提示或同意提示 (使用者介面之前看到提高許可權提示) 甚至可見。 這也表示沒有人能夠直接檢視目前的設定,直到使用系統管理員認證進行驗證之後
  • 如果您要在安裝應用程式上標記 requireAdministrator,您應該注意執行安裝程式的使用者與可能使用者應用程式的使用者不同。 因此,您不應該修改HKEY_CURRENT_USER (HKCU) 和其他個別使用者設定,例如在系統管理設定期間寫入使用者設定檔。

重要 您必須假設執行系統管理應用程式的使用者與電腦上的一般使用者不同。

需要系統管理員存取權杖的可執行檔會以防護圖示重迭標示。

混合應用程式

混合應用程式是由使用者執行的應用程式—系統的所有使用者 (標準使用者、管理員核准模式中的系統管理員,以及備份操作員) 等。 這也是「啟動前提示」應用程式。 應用程式會使用叫用者的存取權杖執行,而且通常會針對標準使用者啟動, (沒有提高許可權提示) 。然後,程式必須在執行時間修改其行為,以根據取得的系統管理存取權杖停用使用者無法使用的功能。

混合應用程式無法在啟動時取得額外的系統管理許可權;因此,它不提供先前所述的提升許可權進程或 COM 物件方法的彈性。 這最適用于需要高於標準使用者之存取權杖但小於完整系統管理員的應用程式。

例如,Microsoft Management Console (MMC) 標示為 highestAvailable。 如果真正的標準使用者執行 MMC,MMC 將會以標準使用者應用程式的形式啟動,而不需要任何提高許可權嘗試或提示。 如果使用者是「分割權杖」使用者,例如管理員核准模式或備份操作員中的系統管理員,作業系統會提示使用者同意以使用者的「最高」可用許可權啟動 MMC。 如果是具有備份操作員許可權的標準使用者,在提高許可權之後,MMC 將會以標準使用者 + 備份操作員啟動,但不會再啟動。 如果系統管理員啟動 MMC,在提高許可權之後,MMC 將會以完整系統管理員應用程式的形式執行。

正確設計混合應用程式的優點是應用程式可供系統的所有使用者使用,即使某些功能可能已停用也一樣。

下列清單詳細說明設計混合應用程式的考慮點:

  • 開發人員必須根據使用者可用的系統管理 Windows 許可權和使用者權限,動態變更應用程式的行為。
  • 標準使用者無法對使用者介面上的系統管理層級功能採取行動。 一旦程式執行 (系統管理員必須先提高許可權,才能開啟使用者介面) ,就沒有提示提高許可權的可能性。

注意 前一個專案符號點有一個因應措施。 系統管理員可以在標準使用者的電腦上啟動提升許可權的命令提示字元,並從命令提示字元執行應用程式。 例如,以滑鼠右鍵按一下命令提示字元,選取 [ 以系統管理員身分執行],然後在命令提示字元中輸入 「applicationname.exe」。

使用者體驗會在標準使用者與系統管理員之間分支,管理員核准模式。

混合應用程式範例:備份應用程式

應用程式可由備份操作員群組的成員啟動。 然後,程式會確認使用者可用的最高層級系統管理 Windows 許可權和使用者權限就足以讓程式運作。 如需程式啟動行為的詳細資訊,請參閱本檔的應用程式資訊清單標記和應用程式啟動行為一節。

設計Administrator-Only應用程式的重要決策

後端商務物件

本節提供開發人員在開發提供最佳使用者體驗的系統管理應用程式時,可以選擇的三種模型概觀。

  • 管理員 Broker 模型
  • Back-End服務模型
  • 管理員 COM 物件模型

管理員 Broker 模型

在 管理員 Broker 模型中,應用程式分成兩個獨立可執行檔:標準使用者可執行檔和系統管理可執行檔。 開發人員使用應用程式資訊清單,以 requestedExecutionLevel asInvoker 標記標準使用者程式,並以 requireAdministrator 的 requestedExecutionLevel 標記系統管理程式。 使用者會先啟動標準使用者程式。 當使用者嘗試執行標準使用者程式知道的作業需要完整的系統管理員存取權杖時,它會執行 ShellExecute () 並啟動系統管理程式。 Windows ShellExecute () API 會先查看資訊清單,並在使用使用者的完整系統管理存取權杖執行應用程式之前,先向使用者要求核准。 系統管理程式接著可以執行系統管理工作。

注意 系統管理可執行檔程式可以使用共用記憶體、本機 RPC 或具名管道,啟用與標準使用者可執行檔之間的處理序間通訊。 如果系統管理程式確實啟用與標準使用者可執行檔的通訊,開發人員必須使用良好的安全性作法來驗證來自較低許可權程式的所有輸入。

注意 第二個程式啟動時,這兩個程式之間沒有通道

下列清單詳細資料會針對系統管理員訊息代理程式模型使用:

  • 精靈— 當硬體精靈發現所需的驅動程式未安裝在電腦上或位於企業核准的位置時,它需要提升許可權的應用程式,且能夠將驅動程式移至電腦存放區。
  • Autorun.exe呼叫 Setup.exe— 第一次放入遊戲 CD 時,autorun.exe的必要作業是設定應用程式。 第二次插入 CD 時,預設作業是播放遊戲。

使用系統管理員訊息代理程式模型的優點是,它可能是為開發人員實作的最簡單機制。

下列清單詳細說明使用 管理員 Broker 模型的一些缺點:

  • 從應用程式轉換至應用程式可能會讓使用者混淆。 難以讓使用者瞭解為什麼新的應用程式在監視器上「快顯」的原因。
  • 此外,在這兩個應用程式之間傳遞狀態較困難。 例如,您不會使用此方式在標準使用者控制台 (CPL) 及其系統管理員對應項之間傳遞狀態,只是為了允許相同的 CPL 具有系統管理和非系統管理功能。 標準使用者 CPL 必須將其狀態儲存在某處。
  • 通常,在兩個程式之間分割功能時,有許多複寫的程式碼。

若要實作系統管理員訊息代理程式模型,請建立兩個程式 (一個標準使用者和一個系統管理) ,並以適當的資訊清單要求ExecutionLevel 標記它們,並使用 ShellExecute () 從標準使用者程式啟動系統管理程式。

Back-End服務模型

在後端服務模型中,應用程式再次分成兩個獨立可執行檔,這是一個標準使用者可執行檔,可為使用者提供使用者介面,以及在系統上執行的後端服務。 Microsoft 遠端程序呼叫 (RPC) 是用來在兩者之間通訊。 前端應用程式會標示為 requestedExecutionLevel asInvoker,而後端服務會以 SYSTEM 的形式執行。 應用程式和後端服務之間的通訊是使用 RPC 來完成。

後端服務模型的其中一個用途是控制可能會影響系統的程式,例如防毒程式或反間諜軟體) 。 前端應用程式提供登入的使用者和控制服務層面的方法。

使用後端服務模型的主要優點是不需要提高許可權提示。

下列清單詳細說明使用後端服務模型的一些缺點:

  • 服務必須限制前端應用程式可以告知其執行的活動類型。 例如,防毒軟體服務可能會允許標準使用者起始系統的掃描,但無法停用即時病毒檢查。
  • 將不必要的服務新增至系統可能會影響整個系統。 請確定您的 Windows Vista 實作確實需要您的服務,而且服務已正確架構。

若要實作後端服務模型,請建立標準使用者前端應用程式和後端服務。 在產品安裝期間,在系統中安裝服務。

管理員 COM 物件模型

此模型會在此包含,但先前在本檔中詳述。 系統管理 COM 物件模型可讓動態系統管理提高許可權從應用程式或控制台內執行特定作業。

使用系統管理 COM 物件模型的主要優點是它為使用者提供最佳的使用者體驗。

下列清單詳細說明使用系統管理 COM 物件模型的一些缺點:

  • 需要開發人員最多工作,因為每個應用程式功能都必須針對系統管理員功能進行評估和測試,而且該函式必須由後端 COM 物件提供。
  • 使用者必須提供提高許可權核准。
  • 標準使用者應用程式和管理員後端 COM 物件所產生的「單位」現在為「可驅動」,而且不會受到 UIPI 和其他隔離機制的保護。

若要實作系統管理 COM 物件模型,請建立標準使用者前端應用程式,並啟動提升許可權的後端 COM 物件來執行系統管理工作。

5.重新設計應用程式的安裝程式

下列最佳做法適用于 Windows Vista 或 UAC 環境中的良好應用程式安裝。 這份清單並不是完整的清單。 如需 Windows Vista 標誌需求的詳細說明,包括 UAC 需求,請參閱 Windows Vista 標誌檔以及 Windows Vista 標誌指導方針檔最新草稿的深入版本。

在重新設計您的應用程式時,請使用這些需求。

針對您的安裝套件使用 Windows Installer 4.0。

下列許多需求都已整合到 Windows Installer 引擎中。 針對安裝套件使用 Windows Installer 可協助您遵循 Windows Vista 安裝需求。

使用已建立版本的檔案,且不會在安裝期間降級檔案。

檔案版本控制可確保安裝完成時,最終安裝狀態正確無誤。 若沒有檔案版本,則需要一些特殊的手部,以確保您的安裝適用于許多不同的安裝案例。 此外,安裝已建立版本的檔案時,請勿將版本降級,特別是共用的檔案。 降級版本可能適合您的應用程式,但通常會造成其他應用程式的問題。 藉由在 Windows Installer 套件中宣告正確的檔案版本,Windows Installer 原生支援此功能。

安裝應用程式,並將每個使用者的資料儲存在不同的位置。

應用程式應該安裝在 [程式檔案] 目錄下的 資料夾中。 若要進行此設定,您可以在 Windows Installer 套件的 Direcotry 資料表中使用 ProgramFilesFolder 屬性,每一使用者設定資料應該儲存在 \Users\username\AppData 目錄下的檔案或 HKCU 根目錄下的登錄機碼中。 使用者資料、範本和應用程式建立的檔案在 \Users\username 子目錄中都有適當的位置。 雖然這在過去並未強制執行,因為許多使用者會以完整的系統管理員存取權杖執行程式,但未將資訊放在正確位置的應用程式可能會失敗。 當虛擬化關閉時,尤其如此。

安裝共用元件時,請使用一致的資料夾位置。

共用元件應該使用 Windows Installer 套件的 Directory 資料表中的 CommonFilesFolder 屬性,安裝到 Common Files 目錄。 管理共用元件可能會有問題,並盡可能避免。 未一致安裝共用元件的開發人員,最後可能會有元件物件模型 (COM) 登錄資訊指向較舊元件。 Windows Installer 合併模組 (MSM) 特別設計,可讓共用元件在安裝共用元件的所有套件內容中一致地安裝。 當修改共用元件導致現有應用程式失敗時,就會發生其他問題。 解決此問題的其中一個方法是使用 Microsoft .NET 或 Win32 建立已建立版本的元件來建置應用程式。

如果安裝失敗,請執行安裝程式復原。

部分安裝的軟體可能會以奇怪且非預期的方式失敗,以提供不佳的使用者體驗。 Windows Installer 支援這項復原功能。

請勿在使用者設定檔上安裝應用程式快捷方式。

雖然您可能會想要將您的應用程式圖示新增至 Windows 中的每個已知曝光點,但通常會導致使用者覺得他們失去電腦的控制權。 然後,系統會強制使用者手動移除這些快捷方式,以將電腦傳回所需的外觀與風格。 如果開發人員想要將圖示新增至桌面,請在安裝期間要求使用者取得許可權。 Windows Vista 解決安裝後的應用程式可探索性,以及最近使用的應用程式清單,以避免大型的 [開始] 功能表周遊。

避免在使用者登入時自動啟動背景應用程式。

雖然您可以在安裝期間將程式新增至啟動群組或執行金鑰,但會增加系統的額外負荷。 經過一段時間後,使用者的系統效能可能會大幅降低。 如果您的應用程式可以從背景工作獲益,請讓它成為使用者可設定的。 此外,透過 HLKM 執行金鑰新增啟動工作可能會防止標準使用者帳戶在未來修改行為。 如果使用者想要在登入時啟動應用程式,請將資訊儲存在 HKCU 的執行金鑰中。

遵循清除移除邏輯。

使用者可能會移除應用程式,不僅釋放磁碟空間,還可以在安裝應用程式之前將電腦傳回其狀態。 應用程式的卸載程式應該正確且完全移除應用程式。 Windows Installer 預設為下列規則:

  • 所有非共用的應用程式檔和資料夾。
  • 參考計數 (refcount) 達到零的共用應用程式檔。
  • 登錄專案,但其他程式可能共用的機碼除外。
  • 安裝時應用程式在 [開始] 功能表中建立的所有快捷方式。
  • 使用者喜好設定可能會被視為使用者資料並留下來,但應該包含完全清除移除的選項。
  • 如果未使用 Windows Installer) ,卸載程式本身 (。

6.使用您的應用程式建立和內嵌應用程式資訊清單

在 Windows Vista 中,標記應用程式的正確方式是在程式內嵌應用程式資訊清單,告知操作系統應用程式需要什麼。 在 Windows Vista 版本中,有布建允許非資訊清單或未簽署的程式碼使用完整的系統管理存取權杖來執行。

注意 在未來的版本中,執行提升許可權之應用程式的唯一方式是擁有已簽署的資訊清單,以識別應用程式所需的許可權等級。

應用程式資訊清單架構

應用程式資訊清單不是 Windows Vista 版本的新功能。 資訊清單在 Windows XP 中使用,可協助應用程式開發人員識別應用程式所測試的 DLL 版本等專案。 提供執行層級是該現有資訊清單架構的延伸模組。

Windows Vista 應用程式資訊清單已使用屬性增強,可讓開發人員使用所要求的執行層級來標記其應用程式。 以下是此格式。

<requestedExecutionLevel
level="asInvoker|highestAvailable|requireAdministrator"
uiAccess="true|false"/>

可能要求的執行層級值

描述 註解
asInvoker 應用程式會以與父進程相同的存取權杖執行。 建議用於標準使用者應用程式。 請根據本檔中提供的指引,使用內部提高點進行參考。
highestAvailable 應用程式會以目前使用者可以取得的最高許可權來執行。 建議用於混合模式應用程式。 規劃在未來版本中參考應用程式。
requireAdministrator 應用程式只會針對系統管理員執行,而且需要以系統管理員的完整存取權杖啟動應用程式。 建議僅針對系統管理員應用程式使用。 不需要內部提高許可權點。 應用程式已提升許可權。

注意 只有在裝載應用程式支援特定類型的託管應用程式時,裝載應用程式才能成為標準使用者或僅限系統管理員的應用程式。 例如,MMC.exe現在只裝載系統管理嵌入式管理單元,而Explorer.exe只裝載標準使用者程式碼。

系統行為

應用程式 Markin 虛擬?
無名
asInvoker
requireAdministrator
highestAvailable

應用程式資訊清單標記和應用程式啟動行為

本節詳細說明許可權提示的行為,視父進程存取權杖、使用者帳戶控制:管理員核准模式原則中系統管理員的提高許可權提示行為,以及使用者帳戶控制:標準使用者原則的提高許可權提示行為,以及應用程式的要求執行層級標記。

應用程式是否可以執行,以及可以取得哪些使用者權限和管理 Windows 許可權,取決於應用程式相容性資料庫中應用程式要求執行層級的組合,以及啟動應用程式的使用者帳戶可用的系統管理許可權。 下表根據這類可能的組合,識別可能的執行時間行為。

本機 Administrators 群組成員的應用程式啟動行為

父進程存取權杖 本機系統管理員群組成員的同意原則 None 或 asInvoker highestAvailable requireAdministrator
標準使用者 沒有提示 應用程式以標準使用者身分啟動 應用程式會以完整的系統管理存取權杖啟動;沒有提示 應用程式會以完整的系統管理存取權杖啟動;沒有提示
標準使用者 提示要求同意 應用程式以標準使用者身分啟動 應用程式會以完整的系統管理存取權杖啟動;提示輸入同意 應用程式會以完整的系統管理存取權杖啟動;提示輸入同意
標準使用者 提示輸入認證 應用程式以標準使用者身分啟動 應用程式會以完整的系統管理存取權杖啟動;提示輸入認證 應用程式會以完整的系統管理存取權杖啟動;提示輸入認證
) 停用系統管理員 (UAC N/A 應用程式會以完整的系統管理存取權杖啟動;沒有提示 應用程式會以完整的系統管理存取權杖啟動;沒有提示 應用程式會以完整的系統管理存取權杖啟動;沒有提示

標準使用者帳戶的應用程式啟動行為

父進程存取權杖 標準使用者的同意原則 asInvoker highestAvailable requireAdministrator
標準使用者 沒有提示 應用程式以標準使用者身分啟動 應用程式以標準使用者身分啟動 應用程式無法啟動
標準使用者 提示輸入認證 應用程式以標準使用者身分啟動 應用程式以標準使用者身分啟動 在執行應用程式之前提示系統管理員認證
) 停用標準使用者 (UAC N/A 應用程式以標準使用者身分啟動 應用程式以標準使用者身分啟動 應用程式可能會啟動,但稍後會失敗

具有額外許可權的標準使用者應用程式啟動行為 (例如備份操作員)

父進程存取權杖 標準使用者的同意原則 asInvoker highestAvailable requireAdministrator
標準使用者 無提示 應用程式以標準使用者身分啟動 應用程式會以具有額外許可權的標準使用者身分啟動 應用程式無法啟動
標準使用者 提示輸入認證 應用程式以標準使用者身分啟動 在執行應用程式之前提示輸入認證 在執行應用程式之前提示系統管理員認證
) 停用標準使用者 (UAC N/A 應用程式以標準使用者身分啟動 應用程式會以具有額外許可權的標準使用者身分啟動 應用程式可能會啟動,但稍後會失敗

uiAccess 值

可能的 uiAccess 值

Description
應用程式不需要驅動桌面上另一個視窗的使用者介面輸入。 未提供協助工具的應用程式應將此旗標設定為 false。 在桌面 (螢幕鍵盤上將輸入驅動至其他視窗所需的應用程式,例如,) 應該將此值設定為 true。
允許應用程式略過使用者介面控制層級,以驅動桌面上較高許可權視窗的輸入。 此設定只能用於使用者介面輔助技術應用程式。

重要uiAccess旗標設定為true的應用程式必須經過 Authenticode 簽署,才能正確啟動。 此外,應用程式必須位於檔案系統中的受保護位置。 \Program Files\ 和 \windows\system32\ 目前是兩個允許的受保護位置。

如何使用 Microsoft Visual Studio 建立內嵌資訊清單

Visual Studio 提供在可攜式可執行檔 (PE) 映射的資源區段中自動內嵌 XML 資訊清單檔的功能。 本節說明如何使用 Visual Studio 建立包含資訊清單的已簽署 PE 映射。 因此,此資訊清單可以包含必要的 requestedExecutionLevel 屬性,讓應用程式能夠在 Windows Vista 上使用所需的許可權等級執行。 啟動程式時,資訊清單資訊將會從 PE 的資源區段擷取,並由作業系統使用。 不需要使用 Visual Studio 圖形化使用者介面 (GUI) 來包含資訊清單。 在原始程式碼中進行必要的變更之後,使用命令列工具進行編譯和連結也會在產生的 PE 映射中包含資訊清單。

資訊清單檔案

若要標記您的應用程式,請先建立要與目標應用程式搭配使用的資訊清單檔案。 這可以使用任何文字編輯器來完成。 資訊清單檔的名稱應該與 副檔名為 .manifest 的target.exe相同,如下列範例所示。

Executable: IsUserAdmin.exe 
Manifest:IsUserAdmin.exe.manifest
Sample application manifest file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
  <assemblyIdentity version="1.0.0.0"
     processorArchitecture="X86"
     name="IsUserAdmin"
     type="win32"/> 
  <description>Description of your application</description> 
  <!-- Identify the application security requirements. -->
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="requireAdministrator"
          uiAccess="false"/>
        </requestedPrivileges>
       </security>
  </trustInfo>
</assembly>

需要調整應用程式的資訊清單部分會以粗體標示。 其包括:

  • 元件識別
  • 名稱
  • 類型
  • 描述
  • requestedExecutionLevel 中的屬性

使用僅限 Windows Vista 應用程式的 Visual Studio 2005 在 C/C++ 程式碼中建置應用程式資訊清單

重要 如果您的應用程式是要在 Windows Vista 和 Windows XP 上執行,您必須遵循下一節中詳述的程式:使用 Microsoft Visual Studio 2005 for Windows XP 和 Windows Vista 應用程式建置和內嵌資訊清單。

接下來,您必須將資訊清單附加至可執行檔,方法是在應用程式的資源檔中新增一行, (.rc 檔案) ,讓 Microsoft Visual Studio 將資訊清單內嵌在 PE 檔案的資源區段中。 若要達成此目的,請將資訊清單放在與您要建置之專案的原始程式碼相同的目錄中,並編輯 .rc 檔案以包含下列幾行。

#define MANIFEST_RESOURCE_ID 1
MANIFEST_RESOURCE_ID RT_MANIFEST "IsUserAdmin.exe.manifest"

重建應用程式之後,資訊清單應該內嵌在可執行檔的資源區段中。

使用 Microsoft Visual Studio 2005 for Windows XP 和 Windows Vista 應用程式建置和內嵌資訊清單

在 Visual Studio 2005 中,C/C++ 整合式開發環境 (IDE) 介面,允許在目標可執行檔中包含其他資訊清單檔,會在 XML 上執行一些處理,這會插入重複的 xmlns 標記。 因此,如果應用程式應該在 Windows Vista 和 Windows XP 上執行,則無法使用先前記載如何在 Visual Studio 2005 C++ 專案中包含資訊清單的方法。 下列程式會修改為在 trustInfo 區段中包含明確的版本標籤。

已針對mt.exe工具規劃修正,以解決它在 XML 中產生重複命名空間宣告的問題。 在有新版本的 mt.exe可用之前,您可以明確將版本標籤新增至資訊清單的 trustinfo 區段,以避免合併資訊清單的問題。 範例資訊清單如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
   <ms_asmv2:trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2">
      <ms_asmv2:security>
         <ms_asmv2:requestedPrivileges>
            <ms_asmv2:requestedExecutionLevel level="asInvoker">
            </ms_asmv2:requestedExecutionLevel>
         </ms_asmv2:requestedPrivileges>
      </ms_asmv2:security>
   </ms_asmv2:trustInfo>
</assembly>

C 或 C++ 專案

下列程式詳細說明如何在 Visual Studio 2005 中建立 C 或 C++ 專案類型的資訊清單。

在 Microsoft Visual Studio 2005 中建立 C 或 C++ 專案的資訊清單

  1. 在 Microsoft Visual Studio 2005 中開啟您的專案
  2. 在 [專案] 底下,選取 [ 屬性]。
  3. 在 [屬性] 中,選取 [資訊清單工具],然後選取 [輸入與輸出]。
  4. 在 [ 其他資訊清單檔] 底下,新增應用程式資訊清單檔的名稱。
  5. 重建應用程式。

注意 包含明確版本標籤的更新資訊清單會允許應用程式在 Windows Vista 和 Windows XP 上正確執行。

Managed Code (C#、J# 和 Visual Basic)

Visual Studio 目前不會將預設資訊清單內嵌至 Managed 程式碼。 針對 Managed 程式碼,開發人員只會使用 mt.exe,將預設資訊清單插入目標可執行檔中。 這些步驟如下所示:

使用 mt.exe將預設資訊清單檔插入目標可執行檔

  1. 使用文字編輯器,例如 Windows 記事本,建立預設資訊清單檔案 temp.manifest。
  2. 使用mt.exe插入資訊清單。 此命令會是: mt.exe –manifest temp.manifest –outputresource:YourApp.exe;#1

在 Visual Studio 建置後將應用程式資訊清單新增為步驟

新增應用程式資訊清單也可以自動化為建置後步驟。 此選項適用于 C/C++ 和兩種 Managed 程式碼語言 C# 和 J#。

注意 IDE 目前不包含 Visual Basic 應用程式的建置後選項。

將下列這一行放在 專案屬性中做為建置後工作:

mt.exe -manifest "$(ProjectDir)$(TargetName).exe.manifest" 
-updateresource:"$(TargetDir)$(TargetName).exe;#1"

7.測試您的應用程式

測試重新設計或新的應用程式,以符合標準使用者分析器的應用程式相容性。 本檔稍早已在測試您的應用程式以取得 UAC 相容性一節中說明詳述此程式的程式。

使用下列工作流程來測試您的應用程式。

測試您的應用程式是否有最終 UAC 相容性

  1. 使用標準使用者分析器工具來測試應用程式。
  2. 以系統管理員身分登入 Windows Vista 電腦,管理員核准模式並執行您的程式。 請確定您測試所有功能,並記下使用者體驗。 據此提出任何提高許可權或使用者介面錯誤。
  3. 以標準使用者身分登入 Windows Vista 電腦並執行程式。 請確定您測試所有功能,並記下標準使用者體驗中任何差異或失敗,與管理員核准模式使用者體驗中的系統管理員相比。 據此提出任何提高許可權和使用者體驗錯誤。

8. Authenticode 簽署您的應用程式

應用程式現在包含將偵測到的資訊清單,以及應用程式啟動時剖析的資訊。 不過,可執行檔可能會遭到竄改。 若要避免這種情況,您應該使用 Authenticode 簽章簽署應用程式。 請注意,Windows Vista 能夠防止任何未簽署的應用程式使用完整系統管理員存取權杖啟動。 如果您想要讓應用程式在鎖定的環境中正確運作,同時顯示更方便使用的使用者介面,則應使用 Authenticode 簽章簽署。

若要簽署應用程式,您可以從makecert.exe產生憑證,或從其中一個商業憑證授權單位單位取得程式碼簽署金鑰 (,) CA) ,例如 VeriSign、Thawte 或 Microsoft CA。

注意 如果您的應用程式在客戶安裝應用程式的目的電腦上受到信任,您將需要商業憑證。

如果您使用 makecert.exe 檔案來產生簽署金鑰組,請注意它只會產生 1024 位金鑰。 Authenticode 簽章至少應該是 2048 位金鑰。 makecert.exe檔案只能用於測試用途。

下列程式詳細說明使用makecert.exe來產生簽署金鑰組的高階需求。 範例和makecert.exe參數遵循此程式。

若要使用makecert.exe來產生簽署金鑰組

  1. 產生憑證。
  2. 簽署程式碼。
  3. 安裝測試憑證。

範例簽署程式

下列程式會以範例的形式提供,而且不適合嚴格遵循。 例如,將測試憑證名稱取代為您的憑證名稱,並確定您量身訂做程式會對應到您的特定 CA 和開發環境。

步驟 1:產生憑證

makecert -r -pe -ss PrivateCertStore -n "CN=Contoso.com(Test)" 
ContosoTest.cer

makecert.exe參數

參數 Description
/r 建立自我簽署憑證
/體育 讓憑證的私密金鑰可匯出至簽署電腦。
/ss StoreName 將儲存測試憑證的憑證存放區名稱。 範例:PrivateCertStore
/n X500Name 憑證主體的 X500 名稱。 範例:Contoso.com (測試)
CertificateName.cer 憑證名稱。 範例:ContosoTest.cer

步驟 2:簽署程式碼

Signtool sign /v /s PrivateCertStore /n Contoso.com(Test) /t 
http://timestamp.verisign.com/scripts/timestamp.dll file.exe

步驟 3:安裝測試憑證

安裝測試憑證

  1. 以滑鼠右鍵按一下 [ 命令提示字元 ],然後選取 [ 以系統管理員身分執行],以啟動提升許可權的命令視窗。
  2. 在 [命令提示字元] 中,輸入 mmc.exe ,然後按 Enter
  3. 在 mmc 中,選取 [ 檔案] ,然後選取 [ 新增/移除嵌入式管理單元...
  4. 在 [新增或移除嵌入式管理單元] 中,選取 [ 憑證],按一下 [ 新增],然後按一下 [ 確定]。
  5. 在 [憑證嵌入式管理單元] 對話方塊中,選取 [ 電腦帳戶 ],然後按 [ 下一步]。
  6. 在 [選取電腦] 中,選取 [ 本機電腦],然後按一下 [ 確定]。
  7. 在 [新增或移除嵌入式管理單元] 中,按一下 [ 確定]。
  8. 在 [憑證] 嵌入式管理單元中,流覽至 [ 受信任的根憑證授權單位],以滑鼠右鍵按一下 [ 憑證],選取 [ 所有工作],然後選取 [ 匯入...
  9. 在 [憑證匯入精靈] 中,匯入測試憑證 ContosoTest.cer。

9.參與 Windows Vista 標誌計畫

Microsoft 提供 Windows Vista 標誌計畫,協助客戶識別符合平臺功能和品質目標之完整基準定義的系統和周邊,以確保終端使用者有絕佳的運算體驗。

部署和修補標準使用者的應用程式

一般而言,企業必須考慮如何在使用者的工作站上以自動化方式安裝應用程式,進而降低系統管理成本。 此問題基本上有兩個部分:首先,應該如何封裝這些應用程式以進行部署,第二個是應該使用哪些技術來部署它們。 在較小的企業環境中,可能不需要健全且自動化的部署機制。

假設企業已清查在其環境中執行的軟體,下一個步驟是重新封裝這些應用程式以進行部署。 Microsoft 建議使用 Windows Installer 格式,因為它具有將個別使用者設定與每部電腦設定分開管理的獨特功能。 這類管理通常無法搭配其他封裝格式使用,特別是只由具有更多許可權的帳戶執行的部署可執行檔,例如 SYSTEM。 MSDN 程式庫包含 Windows Installer 上的許多文章;其中一個建議是Windows Installer 檔的藍圖

Windows Installer 格式包括使用者能夠透過 群組原則 (microsoft IntelliMirror) 和 SMS 來控制這些應用程式的安裝。 若要使用副檔名或快捷方式啟用隨選安裝,Windows Installer 套件中的下表必須填入廣告資料:快捷方式、延伸模組、圖示和動詞。 建議您也填入類別、MIME、ProgID 和 TypeLib。 如需 IntelliMirror 和隨選安裝的詳細資訊 ,請參閱修補Per-User受控應用程式

還有其他安裝程式技術可讓應用程式安裝個別使用者並支援自動更新,例如 ClickOnce。 這表示只要電腦連線到網路,安裝程式就不需要系統管理員或更高的許可權來安裝,而且使用者一律會執行最新版本。 它也會對 IT 專業人員控制這些應用程式安裝的能力有所限制。

ClickOnce 部署是 Microsoft .NET 安裝技術,當使用者按一下資訊清單連結時,會自動安裝和設定用戶端應用程式,例如網站中的資訊清單、CD 上的資訊清單,或通用命名慣例, (UNC) 路徑。 根據預設,應用程式會將本身複製到暫存網際網路檔案資料夾,並在受限制的環境中執行。

注意 即使您的應用程式已使用授與完全信任的 IT 強式名稱簽署,您仍無法執行任何需要系統管理員許可權的任何動作,例如存取檔案系統和登錄的特定部分。 不過,ClickOnce 應用程式是以個別使用者應用程式為目標,因此這不應該是問題。

重要 ClickOnce 不應該用於部署執行系統管理作業的應用程式。

部署至單一電腦

若要為單一電腦部署應用程式,系統管理員必須在該電腦上「發佈」應用程式。

部署至網域中的所有使用者

若要公告網域中的所有使用者,系統管理員必須透過群組原則部署「發佈」應用程式。 目前,只有 Windows Server® 2003 作業系統和 Windows 2000 Server 作業系統的群組原則型軟體部署元件會利用這項功能。

使用 Windows Installer 4.0 將應用程式修補為標準使用者

標準使用者帳戶修補可讓 Windows Installer 套件作者識別未來標準使用者可套用的已簽署修補程式。 必須符合下列條件,才能使用 Windows Installer 4.0 啟用標準使用者修補:

  • 應用程式是使用 Windows Installer 4.0 安裝在 上。
  • 應用程式最初是每部電腦安裝。
  • MsiPatchCertificate 資料表存在於原始的 Window Installer 套件 (.msi 檔案) 中。
  • 修補程式會由 MsiPatchCertificate 資料表中所列的憑證進行數位簽署。
  • 您可以根據數位簽章來驗證修補程式。
  • 設定 MSIDISABLELUAPATCHING 屬性或 DisableLUAPatching 原則,尚未停用標準使用者帳戶修補。

Windows Installer 4.0 標準使用者卸載行為

標準使用者所套用 Windows Installer 4.0 修補程式的預期行為,就是標準使用者也可以將其移除。

針對常見問題進行疑難排解

下列各節詳述 Windows Vista 中應用程式遇到的常見問題。

常見問題包括:

  • ActiveX 安裝問題
  • ActiveX 檔未安裝
  • 需要應用程式、架構或增益集
  • 安裝/修補需要系統管理許可權
  • 個別使用者應用程式設定位置
  • 應用程式預設會儲存在受保護的目錄中

ActiveX 安裝問題

系統管理員必須安裝 ActiveX 控制項。 ActiveX 控制項通常用於企業營運應用程式,以擴充網頁瀏覽器功能,以建立更有彈性的使用者介面,或提高對網頁瀏覽器內執行之應用程式通常拒絕的電腦資源存取權。 ActiveX 控制項通常是藉由在網頁中內嵌 ActiveX 控制項的參考來安裝。 如果控制項不存在於本機電腦上,這會導致 Microsoft Internet Explorer 下載並安裝控制項。 一般而言,以這種方式下載的 ActiveX 控制項位於標準使用者可寫入的 %HOMEPATH%\Local Settings\Temporary Internet Files 目錄。 不過,若要在 Internet Explorer 內運作,控制項必須有多個登錄專案,而非系統管理員則無法使用這些專案。

解決方案

從應用程式移除 ActiveX 控制項幾乎一律會導致功能遺失。 因此,除非 ActiveX 控制項提供一些不屬於網站核心功能的視覺或功能增強功能,否則不建議進行補救。 例如,非股票相關入口網站上股票勾號。

在大部分情況下,封裝 ActiveX 控制項以供 SMS 或群組原則安裝是正確的解決方案。 不過,大部分的控制項都不會包含在基底映射中,因此網站必須修改其頁面才能正常失敗。 這應該包含偵測遺漏的 ActiveX 控制項,並重新導向至 Managed Desktop 軟體要求頁面。

ActiveX 檔未安裝

ActiveX 檔是 Microsoft Visual Basic 4 和 Microsoft Visual Basic 5 中已被取代的技術。 它們可以以與 ActiveX 控制項類似的方式下載。

解決方案

由於 Visual Basic 4 和 Visual Basic 5 已被取代,因此 Microsoft 建議您取代應用程式。 應該可以安裝 ActiveX 檔做為用戶端安裝的一部分;不過,檔更新將會受到限制,而不需透過 SMS 或群組原則重新部署。

需要應用程式、架構或增益集

許多應用程式相依于其他軟體,可能預設不會安裝,可能是因為電腦上已提供它們,或因為其他應用程式未提供可散發的二進位檔供協力廠商使用。 在一般情況下,系統會將使用者導向取得並安裝其他軟體。 在受控桌面下,無法安裝。 範例包括 Adobe Acrobat、Microsoft Office、Office Web 元件、WinZip 和 IT Microsoft .NET 安全性原則。

解決方案

識別相依性之後,就可以使用基底映射進行封裝,或透過隨選 SMS 安裝提供。 應用程式可能必須變更通知使用者遺失軟體的方式,將使用者導向 SMS 安裝網站,而非製造商。

安裝/修補需要系統管理許可權

因為安裝程式需要將檔案新增至 Program Files,所以一律需要系統管理許可權,因此必須以具有提高許可權的使用者身分執行。

注意您也可以使用 SMS 或群組原則搭配 [新增或移除程式] (ARP) 控制台來「推送」修補程式。 使用者選取要安裝的軟體,而系統安裝程式會執行其餘作業,使用者不需要是系統管理員。 針對初始安裝,這可以透過封裝軟體來推送安裝代理程式來處理。不過,某些應用程式依賴可能無法與集中管理的應用程式模型相符的頻繁自動更新。

偵測更新並嘗試修補本身的應用程式將無法這麼做,因為它們沒有修改系統目錄中檔案的許可權。

解決方案

  • 封裝您的應用程式/修補程式以透過 SMS 進行部署。 只要應用程式不需要系統管理許可權) ,就能 (偵測到升級是否可用,而且可以重新導向至布建網站。
  • 您的應用程式是否需要提高的電腦許可權,例如檔案系統、登錄存取或 COM 互通性。 如果沒有,則可能可以將應用程式重寫為 ClickOnce 部署套件,這會在 Microsoft .NET 沙箱中執行。
  • 轉換至 Web 應用程式,而不需任何用戶端相依性。

Per-User應用程式設定位置

針對 Windows Vista,必須在執行時間變更的應用程式設定應該儲存在下列其中一個位置:

  • CSIDL_APPDATA
  • CSIDL_LOCAL_APPDATA
  • CSIDL_COMMON_APPDATA

使用者儲存的檔應該儲存在CSIDL_MYDOCUMENTS中。

注意 使用者的 Documents 資料夾不再儲存在 [檔和設定] 之下。 在 Windows Vista 中,名為 Users 的檔案系統上新的根目錄現在包含電腦的使用者設定檔。

由於這些目錄已變更,因此建議開發人員使用 CSIDL,以獨立于系統的方式找出特定已知目錄的路徑。 如需詳細資訊,請參閱 CSIDL

應用程式需要檔案系統的寫入權限。 在受管理桌面下執行時,應用程式只有下列資料夾及其子系的寫入權限。

  • CSIDL_PROFILE
  • CSIDL_COMMON_APPDATA

注意 標準使用者無法寫入 Users\Common。

  • C:\Users\Common > cd 「Application Data」
    • C:\Users\Common\Application Data > echo File > File.txt
    • C:\Users\Common\Application Data>

應用程式不應該嘗試寫入其他位置,例如:

  • C:\Windows。
  • C:\Windows\System32。
  • Program Files\{application}。
  • C:\{application}。

注意 如果使用者建立資料夾,使用者群組的成員預設可以執行此動作,這會正常運作。

不允許應用程式嘗試特別建立 C:\Users\Profiles\{user},因為使用者只能在 C:\Users\{user} 下建立資料夾。 選擇的位置似乎會根據 Microsoft 儲存舊版作業系統上的 Documents 資料夾而混淆。

執行時間需要變更的應用程式設定應該儲存在下列其中一個位置:

  • CSIDL_APPDATA
  • CSIDL_LOCAL_APPDATA
  • CSIDL_COMMON_APPDATA

使用者儲存的檔應該儲存在 CSIDL_MYDOCUMENTS 資料夾中。

所有路徑不應該硬式編碼,但應該使用 Environment.GetFolderPath () 函式。

應用程式預設會儲存在受保護的目錄中

某些應用程式可讓使用者儲存或匯出資料到其本機電腦。 通常,對話方塊預設為 C:\之類的位置,而標準使用者沒有寫入權限。 此外,某些應用程式在撰寫檔案的程式碼失敗時不會回應良好,因為因為從作業系統拒絕存取。

解決方案

假設使用者只能寫入自己的設定檔。 針對使用者刻意儲存的檔,初始化對話方塊,以從 Documents (Environment.GetFolderPath (Environment.SpecialFolder.Personal) 開始。 請記住,[ 儲存 ] 對話方塊可讓使用者流覽至使用者設定檔以外的其他位置,因此應用程式應該包含邏輯,以確保如果使用者選擇與位於其設定檔中的目錄不同的目錄,則應用程式應該包含邏輯,以確保其失敗。

參考資料

本節包含虛擬化參考和安全性設定參考。

虛擬化參考

檔案虛擬化

  • 虛擬化 (%SYSTEMROOT%%PROGRAMDATA%%PROGRAMFILES%\ (子目錄)
  • 重新導向至: %LOCALAPPDATA%\VirtualStore
  • 排除的二進位可執行檔:.exe、.dll、.sys

登錄虛擬化:

  • 虛擬化 (HKLM\SOFTWARE)
  • 重新導向至:HKCU\Software\Classs\VirtualStore\MACHINE\SOFTWARE\ < Application Registry Keys>
  • 從虛擬化排除的金鑰
  • HKLM\Software\Classs
  • HKLM\Software\Microsoft\Windows
  • HKLM\Software\Microsoft\Windows NT

適用性

  • 虛擬市集未漫遊
  • 對應的全域物件不會漫遊
  • 僅針對互動式標準使用者啟用
  • 針對非互動式進程停用
  • 已針對 64 位可執行檔停用
  • 針對要求執行層級的可執行檔停用 , (requestedExecutionLevel) 其應用程式資訊清單中,用於分隔的模型
  • 已停用核心模式和模擬呼叫端
  • 只有系統管理員可寫入的登錄機碼和檔案會虛擬化

UAC 安全性設定參考

此參考詳細說明可使用 群組原則 或電腦的本機安全性原則來管理 UAC 的安全性設定。

注意 本節中呈現的程式適用于管理非受控電腦。 若要使用 群組原則 在受控環境中集中管理設定,請使用 Active Directory 使用者和電腦 (dsa.msc) ,而不是本機安全性原則管理員嵌入式管理單元 (secpol.msc) 。

設定 UAC 安全性設定

下列程式詳細說明如何使用安全性原則管理員設定 UAC 安全性設定。 此程式詳述管理員核准模式中系統管理員的預設使用者體驗。

使用安全性原則管理員檢視/設定 UAC 安全性設定

  1. 按一下 [ 開始] 按鈕,在搜尋方塊中輸入 secpol.msc ,然後按 Enter
  2. 在 [使用者帳戶控制同意] 提示字元中,按一下 [ 繼續]。
  3. 在 [本機安全性設定] 中,展開 [ 本機原則],然後按一下 [ 安全性選項]。
  4. 以滑鼠右鍵按一下您想要變更的安全性設定,然後選取 [ 屬性]。

下列程式詳細說明如何使用 群組原則 設定 UAC 安全性設定。 此程式詳細說明管理員核准模式中系統管理員的預設使用者體驗。

若要使用群組原則物件編輯器來檢視/設定 UAC 安全性設定

  1. 按一下 [ 開始] 按鈕,在搜尋方塊中輸入 gpedit.msc ,然後按 Enter鍵。
  2. 在 [使用者帳戶控制同意] 提示字元中,按一下 [ 繼續]。
  3. 在 [群組原則] 中,依序展開 [使用者設定] 和 [安全性選項]。
  4. 以滑鼠右鍵按一下您想要變更的安全性設定,然後選取 [ 屬性]。

UAC 安全性設定

下表列出可設定的 UAC 安全性設定。 這些設定可以使用安全性原則管理員 (secpol.msc) 設定,或使用 gpedit.msc) 群組原則 (集中管理。

UAC 安全性設定

設定 Description 預設值
使用者帳戶控制:管理員內建系統管理員帳戶的核准模式。 有兩個可能的設定:
  • 已啟用:內建系統管理員將會以系統管理員身分在管理員核准模式中執行。
  • 已停用:系統管理員使用完整系統管理員存取權杖執行。
  • 已針對新安裝停用,以及針對內建系統管理員不是電腦上唯一本機使用中系統管理員的升級。 在加入網域的電腦上安裝和升級時,預設會停用內建的 Administrator 帳戶。
  • 當 Windows Vista 判斷內建系統管理員帳戶是電腦上唯一的作用中本機系統管理員時,啟用升級。 如果 Windows Vista 判斷此情況,內建的 Administrator 帳戶也會在升級之後保持啟用。 在加入網域的電腦上安裝和升級時,預設會停用內建的 Administrator 帳戶。
使用者帳戶控制:在管理員核准模式,系統管理員之提升權限提示的行為 此設定有三個可能的值:
  • 提高許可權而不提示:以無訊息方式提高許可權。
  • 提示輸入認證:要求使用者在繼續之前輸入其登入密碼。
  • 提示同意:在提高許可權之前,要求使用者核准。 這是預設值。 

此設定會決定在執行具有較高許可權的程式之前,如何提示使用者。 只有在啟用 UAC 時,此原則才會生效。

提示要求同意
使用者帳戶控制:標準使用者之提升權限提示的行為 決定在執行具有較高許可權的程式之前,如何提示使用者。 只有在啟用 UAC 時,此原則才會生效。 以下是此設定的可用組態選項:
  • 自動拒絕提高許可權要求:當應用程式想要執行系統管理工作時,將不會提示使用者。 應用程式將無法啟動,且會對使用者顯示拒絕存取或對等的錯誤。
  • 提示輸入認證:要求使用者在繼續之前輸入其登入密碼。
提示輸入認證
使用者帳戶控制:偵測應用程式安裝,並提示提升權限 有兩個可能的值:
  • 已啟用:當 Windows Vista 偵測到安裝程式時,系統會提示使用者同意或認證。
  • 已停用:應用程式安裝會以無訊息方式失敗或以不具決定性的方式失敗。
啟用
使用者帳戶控制:僅針對已簽章與驗證過的可執行檔,提高其權限 有兩個可能的值:
  • 已啟用:只會執行已簽署的可執行檔。 此設定會封鎖未簽署的應用程式執行。
  • 已停用:將會執行已簽署和未簽署的程式碼。
已停用
使用者帳戶控制:僅針對在安全位置安裝的 UIAccess 應用程式,提高其權限 有兩個可能的值:
  • 已啟用:系統只會為從 %ProgramFiles% 或 %windir% 下啟動的可執行檔提供 UIAccess 許可權和使用者權限。 這些目錄中的 ACL 可確保可執行檔無法修改 (,否則會允許提高許可權) 。 從其他位置啟動的 UIAccess 可執行檔將會啟動,而不需要額外的許可權 (,也就是他們會執行 「asInvoker」) 。
  • 已停用:未完成位置檢查,因此所有 UIAccess 應用程式都會在使用者核准時,使用使用者的完整存取權杖啟動。
啟用
使用者帳戶控制:所有系統管理員均以管理員核准模式執行 有兩個可能的值:
  • 已啟用:嘗試執行系統管理作業時,系統將會提示系統管理員和標準使用者。 提示樣式則取決於原則。
  • 已停用:UAC 基本上是「已關閉」,而且 AIS 服務會從自動啟動中停用。
啟用
使用者帳戶控制:提示提升權限時切換到安全桌面 有兩個可能的值:
  • 已啟用:在安全桌面上顯示 UAC 提高許可權提示。 安全桌面只能接收來自 Windows 進程的訊息,這可消除來自惡意軟體的訊息。 因此,安全桌面上無法詐騙同意和認證提示。
  • 已停用:UAC 提高許可權提示會顯示在使用者桌面上。
啟用
使用者帳戶控制:將檔案及登錄寫入失敗虛擬化並儲存至每一使用者位置 有兩個可能的值:
  • 已啟用:應用程式資訊清單中缺少應用程式相容性資料庫專案或要求執行層級標記的應用程式不符合 UAC 規範。 使用不符合規範之軟體的環境應保持啟用此設定。
  • 已停用:符合 UAC 規範的應用程式不應寫入受保護的區域,並導致寫入失敗。 因此,只使用 UAC 相容應用程式的環境應該停用此設定。 如果停用此設定,嘗試寫入 Program Files 和 %systemroot% 的非相容應用程式將會以無訊息方式失敗。
啟用

注意 在大部分情況下,不建議使用 [提高許可權而不提示] 選項。 提高許可權而不提示會允許以標準使用者身分執行的應用程式在沒有使用者同意的情況下啟動系統管理應用程式,並有效地略過 UAC。

工作排程器程式碼範例

下列 C++ 程式碼範例說明如何使用工作排程器為使用者執行提高許可權。 因此,應用程式可以使用系統管理員的認證在登入期間自動提高許可權,而 Windows Vista 將不會封鎖應用程式。 您必須在安裝期間為應用程式建立系統管理員使用者,才能讓此解決方案正常運作。

//---------------------------------------------------------------------
//  This file is part of the Microsoft .NET Framework SDK Code Samples.
// 
//  Copyright (C) Microsoft Corporation.  All rights reserved.
// 
//This source code is intended only as a supplement to Microsoft
//Development Tools and/or on-line documentation.  See these other
//materials for detailed information regarding Microsoft code samples.
// 
//THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//PARTICULAR PURPOSE.
//---------------------------------------------------------------------

/****************************************************************************
* Main.cpp - Sample application for Task Scheduler V2 COMAPI                * Component: Task Scheduler                          
* Copyright (c) 2002 - 2003, Microsoft Corporation 
* This sample creates a task to at the time registered to start the desired task.                                                             *
****************************************************************************/
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <comdef.h>
#include <comutil.h>
//Include Task header files - Included in Windows Vista Beta-2 SDK from MSDN
#include <taskschd.h>
#include <conio.h>
#include <iostream>
#include <time.h>

using namespace std;

#define CLEANUP \
pRootFolder->Release();\
        pTask->Release();\
        CoUninitialize();

HRESULT CreateMyTask(LPCWSTR, wstring);

void __cdecl wmain(int argc, wchar_t** argv)
{
wstring wstrExecutablePath;
WCHAR taskName[20];
HRESULT result;

if( argc < 2 )
{
printf("\nUsage: LaunchApp yourapp.exe" );
return;
}

// Pick random number for task name
srand((unsigned int) time(NULL));
wsprintf((LPWSTR)taskName, L"Launch %d", rand());

wstrExecutablePath = argv[1];

result = CreateMyTask(taskName, wstrExecutablePath);
printf("\nReturn status:%d\n", result);

}
HRESULT CreateMyTask(LPCWSTR wszTaskName, wstring wstrExecutablePath)
{
    //  ------------------------------------------------------
    //  Initialize COM.
TASK_STATE taskState;
int i;
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    if( FAILED(hr) )
    {
        printf("\nCoInitializeEx failed: %x", hr );
        return 1;
    }

    //  Set general COM security levels.
    hr = CoInitializeSecurity(
        NULL,
        -1,
        NULL,
        NULL,
        RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL,
        0,
        NULL);

    if( FAILED(hr) )
    {
        printf("\nCoInitializeSecurity failed: %x", hr );
        CoUninitialize();
        return 1;
    }

    //  ------------------------------------------------------
    //  Create an instance of the Task Service. 
    ITaskService *pService = NULL;
    hr = CreateElevatedComObject( CLSID_TaskScheduler,
                           NULL,
                           CLSCTX_INPROC_SERVER,
                           IID_ITaskService,
                           (void**)&pService );  
    if (FAILED(hr))
    {
        printf("Failed to CoCreate an instance of the TaskService class: %x", hr);
        CoUninitialize();
        return 1;
    }
        
    //  Connect to the task service.
    hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
    if( FAILED(hr) )
    {
        printf("ITaskService::Connect failed: %x", hr );
        pService->Release();
        CoUninitialize();
        return 1;
    }

    //  ------------------------------------------------------
    //  Get the pointer to the root task folder.  This folder will hold the
    //  new task that is registered.
    ITaskFolder *pRootFolder = NULL;
    hr = pService->GetFolder( _bstr_t( L"\\") , &pRootFolder );
    if( FAILED(hr) )
    {
        printf("Cannot get Root Folder pointer: %x", hr );
        pService->Release();
        CoUninitialize();
        return 1;
    }
    
    //  Check if the same task already exists. If the same task exists, remove it.
    hr = pRootFolder->DeleteTask( _bstr_t( wszTaskName), 0  );
    
    //  Create the task builder object to create the task.
    ITaskDefinition *pTask = NULL;
    hr = pService->NewTask( 0, &pTask );

    pService->Release();  // COM clean up.  Pointer is no longer used.
    if (FAILED(hr))
    {
        printf("Failed to CoCreate an instance of the TaskService class: %x", hr);
        pRootFolder->Release();
        CoUninitialize();
        return 1;
    }
        

    //  ------------------------------------------------------
    //  Get the trigger collection to insert the registration trigger.
    ITriggerCollection *pTriggerCollection = NULL;
    hr = pTask->get_Triggers( &pTriggerCollection );
    if( FAILED(hr) )
    {
        printf("\nCannot get trigger collection: %x", hr );
CLEANUP
        return 1;
    }
  
    //  Add the registration trigger to the task.
    ITrigger *pTrigger = NULL;
    
    hr = pTriggerCollection->Create( TASK_TRIGGER_REGISTRATION, &pTrigger );     
    pTriggerCollection->Release();  // COM clean up.  Pointer is no longer used.
    if( FAILED(hr) )
    {
        printf("\nCannot add registration trigger to the Task %x", hr );
        CLEANUP
        return 1;
    }
    pTrigger->Release();

    //  ------------------------------------------------------
    //  Add an Action to the task.     
    IExecAction *pExecAction = NULL;
    IActionCollection *pActionCollection = NULL;

    //  Get the task action collection pointer.
    hr = pTask->get_Actions( &pActionCollection );
    if( FAILED(hr) )
    {
        printf("\nCannot get Task collection pointer: %x", hr );
        CLEANUP
        return 1;
    }
    
    //  Create the action, specifying that it is an executable action.
    IAction *pAction = NULL;
    hr = pActionCollection->Create( TASK_ACTION_EXEC, &pAction );
    pActionCollection->Release();  // COM clean up.  Pointer is no longer used.
    if( FAILED(hr) )
    {
        printf("\npActionCollection->Create failed: %x", hr );
        CLEANUP
        return 1;
    }

    hr = pAction->QueryInterface( IID_IExecAction, (void**) &pExecAction );
    pAction->Release();
    if( FAILED(hr) )
    {
        printf("\npAction->QueryInterface failed: %x", hr );
        CLEANUP
        return 1;
    }

    //  Set the path of the executable to the user supplied executable.
hr = pExecAction->put_Path( _bstr_t( wstrExecutablePath.c_str() ) );  

//hr = pExecAction->put_Path( (BSTR)wstrExecutablePath );  
    if( FAILED(hr) )
    {
        printf("\nCannot set path of executable: %x", hr );
        pExecAction->Release();
        CLEANUP
        return 1;
    }
    hr = pExecAction->put_Arguments( _bstr_t( L"" ) );  
//    hr = pExecAction->put_Arguments( _bstr_t( L"ArgumentsToYourExecutable--HelpFileToOpen" ) );  
   if( FAILED(hr) )
    {
        printf("\nCannot set arguments of executable: %x", hr );
        pExecAction->Release();
        CLEANUP
        return 1;
    }
    
    //  ------------------------------------------------------
    //  Save the task in the root folder.
    IRegisteredTask *pRegisteredTask = NULL;
    hr = pRootFolder->RegisterTaskDefinition(
            _bstr_t( wszTaskName ),
            pTask,
        TASK_CREATE, 
_variant_t(_bstr_t( L"S-1-5-32-545")),//Well Known SID for \\Builtin\Users group
_variant_t(), 
TASK_LOGON_GROUP,
            _variant_t(L""),
            &pRegisteredTask);
    if( FAILED(hr) )
    {
        printf("\nError saving the Task : %x", hr );
        CLEANUP
        return 1;
    }
    printf("\n Success! Task successfully registered. " );
for (i=0; i<100; i++)//give 10 seconds for the task to start
{
pRegisteredTask->get_State(&taskState);
if (taskState == TASK_STATE_RUNNING)
{
printf("\nTask is running\n");
break;
}
Sleep(100);
}
if (i>= 100) printf("Task didn't start\n");

//Delete the task when done
    hr = pRootFolder->DeleteTask(
            _bstr_t( wszTaskName ),
            NULL);
    if( FAILED(hr) )
    {
        printf("\nError deleting the Task : %x", hr );
        CLEANUP
        return 1;
    }

    printf("\n Success! Task successfully deleted. " );

//  Clean up.
    CLEANUP
    CoUninitialize();
    return 0;
}