嗨,Scripting Guy!

Hey,Scripting Guy!

歡迎使用全新的 TechNet 專欄,Microsoft Scripting Guys 會在此為您解答有關系統管理指令碼的常見問題。您有關於系統管理指令碼方面的問題嗎?請將電子郵件傳送到 scripter@microsoft.com。我們無法保證能夠逐一回答每個問題,不過我們會盡力而為。

今天的問題:可以使用指令碼編輯 .INI 檔案嗎?


可以使用指令碼編輯 .INI 檔案嗎?

嗨,Scripting Guy!可以使用指令碼編輯 .INI 檔案嗎?

-- MZ

MZ,您好。可以的,您「可以」使用指令碼編輯 .INI 檔案 (或任何種類的文字檔)。您必須使用的方法可能不是世界上最聰明的程序,但是它肯定行得通。這就是我們想要的,不是嗎?

在我們討論編輯 .INI 檔的原因之前,先看一下範例檔案。這個範例剛好是 Adobe Reader 的部份 .INI 檔,雖然大部份 .INI 檔看起來都相似:

[OEM Install]
DisplayWelcomeDlg=YES
DisplayEULA=NO
DisplayTypeOfInstallDlg=NO
DisplaySelectDestDirDlg=YES
DisplayCustomDlg=NO
DisplayUserInfoDlg=NO
DisplayConfirmRegDlg=NO
DisplayStartCopyDlg=NO
DisplayFinishDlg=NO
DisplayFinalMessage=YES
DisplayRebootDlg=YES
ProgGroupName=
DefaultDestDir=
UserName=
UserCompanyName=
UserSerialNumber=

假設我們要對這個檔案做兩件事情:我們要將 DisplayWelcomeDlg 變更為 NO,且要將 UserName 設定為 Ken Myer。理想的狀況是,我們撰寫一個指令碼簡單搜尋 DisplayWelcomeDlg 的檔案、然後將指派的值變更為 NO、搜尋 UserName 屬性、將值設定為 Ken Myer,然後再儲存變更。令人遺憾的是,FileSystemObject (用來讀取並修改文字檔的技術) 並沒有這些功能。所以,我們必須以強迫方式編輯 .INI 檔。也許此時您還是不太瞭解,但希望在閱讀完這個專欄後,您就會瞭解我們所說的意思。

我們將示範一個完整的指令碼,並解釋它的作用:

Const ForReading = 1
Const ForWriting = 2
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile("sample.ini", ForReading)
Do Until objTextFile.AtEndOfStream
    strNextLine = objTextFile.Readline
    intLineFinder = InStr(strNextLine, "DisplayWelcomeDlg")
    If intLineFinder <> 0 Then
        strNextLine = "DisplayWelcomeDlg=NO"
    End If
    intLineFinder = InStr(strNextLine, "UserName")
    If intLineFinder <> 0 Then
        strNextLine = "UserName=Ken Myer"
    End If
    strNewFile = strNewFile & strNextLine & vbCrLf
Loop
objTextFile.Close
Set objTextFile = objFSO.OpenTextFile("sample.ini", ForWriting)
objTextFile.WriteLine strNewFile
objTextFile.Close

先定義兩個常數:ForReading 及 ForWriting。在讀取及寫入 .INI 檔時需要這兩個常數。請注意,沒有名為 ForEditing 的常數;原因是 FileSystemObject 不允許您同時讀取及寫入一個檔案。我們反而是要開啟檔案並讀取,然後關閉檔案,再重新開啟來寫入。此時,我們才能儲存變更。就像我們說的,它不是一項最聰明的系統,但是它就是可以用。

定義完兩個常數後,開啟 .INI 檔 (sample.ini) 讀取。接下來,我們設定一個 Do 迴圈,逐行讀取檔案,直到沒有內容可讀取為止 (當 AtEdnOfStream 屬性為 TRUE)。使用 Readline 方法開始讀取檔案的第一行,然後將那行儲存在 strNextLine 變數中。

現在開始變得有趣了。如稍早所說,FileSystemObject 不允許您搜尋檔案;因此,我們必須逐行讀取檔案,然後分別檢查每一行是不是您要的那行。下面的這行程式碼就是在作這個工作:

intLineFinder = InStr(strNextLine, "DisplayWelcomeDlg")

