如何使用PowerShell簡化組策略的管理?
windows系統中的組策略相信經常使用電腦的用戶應該已經不陌生了吧,但是如何簡化對組策略的管理?使用什么技術呢?下文給出了詳細的描述。
Microsoft組策略技術不是在一夜間就流行起來的,這一技術在某種程度上比較難以理解,而且需要采用ActiveDirectory,在當時,ActiveDirectory服務才剛剛出現,與當時被奉為標準的Account/Resource域毫無相似之處,人們對此都很陌生。而時至今日,組策略幾乎成為每個組織管理Windows®基礎結構的主要手段。我有種感覺,WindowsPowerShell™作為Microsoft***的管理技術,將完全肩負起同樣的使命,成為主要的管理手段。實際上,WindowsPowerShell很可能會使身為組策略管理員的您工作起來更加輕松。
在本文中,我將為您介紹在WindowsPowerShell中,如何直接使用為VBScript(以及通常基于COM的腳本語言)之類的WindowsScriptingHost語言編寫的Microsoft®組策略管理控制臺(GPMC)API在自己特有的環境中簡化組策略的管理。
為組策略任務編寫腳本
幾年前Microsoft發布了GPMC,組策略管理員突然發現有許多簡便易用的功能可供自己使用。具體地說,以組策略為中心的MMC管理單元體現了組策略管理向前邁進了一大步,特別是相對于使用ActiveDirectory®的用戶和計算機而言尤其如此。不僅如此,管理員還可以借助一個全新的API,使用基于COM的語言(如VBScript)來執行組策略管理任務,例如備份和還原組策略對象(GPO)、在域之間遷移GPO、配置有關GPO和鏈接的安全設置以及編寫報告。
但遺憾的是,GPMC并沒有提供對組策略對象內實際已配置設置進行編輯的功能。換句話說,您可以對GPO容器執行操作,例如,讀取GPO版本、讀取修改日期、創建全新的GPO、從不同的域中備份和還原/導入GPO,等等,但卻不能以編程的方式添加或更改GPO的內容,例如添加新的重定向文件夾或新的軟件安裝。通常,您只能使用組策略對象編輯器手動創建GPO并配置所有設置,然后備份該GPO,再將其導入測試環境中。只有當各項功能經過驗證可以正常工作時,您才能將其導入實際的應用環境中。盡管缺少這一功能,但使用腳本而不是與GPMCAPI進行人工交互也為日常的策略組管理節省了大量的時間、精力,同時也避免了不少錯誤。
下一級別
WindowsPowerShell與VBScript之類的腳本語言有何不同?對于初學者而言,WindowsPowerShell是一種外殼程序,至少就目前來說,您可以將其視為一種命令行解釋器。盡管VBScript可以從命令行運行,但VBScript文件卻不能逐行運行。相比之下,WindowsPowerShell腳本則可以作為一系列單獨命令動態地創建。此外,WindowsPowerShell還具有一些功能類似于VBScript中的子例程的函數,它們可在WindowsPowerShell命令提示符下實時地進行創建。
更值得一提的是,WindowsPowerShell基于Microsoft.NETFramework,而VBScript則依賴于早期的COM技術。這意味著,目前有大量的.NET代碼可直接在WindowsPowerShell內使用。
總而言之,利用WindowsPowerShell,您可以獲得完全的腳本支持和交互模式,多種功能集于一身。本文提供的示例均為命令行輸入內容,因此您可以一邊看示例一邊嘗試著輸入,不過,如果您將它們放入WindowsPowerShell腳本文件運行,它們也同樣能正常工作。
使用WindowsPowerShell重新創建早期腳本
在開始采用一項新技術時,您要做的***一件事就是拋棄以前的全部工作成果。您可以使用三種方法從GPMCAPI訪問COM對象,或者主要是重新利用任何早期VBScript。下面是可選的三種方法:
1.使用C#或托管C++等編程語言編寫一個WindowsPowerShellcmdlet。
2.使用WindowsPowerShell訪問MSScript.ocx中的ScriptControl,以封裝早期腳本。
3.將COM調用封裝在可重用的WindowsPowerShell函數中或直接調用COM對象。
我將重點介紹第三種方法,但首先讓我們簡單了解一下所有方法。
創建WindowsPowerShellCmdlet
Microsoft在WindowsPowerShell中放入了大量的cmdlet,這些cmdlet允許您復制文件、將輸出內容格式化、檢索日期和時間等,但您也可以自己創建cmdlet。有關整個過程的完整詳細記錄,請訪問msdn2.microsoft.com/ms714598.aspx。概括地講,主要步驟如下所示:
1.使用.NET編程語言(如C#)創建一個類庫DLL。
2.創建一個新類并從基類cmdlet繼承。
3.設置各種屬性,以確定名稱、用法、輸入參數等,并添加您的代碼。
由于WindowsPowerShell基于.NETFramework,任何作為參數返回或傳遞的類型(如字符串、對象等)在代碼中與在WindowsPowerShell中都是完全相同的,不需要進行任何特殊類型的轉換。
這一解決方案真正強大之處在于您將擁有一種完全受自己支配的編程語言。
使用MSScript.ocx中的ScriptControl對象封裝早期腳本
顯然,您需要VBScript引擎來運行VBScript文件。令人不太注意的是,該引擎是COM對象,而且由于您可以從WindowsPowerShell使用COM對象,因此可以調用VBScript引擎。過程如下所示:
- $scriptControl=New-Object-ComObjectScriptControl
- $scriptControl.Language=‘VBScript’
- $scriptControl.AddCode(
- ‘FunctionShowMessage(messageToDisplay)
- MsgBoxmessageToDisplay
- EndFunction’)
- $scriptControl.ExecuteStatement(‘ShowMessage
- “HelloWorld”’)
如果您在WindowsPowerShell命令行界面(CLI)中輸入此代碼,則會由某參數調用并執行VBScript函數,從而顯示一個帶有文本“HelloWorld”的消息框。
這時有些人可能會想:“太棒了!我已經掌握了從WindowsPowerShell使用COM的技巧,不用再繼續讀這篇文章,馬上開始使用我的早期GPMC腳本填充ScriptControl對象吧。”很遺憾,事情沒有那么簡單。隨著腳本的增大,這種方法很快就會變得非常復雜而繁瑣。
封裝COM對象
由此可見,第三種方法是***的:將COM調用封裝在可重用的WindowsPowerShell函數中,這樣您就能夠在GPMCAPI中使用COM對象。下列代碼將說明如何直接在WindowsPowerShell中創建.NET對象。在此示例中,可以使用FileInfo對象獲得文件的大小:
- $netObject=New-ObjectSystem.IO.FileInfo(
- “C:\boot.ini”)#CreateaninstanceofFileInfo
- #representingc:\boot.ini
請注意,“#”在WindowsPowerShell中用于表示行內注釋。使用此新實例化的FileInfo對象,只要鍵入以下代碼即可輕松獲得boot.ini的大小:
- $netObject.Length#Displaythesizeinbytesofthe
- #fileinthecommandlineinterface
等等,我們不是說要談論COM對象和VBScript轉換嗎?沒錯,但請看以下命令:
- $comFileSystemObject=New-ObjectCComObjectScripting.FileSystemObject
您會發現,此處的語法與我之前從.NETFramework創建本地對象時所用的基本相同,差別只有兩點:***,我添加了CComObject開關,將WindowsPowerShell指向了COM環境,而不是.NET環境。第二,我使用的是COMProgID,而并非.NET構造函數,在本例中為Scripting.FileSystemObject。這里的ProgID是您經常使用的名字。在VBScript中,等同的代碼應為:
- SetcomFileSystemObject=CreateObject(
- “Scripting.FileSystemObject”)
若要使用VBScript獲得該文件的大小,請將上面的代碼行連同以下代碼一起添加到一個文件中:
- SetcomFileObject=comFileSystemObject.GetFile(
- “C:\Boot.ini”)
- WScript.EchocomFileObject.Size
然后,使用Cscript.exe等運行它。在WindowsPowerShell中,您可以按如下所示獲得文件大小(如果您愿意,可以從WindowsPowerShell命令行直接輸入):
- $comFileObject=$comFileSystemObject.GetFile(
- “C:\boot.ini”)
- $comFileObject.Size
當然,我本可以使用管理驅動器內對象的WindowsPowerShellcmdlet對讀取文件大小的VBScript進行轉換,但我想向您展示從WindowsPowerShell訪問COM是多么容易。請注意,雖然我指示WindowsPowerShell創建的是一個COM對象,但實際創建的對象(此處為$comFileSystemObject)是一個封裝了該COM對象并公開了其接口的.NET對象。不過,就本文而言,這樣做沒有任何影響。
運行狀態的WindowsPowerShell
現在,您已經知道如何從WindowsPowerShell訪問COM,接下來,我們要專門介紹組策略。此處的示例將展示一些簡短的代碼段,讓您對如何從WindowsPowerShell使用GPMCAPI有一個大致的概念;您可以從本文相關的代碼下載處,在線為technetmagazine.com/code07.aspx,下載到一整套WindowsPowerShell函數集來管理組策略。圖1所列為下載內容中包含的各種函數。
在閱讀本節內容時,您可以隨意啟動WindowsPowerShell命令行并鍵入命令。但是請記住,有些命令要依賴于前面的命令。也就是說,最初創建的一些對象在以后也會用到,因此,請在同一個WindowsPowerShell會話中執行操作。如果您關閉該會話,則必須從頭開始,重新鍵入所有命令。
好,現在就讓我們先用WindowsPowerShell創建一個新的GPO。Microsoft的組策略團隊隨GMPC提供了許多能夠運行正常的VBScript示例,您可以利用它們加快工作速度。這些示例位于%ProgramFiles%\GPMC\Scripts目錄中,您還可以在該目錄下找到一個包含GPMCAPI文檔的gpmc.chm文件。接下來讓我們看看CreateGPO.wsf腳本,仔細研究一下它為何能夠正常運行。
在腳本的開頭,您會發現這么一行:
- DimGPM
- SetGPM=CreateObject(“GPMgmt.GPM”)
這基本上是所有組策略管理會話或腳本的起點,因為是它實例化了GPMgmt.GPM類,從而使大多數GPMC功能都能夠被訪問。接下來,我們轉而從WindowsPowerShell執行這一操作:
- $gpm=New-Object-ComObjectGPMgmt.GPM
現在,您已獲得了組策略管理的起點,接下來要了解使用它能夠做些什么。通常您需要閱讀相關文檔來獲得此類信息,但WindowsPowerShell提供了一個非常酷的功能。如果鍵入以下一行,您可以得到如圖2中所示的輸出:
圖2Get-Member輸出(單擊該圖像獲得較小視圖)
$gpm|gm
我覺得這個功能真的很棒。請注意觀察,看Get-Member(orgm)cmdlet是如何允許您直接從命令行查看該對象所支持的屬性和方法的。這當然不能等同于閱讀文檔,但如果您不記得參數的確切個數或確切名稱等,該功能可以讓您輕松使用熟悉的對象。請牢記一點,在您查看GPMC文檔節點列表時,會發現它很象GPM對象,而且所有其他類均帶有前綴字母I;這是由于COM的內部工作方式而造成的,我們不需要過分關注這一點;這是專為C++程序員編寫本地COM代碼準備的,用于表示界面和實現它的類之間的差異。另外還要注意,使用GPMCAPI時,只有一個對象需要您采用此方法來創建,那就是GPMgmt.GPM;其他所有對象均使用該GPM對象開始的方法來創建。
現在,我們要繼續創建新的GPO。
圖3說明了創建一個GPO是如此的簡單。請注意,在這里我省去了一些代碼,包括對錯誤的處理(例如,如果您無權創建GPO會出現什么情況),并且我已對域名進行硬編碼,這些都是您應該了解的。
現在,您已經學會如何創建GPO,讓我們打開一個現有的GPO。您仍具有對域$gpmDomain的引用,因此請鍵入以下內容:
- $gpmExistingGpo=$gpmDomain.GetGPO(
- “{31B2F340-016D-11D2-945F-00C04FB984F9}”)
- #OpenanexistingGPObasedonitsGUID,
- #inthiscasetheDefaultDomainPolicy.
- $gpmExistingGpo.DisplayName
- #ShowthedisplaynameoftheGPO,it
- #shouldsayDefaultDomainPolicy
- $gpmExistingGpo.GenerateReportToFile($gpmConstants.ReportHTML,“.\DefaultDomainPolicyReport.html”
上述代碼以HTML的形式完整報告了DefaultDomainPolicy中的各項設置,但是很明顯,您可以使用任何一種方法和屬性(如ModificationTime,它說明該GPO***被修改的時間)來得知該GPO中所有設置的更改時間。
這是非常實用的。例如,您很可能遇到過這類情況:電話瘋狂地響個不停,用戶紛紛來電抱怨說他們的計算機運轉異常。您懷疑這是更改、添加或刪除了GPO設置造成的,但沒有線索,不知該從哪個GPO著手。此時,WindowsPowerShell可以救急!只要在WindowsPowerShell命令行中輸入圖4所示的腳本,就可以獲得過去24小時內更改的所有GPO。
請注意Cge運算符,它表示大于或等于。如果您習慣使用其他腳本或編程語言中的<和>運算符,可能會有些不習慣。但由于這些運算符主要用于重定向,例如,將輸出重定向到文件,因此在WindowsPowerShell中不可將其用作比較運算符。
結束語
圖5所列為將一個GPO的設置復制到另一GPO中的完整腳本。現在,您應該能清楚了解如何將這一新技術用于組策略,如何才能重新使用任何COM對象或利用COM對象的VBScript代碼。
正如組策略一樣,WindowsPowerShell必將成為任何Windows管理環境的組成部分。但面對數百萬行需要進行遷移或維護的VBScript代碼,希望此教程會對您有所幫助。
您可以使用許多資源來改進組策略管理和其他先前使用VBScript的領域,這些資源包括下載內容中的WindowsPowerShell函數,另外TechNet網站上還提供了VBScript到WindowsPowerShell的轉換準則,這一極為實用的準則在您了解VBScript中的等同內容的情況下,可以提示您如何在WindowsPowerShell中執行常見任務。您可以從microsoft.com/technet/scriptcenter/topics/winpsh/convert獲得該轉換準則。
此外,GPMCAPI也提供完整的文檔內容,您可以從組策略網站(microsoft.com/grouppolicy)下載相應的信息。
***但并非最不重要的一點,如果您尚未安裝WindowsPowerShell,那還在等什么呢?現在就從下載吧。祝您愉快!
希望本文介紹的使用PowerShell簡化組策略管理的方法能夠對讀者有所幫助,更多有關組策略的知識還有待于讀者去探索和學習。
【編輯推薦】