嘿,指令 Scripting Guy ! 備份您的事件記錄檔,Windows PowerShell 指令碼

The Microsoft Scripting Guys

作用中! sweltering]、 [自黏]、 [氣息製作 humid 熱度的首先 Jason 和我注意到當我們登陸在中吉隆坡,馬來西亞中取得。 我們已經到達邊欄之前先好記的封包驅動程式必須在線路] 和 [門開啟為我們我們 「 袋 」。 透過領導吉隆坡城市中心 (KLCC) 的棕櫚 tree–lined 道路 brisk 旅行。 只要我們輸入公路,我們可以看到 glistening 標示 KLCC 英哩,離開中每個方向從 [Patronus 塔台的頂端。 我們在一群 Microsoft 員工教導 Microsoft 作業架構 (MOF) 類別的城鎮。

MOF 類別的反白的機場模擬,絕對沒有人會有在第一次嘗試中取得。 但是,類別的點的一部分,處理改進。 我們必須教導類別超過二十次,並沒有人會在第一天成功。 有些類別幾乎沒有它透過進行模擬在類別的最後一天。 直到現在。

第一天結尾是圓形的一種模擬的時間。 Jason,交換知道 glances,為我們提供指示出。 學生 sat 與 rapt 注意,而且再為時鐘已開始 ticking,而不一般大聲執行的周圍變碼的混淆的學生無訊息模式一起到小型的 huddle。 他們討論的五分鐘內快速一個學生開啟膝上型電腦,並開始製作筆記。 然後他們鎮定開啟周圍並不斷在第一輪中獲勝。

他們如何是否能? 他們直接導向所有案例的基本項目的他們注意。 它們會被略過所有不必要的資訊,並建立一個新的程序解決問題。 因為他們專注於核心問題,是可用的任何複雜的工作的規則,而且,所以能夠焦點其能源放在手邊的工作。

規則太複雜的工作會妨礙產能。 今天的指令碼成長超出情況下一個客戶面臨,它們已花費數小時,一天備份 [從各種不同的網路伺服器中的 [事件記錄檔,並將它們複製到中央儲存位置,所以稍後備份到磁帶。 我們有超過其複雜的工作] 規則之後,我們能夠建立自訂的指令碼完全是他們所需要的。 此指令碼儲存在他們有先前花費管理事件記錄檔的人力客戶 10 小時,一週和每年 500 小時。

當我們要從複雜的工作規則的逾時,我們把焦點可以放更多注意和能源任務在手動的方式就是提供 IT 服務。 讓我們來看看一個可以用來備份、 封存,和清除事件記錄檔在網路上的指令碼。 圖 1 ] 所示整個 BackUpAndClearEventLogs.ps1 指令碼。

[圖 1 BackUpAndClearEventLogs.ps1

Param(
       $LogsArchive = "c:\logarchive", 
       $List,
       $computers,
       [switch]$AD, 
       [switch]$Localhost,
       [switch]$clear,
       [switch]$Help
     )
Function Get-ADComputers
{
 $ds = New-Object DirectoryServices.DirectorySearcher
 $ds.Filter = "ObjectCategory=Computer"
 $ds.FindAll() | 
     ForEach-Object { $_.Properties['dnshostname']}
} #end Get-AdComputers

Function Test-ComputerConnection
{
 ForEach($Computer in $Computers)
 {
  $Result = Get-WmiObject -Class win32_pingstatus -Filter "address='$computer'"
  If($Result.Statuscode -eq 0)
   {
     if($computer.length -ge 1) 
        { 
         Write-Host "+ Processing $Computer"
         Get-BackUpFolder 
        }
   } #end if
   else { "Skipping $computer .. not accessible" }
 } #end Foreach
} #end Test-ComputerConnection



Function Get-BackUpFolder
{
 $Folder = "{1}-Logs-{0:MMddyymm}" -f [DateTime]::now,$computer
  New-Item "$LogsArchive\$folder" -type Directory -force  | out-Null
  If(!(Test-Path "\\$computer\c$\LogFolder\$folder"))
    {
      New-Item "\\$computer\c$\LogFolder\$folder" -type Directory -force | out-Null
    } #end if
 Backup-EventLogs($Folder)
} #end Get-BackUpFolder

Function Backup-EventLogs
{
 $Eventlogs = Get-WmiObject -Class Win32_NTEventLogFile -ComputerName $computer
 Foreach($log in $EventLogs)
        {
            $path = "\\{0}\c$\LogFolder\$folder\{1}.evt" -f $Computer,$log.LogFileName
            $ErrBackup = ($log.BackupEventLog($path)).ReturnValue
            if($clear)
               {
                if($ErrBackup -eq 0)
                  {
                   $errClear = ($log.ClearEventLog()).ReturnValue
                  } #end if
                else
                  { 
                    "Unable to clear event log because backup failed" 
                    "Backup Error was " + $ErrBackup
                  } #end else
               } #end if clear
            Copy-EventLogsToArchive -path $path -Folder $Folder
        } #end foreach log
} #end Backup-EventLogs

Function Copy-EventLogsToArchive($path, $folder)
{
 Copy-Item -path $path -dest "$LogsArchive\$folder" -force
} # end Copy-EventLogsToArchive

Function Get-HelpText
{
 $helpText= `
@"
 DESCRIPTION:
 NAME: BackUpAndClearEventLogs.ps1
 This script will backup, archive, and clear the event logs on 
 both local and remote computers. It will accept a computer name,
 query AD, or read a text file for the list of computers. 

 PARAMETERS: 
 -LogsArchive local or remote collection of all computers event logs
 -List path to a list of computer names to process
 -Computers one or more computer names typed in
 -AD switch that causes script to query AD for all computer accounts
 -Localhost switch that runs script against local computer only
 -Clear switch that causes script to empty the event log if the back succeeds
 -Help displays this help topic

 SYNTAX:
 BackUpAndClearEventLogs.ps1 -LocalHost 

 Backs up all event logs on local computer. Archives them to C:\logarchive.

 BackUpAndClearEventLogs.ps1 -AD -Clear

 Searches AD for all computers. Connects to these computers, and backs up all event 
 logs. Archives all event logs to C:\logarchive. It then clears all event logs 
 if the backup operation was successful. 

 BackUpAndClearEventLogs.ps1 -List C:\fso\ListOfComputers.txt

 Reads the ListOfComputers.txt file to obtain a list of computer. Connects to these 
 computers, and backs up all event logs. Archives all event logs to C:\logarchive. 

 BackUpAndClearEventLogs.ps1 -Computers "Berlin,Vista" -LogsArchive "\\berlin\C$\fso\Logs"

 Connects to a remote computers named Berlin and Vista, and backs up    all event 
 logs. Archives all event logs from all computers to the path c:\fso\Logs directory on 
   a remote computer named Berlin. 

BackUpAndClearEventLogs.ps1 -help

Prints the help topic for the script
"@ #end helpText
  $helpText
}

# *** Entry Point To Script ***

If($AD) { $Computers = Get-ADComputers; Test-ComputerConnection; exit }
If($List) { $Computers = Get-Content -path $list; Test-ComputerConnection; exit }
If($LocalHost) { $computers = $env:computerName; Test-ComputerConnection; exit }
If($Computers) 
  { 
   if($Computers.Contains(",")) {$Computers = $Computers.Split(",")} 
   Test-ComputerConnection; exit 
  }
If($help) { Get-HelpText; exit }
"Missing parameters" ; Get-HelpText

首先我們執行指令碼是在 BackUpAndClearEventLogs.ps1 中使用參數陳述式來建立的指令碼的某些命令列參數會像這樣:

Param(
       $LogsArchive = "c:\logarchive", 
       $List,
       $Computers,
       [switch]$AD, 
       [switch]$Localhost,
       [switch]$Clear,
       [switch]$Help
     )

我們使用數個參數中提供的彈性,指令碼。 -LogsArchive 參數用來定義的事件記錄檔保存位置。 我們將此預設位置 C:\ 磁碟機,但藉由使用-LogsArchive,您可以選擇適合您的電腦環境的任何位置。

-清單參數可讓您提供的文字檔案透過指令碼的電腦清單。 這個參數必須包含電腦名稱一個文字檔案完整路徑。 文字檔案的語法是簡單的 ; 您只將您想要使用它自己個別的線條上的每個電腦的名稱。

參數可讓您提供的電腦從命令列清單,當您執行指令碼-電腦。 若要將這個參數,您將在一組引號之間以逗號 (,) 來分隔的電腦名稱。 理想的情況下,您可以使用這個參數如果您要檢查只是少數的電腦。

下一步是四個切換的參數。 酷之一就是呼叫可讓您查詢的電腦清單的 Active Directory –AD 切換的參數。 它可以使用此參數,如果您想要檢查大量網路上所有電腦上的事件記錄檔。 就當然在大型網路上這可能要花很長的時間。 如果您想要對您的本機電腦執行指令碼,使用-Localhost 參數,它可指示要對本機電腦執行指令碼。 besides 備份事件記錄檔,而且您封存它們到中央位置,可以也空藉由使用-清除事件記錄檔的內容切換參數。 若要說明資訊執行指令碼使用的說明]。 我們現在有第一個函式我們的指令碼。 取得 ADComputers 函式是用來擷取所有的電腦帳戶在 Active Directory 中的清單一個查詢。 這個函式並不需要任何輸入的參數。 當呼叫此函式時,它便會使用新增物件] 指令程式,來建立從 Microsoft.NET 的 DirectoryServices.DirectorySearcher 類別的執行個體。 我們不要傳送任何資訊到 [新增物件的 Cmdlet,DirectoryServices.DirectorySearcher 類別使用預設建構函式建立。 新的 DirectorySearcher 類別儲存在的 $ ds 變數中,如下所示:

Function Get-ADComputers
{
$ds = New-Object DirectoryServices.DirectorySearcher

我們有 DirectorySearcher 類別的執行個體之後,我們可以使用 Filter 屬性來建立搜尋篩選,以減少擷取的項目數目。 LDAP 搜尋篩選條件會記錄在" 搜尋篩選條件語法." 我們想要的屬性稱為 ObjectCategory,我們要尋找的值為 「 電腦 」。 我們已經建立我們的篩選器之後,我們會使用從 DirectorySearcher 物件 FindAll 方法:

 $ds.Filter = "ObjectCategory=Computer"
$ds.FindAll() | 

從 FindAll 方法結果被管線到 ForEach 物件指令程式用來逐一查看集合的 DirectoryEntry FindAll 所傳回的物件。 在指令碼區塊的大方括號包圍中我們可以使用 $ _ 自動變數來參照至目前的項目上管線。 我們存取 DirectoryEntry 物件的屬性,並傳回該 dnshostname:

     ForEach-Object {$_.Properties['dnshostname']}
} #end Get-ADComputers

現在我們將建立測試 ComputerConnection 函式來確保電腦是在 [網路] 及 [執行]。 將防止逾時問題並讓指令碼更有效率。 我們開始使用函數關鍵字,指定函式的名稱,然後開啟指令碼區塊:

Function Test-ComputerConnection
{

接下來我們要逐步解說的我們會做 $ 電腦變數內所儲存的電腦集合 ForEach 陳述式使用列舉值為 $ 電腦變數。 我們再開啟指令碼區塊使用左邊的大括號:

 ForEach($Computer in $Computers)
{

我們要使用 WMI 類別 Win32_PingStatus 來抓取遠端電腦。 若要執行此動作我們必須使用 Get WmiObject 指令程式,並指定類別 Win32_PingStatus 並建立篩選器,檢查以查看它是否符合 $ 電腦變數中儲存值的 [位址] 屬性。 如下所示,我們可以存放在變數名稱 $ 結果的這個 WMI 查詢的結果:

  $Result = Get-WmiObject -Class Win32_PingStatus -Filter "address='$computer'"

現在我們評估 WMI 查詢所傳回的狀態碼。 如果狀態的程式碼是等於零,時沒有發生錯誤,電腦啟動且正在執行:

  If($Result.Statuscode -eq 0)
   {

因為某些奇怪原因在我的電腦上查詢傳回虛設的電腦,它會評估為存在但沒有名稱。 若要移除的幽靈電腦,新增某行的以確保電腦名稱是至少一個字元長的程式碼:

     if($computer.length -ge 1) 
        { 

接下來我們提供的意見反應給使用者藉由顯示狀態訊息指出我們正在處理電腦。 我們可以使用寫入主機指令程式來提供此意見反應:

         Write-Host "+t Processing $Computer"

現在我們呼叫 Get BackupFolder 函式以尋找要用於備份的資料夾:

         Get-BackUpFolder 
        }
   } #end if

如果電腦是可存取的沒有在嘗試備份事件記錄檔,因為我們無法到達點。 我們顯示狀態訊息,指出我們將略過電腦,並結束函式:

   else { "Skipping $computer .. not accessible" }
 } #end Foreach
} #end Test-ComputerConnection

之後評估電腦的存取範圍,就是建立取得 BackupFolder 函式的時候:

Function Get-BackupFolder
{

下的一行程式碼是有點 odd-looking 因此有點混淆:

$Folder = "{1}-Logs-{0:MMddyymm}" -f [DateTime]::now,$computer

我們會使用格式運算子 (-f) 來執行我們將使用做為資料夾名稱的字串中的某些值替代。 字串包含數字 1 在一對大括號前後連字號,另一對大括號封入的數字 0 跟隨一連串的字母的文字記錄檔。

讓我們看一次的此一步驟。 –f 運算子會執行一個替代的字串中所包含的值。 如同陣列,第一個項目開始於 0,1 在第二個。 –f 運算子的右邊項目是放在適當的插槽,在左邊的替代值。

到達回主要的指令碼之前, 讓我們花一點時間以釐清如何在指令碼中是替代的範例。 請注意我們如何替換為 {0} 部分文字及 「 兩個 {1} 部分在下列程式碼中:

PS C:\Users\edwilson> $test = "{0}-first-{1}-second" -f "one","two"
PS C:\Users\edwilson> $test
one-first-two-second

重新我們可能應該有排列我們的程式碼,讓第一個項目已在第一個位置。 而是,我們撰寫它,第二個元素是在第一個的位置而第一個項目在第二個位置。 如果我們有移動位元下, 一行程式碼項目會有尋找像這樣:

PS C:\Users\edwilson> $computer = "localhost"
PS C:\Users\edwilson> $Folder = "{0}-Logs-{1:MMddyymm}" -f $computer, [DateTime]::now
PS C:\Users\edwilson> $Folder
localhost-Logs-04070938

在上述命令中的 {1:MMddyymm} 用來提供目前的日期和時間。 我們不希望因為它是太長,並且包含資料夾名稱不允許的字元在這裡顯示的日期時間物件的一般的顯示。 日期時間物件的預設顯示是 2009 4 月格林威治時間,星期二 6:45:37 PM。

在我們的指令碼中的冒號字元的字母模式用來控制,將會顯示日期時間值的方法。 在我們的案例中月份後面跟著一天的年份,分鐘數。 這些日期時間格式字串會記載在 自訂 DateTime 格式字串. 它們也都在 「 Microsoft 指令碼 」,將新的發行項中有所討論" 如何可以我檢查我的事件記錄檔的大小,然後備份和保存它是否超過半滿?"

接下來,我們建立事件記錄檔的封存資料夾。 若要建立資料夾,我們可以使用新的項目指令程式,並指定類型為目錄。 我們使用變數的 $ LogsArchive 和我們儲存在 $ 資料夾變數以建立保存檔路徑中的模式。 我們使用-強制參數來啟用的完整的路徑建立,在必要時。 因為我們不感興趣這個命令的意見我們管線將結果 [Out-Null 此處所顯示的指令程式:

New-Item "$LogsArchive\$folder" -type Directory -force | Out-Null

我們也需要判斷電腦上是否存在記錄檔資料夾。 若要如此我們使用 [測試路徑的 Cmdlet 如下:

  If(!(Test-Path "\\$computer\c$\LogFolder\$folder"))
    {

在的測試路徑 Cmdlet 會傳回一個 $ true 或 $ 布林值,則為 False。 它會要求,有記錄檔資料夾? 將不測試路徑指令程式的前面的運算子 (!) 表示我們想要只当資料夾不存在。

如果在遠端電腦上不存在記錄檔資料夾,我們會使用新的項目指令程式,來建立它。 我們有 LogFolder 的硬式編碼值,但您可以變更此。 在前一個新增的項目指令程式為我們使用-強制參數來建立完整的路徑和管線將結果 [Out-Null 指令程式:

      New-Item "\\$computer\c$\LogFolder\$folder" -type Directory -force | out-Null
    } #end if

我們現在要呼叫備份 EventLogs 函式會執行實際的事件記錄檔備份。 我們將傳遞路徑儲存在 $ 資料夾變數中,當我們呼叫此函式:

 Backup-EventLogs($folder)
} #end Get-BackUpFolder

接下來,我們會建立備份 EventLogs 函式:

Function Backup-EventLogs
{

我們可以使用 Win32_NTEventLogFile WMI 類別來執行實際的備份。 若要執行此動作我們可以呼叫取得 WmiObject 指令程式,並賦予 Win32_NTEventLogFile 類別名稱,以及 $ 電腦變數中所包含的電腦名稱。 我們可以儲存所產生的 WMI 物件在 $ Eventlogs 變數:

$Eventlogs = Get-WmiObject -Class Win32_NTEventLogFile -ComputerName $computer

藉由執行一般、 未篩選的 WMI 查詢,我們會傳回代表電腦上的每個事件記錄檔的事件記錄檔物件。 這些是傳統 [圖 2 ] 所示的事件日誌。

若要使用這些事件記錄檔,我們要使用 ForEach 陳述式來逐步解說的 WMI 物件集合。 我們使用為我們的列舉值的變數 $ 記錄檔來協助保持我們的位置,如我們逐步集合:

fig02.gif

[圖 2 傳統事件記錄檔擷取 Win32_NTEventLogFile

 ForEach($log in $EventLogs)
        {

我們現在需要建立路徑。 再一次我們會使用格式運算子來執行一些模式替代。 {0} 是電腦名稱,用於事件記錄檔路徑中的預留位置。 {1} 是預留位置,用來保存記錄檔名稱會在事件記錄檔備份時使用:

            $path = "\\{0}\c$\LogFolder\$folder\{1}.evt" -f $Computer,$log.LogFileName

現在,我們從 Win32_NTEventLogFile WMI 類別呼叫 BackupEventLog 方法。 我們將路徑傳遞至 BackupEventLog 方法,並擷取方法呼叫的傳回值。 我們在 $ ErrBackup 變數,如下所示儲存傳回值:

            $ErrBackup = ($log.BackupEventLog($path)).ReturnValue

如果指令碼執行與 –clear 切換的變數會是存在,而且我們在這種情況下需要清除事件記錄檔清除 $。 因此,我們使用 if 陳述式來清除變數 $ 是否存在:

            if($clear)
               {

我們空的事件記錄檔之前先我們想要確保事件記錄檔已成功備份。 若要執行此動作,我們會檢查 $ ErrBackup 變數中儲存值。 如果是等於零我們知道備份作業期間發生任何錯誤並且安全地繼續清空事件記錄檔:

                if($ErrBackup -eq 0)
                  {

我們從 Win32_NTEventLogFile WMI 類別呼叫 ClearEventLog 方法,並在 ReturnValue 擷取方法呼叫。 我們可以儲存在 ReturnValue 在 $ errClear 變數,如下所示:

                   $errClear = ($log.ClearEventLog()).ReturnValue
                  } #end if

如果 $ ErrBackup 變數的值不等於 0,我們做不清除出事件記錄檔。 而是,我們會顯示一個狀態訊息,指出我們無法清除事件記錄檔,因為備份作業失敗。 若要提供其他疑難排解資訊,我們顯示狀態程式碼,從備份作業,所以擷取:

                else
                  { 
                    "Unable to clear event log because backup failed" 
                    "Backup Error was " + $ErrBackup
                  } #end else
               } #end if clear

接下來,我們將事件記錄檔複製到封存位置。 若要執行此動作我們呼叫複製 EventLogsToArchive 函式並賦予路徑到事件記錄檔及資料夾的目的地:

            Copy-EventLogsToArchive -path $path -Folder $Folder
        } #end foreach log
} #end Backup-EventLogs

複製 EventLogsToArchive 使用複製的項目指令程式,來將事件記錄檔複製到封存位置。 我們再次使用-強制參數來建立資料夾,如果不存在:

Function Copy-EventLogsToArchive($path, $folder)
{
 Copy-Item -path $path -dest "$LogsArchive\$folder" -force
} # end Copy-EventLogsToArchive

現在我們需要建立一些指令碼的說明文字。 若要這樣做,我們建立將說明資訊儲存在單一變數中取得 HelpText 函式: $ helpText。 [說明] 文字會寫入為這裡-字串,讓我們依我們想要顯示在螢幕上沒有關於自己的逸出引號文字格式。 這樣就讓我們輸入大的字串,如 [圖 3 ] 中來得簡單許多。

[圖 3 取得 HelpText 函式

Function Get-HelpText
{ 
 $helpText= `
@"
 DESCRIPTION:
 NAME: BackUpAndClearEventLogs.ps1
 This script will backup, archive, and clear the event logs on 
 both local and remote computers. It will accept a computer name,
 query AD, or read a text file for the list of computers. 
 PARAMETERS: 
 -LogsArchive local or remote collection of all computers event logs
 -List path to a list of computer names to process
 -Computers one or more computer names typed in
 -AD switch that causes script to query AD for all computer accounts
 -Localhost switch that runs script against local computer only
 -Clear switch that causes script to empty the event log if the back succeeds
 -Help displays this help topic
 SYNTAX:
 BackUpAndClearEventLogs.ps1 -LocalHost 
Backs up all event logs on local computer. Archives them to C:\logarchive.
 BackUpAndClearEventLogs.ps1 -AD -Clear
 Searches AD for all computers. Connects to these computers, and backs up all event 
 logs. Archives all event logs to C:\logarchive. It then clears all event logs if the
 backup operation was successful. 
 BackUpAndClearEventLogs.ps1 -List C:\fso\ListOfComputers.txt
 Reads the ListOfComputers.txt file to obtain a list of computer. Connects to these 
 computers, and backs up all event logs. Archives all event logs to C:\logarchive. 
 BackUpAndClearEventLogs.ps1 -Computers "Berlin,Vista" -LogsArchive "\\berlin\C$\fso\Logs"
 Connects to a remote computers named Berlin and Vista, and backs up all event 
 logs. Archives all event logs from all computers to the path c:\fso\Logs directory on 
 a remote computer named Berlin. 
 BackUpAndClearEventLogs.ps1 -help
 Prints the help topic for the script
 "@ #end helpText

若要顯示 [說明] 文字,我們可以呼叫變數名稱:

  $helpText
}

下一步],我們剖析命令列輸入如下:

If($AD) { $Computers = Get-ADComputers; Test-ComputerConnection; exit }
If($List) { $Computers = Get-Content -path $list; Test-ComputerConnection; exit }
If($LocalHost) { $computers = $env:computerName; Test-ComputerConnection; exit }

如果 $ AD 變數的話,指令碼執行-AD 的參數,我們因此填入 $ 電腦變數取得 ADComputers 函式取得資訊。 然後,我們呼叫測試 ComputerConnection 函式會判斷電腦是否線上並回復設定事件記錄檔。 然後我們會結束指令碼。 如果 $ 清單變數沒有,我們會使用取得內容指令程式,來讀取文字檔案,並填入 $ 電腦變數。 然後我們呼叫測試 ComputerConnection 函式,並結束指令碼。 如果 $ 本機主機變數存在,我們會藉由讀取直接從電腦名稱的環境變數的值填入 $ 電腦變數。 然後我們呼叫測試 ComputerConnection 函式,並結束指令碼。

如果 $ 電腦變數存在,這表示已執行指令碼,並且從命令列提供了電腦名稱。 我們需要將這些電腦名稱分成陣列。 若要執行此動作,我們會使用字串物件的分割方法:

If($Computers) 
  { 
   if($Computers.Contains(",")) {$Computers = $Computers.Split(",")} 
   Test-ComputerConnection; exit 
  }

如果已使用的說明參數執行指令碼,我們呼叫 Get HelpText 函式,顯示 [說明],並結束指令碼:

If($help) { Get-HelpText; exit }

若存在沒有參數,則我們會顯示訊息狀態,我們遺失的參數,然後呼叫取得說明的測試函式:

"Missing parameters" ; Get-HelpText

BackupAndClearEventLogs.ps1 指令碼可以輕易地適用於在您的網路上提供您的需求。 就例如您可以修改 Active Directory 查詢,以便它會傳回特定組織單位只有伺服器,或您可以新增的其他 WMI 查詢,以進一步篩選出處理的電腦。 我們希望您喜歡指令碼,可以用您的工作位置。 瀏覽我們和 scripters 的社群, 指令碼中心在其中您可以攔截我們每日嗨 Scripting Guy ! 文件。

Ed Wilson ,已知指令碼專家使用者是八個包括 Windows PowerShell Scripting Guide Microsoft Press (2008) 的書籍和 Microsoft Windows PowerShell Step by Step Microsoft 按的作者 (2007)。 Ed 保留超過 20 個以上的業界認證包括 Microsoft 認證系統工程師 (MCSE) 和認證資訊系統安全性專業人員 (CISSP)。 在他備用的時間內他喜歡 woodworking underwater 相片,以及 scuba diving。 然後茶。

Craig Liebendorfer 就是 wordsmith longtime Microsoft Web 編輯器。 Craig 仍然不敢相信還有時應付他使用文字每一天的工作。 之一他最愛是 irreverent 幽默,他應該放在這裡的右邊。 他認為他最大的成就為 magnificent 女兒的生活。