VBScriptでApacheOpenOffice3.41の設定用XMLファイルを変更して保存
ApacheOpenOffice3.41の設定を全ユーザで変更しようと思っています。 ApacheOpenOfficeの設定はXMLファイルなので、グループポリシーのログオンスクリプトを使い、VBScriptで設定ファイルを修正して保存するという仕掛けです。
なお、毎回ログオン時に適用すると、ユーザが意図的に設定を変更しても再ログイン時に元に戻ってしまうので、フラグを設定したテキストファイルを置いておき、既に過去のログオン時にスクリプト実行済みなら、実行しないということもさせようと思っています。
VBScriptでは Msxml2.DOMDocument を使ってXMLファイルの変更ができるようです。
ただ完全にDOMで一般的なメソッドに対応しているわけでは無いようで苦労しました。
(例えば、element.getAttribute メソッドなどはありません。element.Attributes をループさせて目的の属性までたどり着く必要があります)
Xpath(名前空間接頭辞)で直接ノードを指定したかったんですが、どうもVBScriptではうまくノードの指定が出来ませんした。 なので、ひたすらループでぶん回すという力技にしています。
とりあえずVBScriptをアップしておきます。
Option Explicit '設定ファイルのバージョン。設定ファイルを修正し、適用させたい場合はインクリメントすること。 Const ver = 1 Dim objWshShell , objFileSys Set objWshShell = WScript.CreateObject("WScript.Shell") Dim stmSettingFile , stmVerFile '設定ファイルのパス stmSettingFile = objWshShell.SpecialFolders.Item("AppData") & "\OpenOffice.org\3\user\registrymodifications.xcu" 'バージョンファイルのパス stmVerFile = objWshShell.SpecialFolders.Item("AppData") & "\OpenOffice.org\3\user\setting_ver.txt" '設定値 Dim strSetNameValues(3) '(0)item oor:pathの値 (1)prop oor:nameの値 (2)valueへの設定値 (3)設定が終わったかどうかのフラグ strSetNameValues(0) = Array("/org.openoffice.Office.Linguistic/SpellChecking" , "IsSpellAuto","false",false) strSetNameValues(1) = Array("/org.openoffice.Office.Common/Save/Document" , "AutoSave","true",false) strSetNameValues(2) = Array("/org.openoffice.Office.Common/Save/Document" , "LoadPrinter","false",false) strSetNameValues(3) = Array("/org.openoffice.Office.Common/Save/ODF" , "DefaultVersion","3",false) strSetNameValues(4) = Array("/org.openoffice.Office.Common/Security/Scripting" , "MacroSecurityLevel","1",false) strSetNameValues(5) = Array("/org.openoffice.Office.Common/AutoCorrect" , "CapitalAtStartSentence","false",false) strSetNameValues(6) = Array("/org.openoffice.Office.Common/AutoCorrect" , "DoubleQuoteAtEnd","0",false) strSetNameValues(7) = Array("/org.openoffice.Office.Common/AutoCorrect" , "DoubleQuoteAtStart","0",false) strSetNameValues(8) = Array("/org.openoffice.Office.Common/AutoCorrect" , "DoubleQuoteAtStart","0",false) strSetNameValues(9) = Array("/org.openoffice.Office.Common/AutoCorrect" , "SetInetAttribute","false",false) strSetNameValues(10) = Array("/org.openoffice.Office.Common/AutoCorrect" , "SingleQuoteAtEnd","false",false) strSetNameValues(11) = Array("/org.openoffice.Office.Common/AutoCorrect" , "SingleQuoteAtStart","false",false) strSetNameValues(12) = Array("/org.openoffice.Office.Common/AutoCorrect" , "TwoCapitalsAtStart","false",false) Set objFileSys = CreateObject("Scripting.FileSystemObject") '設定ファイルの存在確認 SettingFileExistCheck objFileSys , stmSettingFile 'バージョンのチェック。 VersionCheck objFileSys WScript.echo "バージョン古いから更新する。スクリプト続行。" 'XMLファイル更新 UpdateXMLNode stmSettingFile 'バージョンファイル書込 WriteVersionFile objFileSys '----------------------------------------------------------- 'XMLファイルノード更新。 '----------------------------------------------------------- Sub UpdateXMLNode(stmSettingFile ) Dim objXML,rtResult 'XML操作オブジェクト Set objXML = CreateObject("Msxml2.DOMDocument.3.0") 'XML読み込み rtResult = objXML.load( stmSettingFile ) If rtResult = False Then WScript.Echo "ノードなし" End If Dim nodeRoot , nodeItems , nodeItem , nodeProps ,nodeProp , nodeValue 'rootノード取得 Set nodeRoot = objXml.documentElement 'itemノード取得 Set nodeItems = nodeRoot.getElementsByTagName("item") 'itemノードをループ For Each nodeItem In nodeItems Dim i , j 'itemノードの属性をループ For i = 0 To nodeItem.Attributes.Length - 1 'WScript.Echo "nodeItem:" & nodeItem.nodeName '設定ファイル値の配列をループ For j = 0 To UBound(strSetNameValues) 'oor:pathがヒットした時 If nodeItem.Attributes(i).Name = "oor:path" And nodeItem.Attributes(i).Text = strSetNameValues(j)(0) Then 'propノードを取り出す Set nodeProps = nodeItem.getElementsByTagName("prop") 'propノードをループ For Each nodeProp In nodeProps 'oor:vがヒットした時 If nodeProp.Attributes(i).Name = "oor:name" And nodeProp.Attributes(i).Text = strSetNameValues(j)(1) Then WScript.Echo nodeProp.Attributes(i).Name & "/" & nodeProp.Attributes(i).Text Set nodeValue = nodeProp.getElementsByTagName("value") WScript.Echo "変更前 value = " & nodeValue(0).Text '設定値更新 nodeValue(0).Text = strSetNameValues(j)(2) '設定変えたフラグを設定 strSetNameValues(j)(3) = true WScript.Echo "変更後 value = " & nodeValue(0).Text End If Next End If Next Next Next '設定が終わっていない項目は、ノードが無いことになるので、ノード追加 Dim strSetNameValue For Each strSetNameValue In strSetNameValues If strSetNameValue(3) = false Then CreateNode objXML, strSetNameValue(0) , strSetNameValue(1) , strSetNameValue(2) End If Next ' XML を保存 objXML.save( stmSettingFile ) End Sub '----------------------------------------------------------- 'セッティングファイルの存在チェック。 '----------------------------------------------------------- Sub SettingFileExistCheck(objFileSys , stmSettingFile) 'セッティングファイルの存在確認 If objFileSys.FileExists(stmSettingFile) = False Then WScript.echo "設定ファイル存在なし。AOO341未インストール。スクリプト終了" WScript.Quit End IF End Sub '----------------------------------------------------------- 'バージョンのチェック。 '----------------------------------------------------------- Sub VersionCheck(objFileSys ) Dim objTextStream,strVerText , blEndFlg blEndFlg = false 'バージョンファイルの存在確認 If objFileSys.FileExists(stmVerFile) = True Then 'ファイルが存在すればバージョン確認 'ファイル開く(読み取り専用) Set objTextStream = objFileSys.OpenTextFile(stmVerFile, 1 ) 'Do Until objTextStream.AtEndOfLine = True '最初の1行だけ読み込み If objTextStream.AtEndOfLine = False Then strVerText = objTextStream.ReadLine End If If CInt(strVerText) >= ver Then blEndFlg = true End If WScript.echo strVerText 'ファイルを閉じる objTextStream.Close() Else 'ファイルが無い場合は作成 objFileSys.CreateTextFile stmVerFile End If Set objTextStream = Nothing 'バージョンは同じなら設定しない If blEndFlg = true Then WScript.echo "バージョン新しいので更新しない。スクリプト終了。" WScript.Quit End If End Sub '----------------------------------------------------------- 'バージョンファイル書込 '----------------------------------------------------------- Sub WriteVersionFile( objFileSys ) Dim objTextStream 'バージョンファイル書き込み 'ファイル開く(上書きモード) Set objTextStream = objFileSys.OpenTextFile(stmVerFile, 2 ) objTextStream.WriteLine Cstr(ver) objTextStream.Close() Set objTextStream = Nothing End Sub '----------------------------------------------------------- 'ノードが無い時に追加するサブプロシージャ '----------------------------------------------------------- Sub CreateNode(objXML , strItemAttName , strPropName , strValue ) Dim objNewItem , objNewProp , objNewValue 'itemノードの追加 Set objNewItem = objXML.createElement("item") objNewItem.setAttribute "oor:path", strItemAttName objNewItem.appendChild(objXML.createTextNode(""))'vbCrLf & vbTab & vbTab)) 'propノードの追加 Set objNewProp = objXML.createElement("prop") objNewProp.setAttribute "oor:name", strPropName objNewProp.setAttribute "oor:op", "fuse" objNewProp.appendChild(objXML.createTextNode(""))'vbCrLf & vbTab & vbTab & vbTab)) 'valueノードの追加 Set objNewValue = objXML.createElement("value") objNewValue.Text = strValue 'propノードにvalueノードを子として追加 objNewProp.appendChild(objNewValue) objNewProp.appendChild(objXML.createTextNode(""))'vbCrLf & vbTab & vbTab)) 'itemノードにpropノードを子として追加 objNewItem.appendChild(objNewProp) objNewItem.appendChild(objXML.createTextNode(""))'vbCrLf & vbTab)) 'ルートノードにitemノードを子として追加 objXML.documentElement.appendChild(objNewItem) '最後に 改行 objXML.documentElement.appendChild(objXML.createTextNode(""))'vbCrLf)) End Sub
参考:
VBScript の お勉強 - 松翠ソフトウェア - It’s About Helping Your Users Become Awesome
VBScriptからXMLデータを読む方法 - XML & SOA - @IT
@IT:Windows TIPS -- Tips:WSHからXMLファイルの設定情報を読み込む
XMLの値を取得 XPathでノードを指定する方法だけどうまくできなかった。
XML/XPath/XPathの書き方 - 俺の基地 使えなかったXpathの書き方。