這個程式碼使用 InStr 方法來查看是否可在 strNextLine 變數中找到 DisplayWelcomeDlg 字串 (請記住,這個變數包含我們剛讀取的 .INI 行)。InStr 的作用是會報告找到目標字串所在的字元位置。例如,假設 strNextLine 等於下列:

xxxxxDisplayWelcomeDlgxxxxx

您可以看見,這個指令碼看起來比較短且清楚,也少了很多雙引號。那為什麼我們不建議您在 XP 或 Windows 2003 上使用這個指令碼?如果您想這麼作是可以的。不過,使用 Shell 物件擷取磁碟配額資訊有兩項限制。第一,Shell 物件指令碼只可針對本機電腦執行;和 WMI 指令碼不同的是,您無法連接到遠端機器並傳回磁碟配額資訊。

第二,您一次只能擷取一台磁碟機的配額資訊。使用 WMI,您可以傳回包含電腦上所有磁碟機之磁碟配額資訊的集合。使用 Shell 物件,您將必須撰寫程式碼取得磁碟機 C: 的資料,然後撰寫程式碼取得磁碟機 D: 的資料,然後再寫程式碼取得磁碟機 E: 的資料等等。

intLineFinder = InStr(strNextLine, "DisplayUserInfoDlg")

您看懂了嗎?現在查看 .INI 檔的第一行,但那不是我們要的。那是要跳過,然後繼續嗎?不,不要跳過。我們要使用這行程式碼:

strNewFile = strNewFile & strNextLine & vbCrLf

這個程式碼會在記憶體中建立全新的 .INI 檔,並將新檔案儲存在 strNewFile 變數中。第一次執行迴圈時,strNewFile 會包含目前在 strNewFile (第一次執行時沒有任何內容) 中的所有內容、「加上」在 strNextLine 變數中的所有內容 ([OEM Install]),再「加上」歸位換行 (vbCrLf)。換句話說,重覆一次之後,strNewFile 看起來會像這樣:

[OEM Install]

很有趣,對吧?

現在,我們進行迴圈然後讀取文字檔的第二行 (DisplayWelcomeDlg=YES)。猜猜看會如何?這次 InStr 找到目標字串,而 intLineFinder 變數會等於 1 (因為 DisplayWelcomeDlg 在第一個字元位置開始)。因為 intLineFinder 不等於 0,所以現在進入第一個 If-Then 區塊。在區塊中,只要變更 strNewLine 的值:

strNextLine = "DisplayWelcomeDlg=NO"

現在,變數中沒有從 .INI 檔讀入的文字;它現在包含了修改過的文字:

DisplayWelcomeDlg=NO

換句話說,我們並沒有真正編輯 DisplayWelcomeDlg 屬性的值。我們只是丟棄舊行,然後用全新的一行取代。不過,最後的結果跟我們直接編輯屬性值並沒有不同。

進入到迴圈的尾端時,strNewFile 變數看起來會像這樣:

[OEM Install]
DisplayWelcomeDlg=NO

看到它的功用了嗎?我們會繼續逐行讀完 .INI 檔,同時逐行地建立 strNewFile 變數。在指令碼完成前,strNewFile 會包含此項資訊:

[OEM Install]
DisplayWelcomeDlg=NO
DisplayEULA=NO
DisplayTypeOfInstallDlg=NO
DisplaySelectDestDirDlg=YES
DisplayCustomDlg=NO
DisplayUserInfoDlg=NO
DisplayConfirmRegDlg=NO
DisplayStartCopyDlg=NO
DisplayFinishDlg=NO
DisplayFinalMessage=YES
DisplayRebootDlg=YES
ProgGroupName=
DefaultDestDir=
UserName=Ken Myer
UserCompanyName=
UserSerialNumber=

沒錯,這和我們在修改的 .INI 檔中想要的資訊完全相同。

我們已經在往目標前進了。接下來關閉 sample.ini 檔,然後馬上重新開啟「寫入」(不是很高明的方法,但必須這麼做)。然後使用下列這行程式碼將 sample.ini 中的現有文字取代為儲存在 strNewFile 變數中的資訊:

objTextFile.WriteLine strNewFile

再次關閉檔案時,就會儲存資料,這就順利修改了 .INI 檔。

我們可不會說這是最好程式碼了;因為它不是。有些 .INI 檔可能無法使用這個功能。但是說實話,這可能是您能做到的最好狀況了,至少有工具內建在作業系統中。


如需詳細資訊

查看嗨,Scripting Guy!- 過往文件

 

回到頁首 回到頁首