2017-06-09 4 views
0

インストールされているアプリケーションのレジストリ値を多くのサーバーで照会しようとしています。私はサーバーをハードコードすることができ、繰り返しがたくさんあり、うまくいくようです。しかし、時にはサーバーのリストが変わることがあります。私はより合理的なモジュール方式を採用したいと考えています。バッチファイルのネストされたforループの正しい構文

私はテストファイルにサーバー名のリストを提供し、これらのサーバーのすべてのレジストリ値をクエリしてログファイルに出力することができます。

私の問題は間違いなく私のループ/変数の格納にあると思います。確かに何が起こっているのかはわかりませんが、一度レジストリ値を取得すると、それぞれのレジストリ値に関係なく、すべての単一サーバに対して出力されます。

この種のスクリプトではあまり経験はありませんので、試行錯誤してこのことをまとめてみました。以下はこれまでのところです。私が作った悲惨な構文エラーを指摘してください。

これは基本的に、各サーバーにMcAfeeスキャンエンジンのバージョンがインストールされていることを確認するためです。 McAfeeコンソール自体からのレポートは常に信頼できるとは限りません。コンテンツが各サーバーに正常にプルダウンされていることを確認する必要があります。

完全なエンジンバージョンを作成するには2つのレジストリ値が必要です。そのため、両方を取得してから1つの文字列に結合する必要があります。

現時点では正しい出力が得られますが、実際には各サーバーにインストールされているものは表示されません。 1つの値が選択されて複製されるようなものです。

これは、コマンドラインで実行した場合にのみ有効です。最初の1〜2回は実行され、値は引き出されません。私が解決策からかなり離れていると感じる。あなたが提供することができます任意の助け

server1 : 5900.5647 
server2 : 6000.4589 
server3 : 5900.5647 
server4 : 5900.5647 

乾杯:

SET LOGFILE=C:\LogFile.log 
For /f %%i in (servers.txt) DO (
for /f "tokens=3" %%a in ('reg query \\%%i\HKLM\SOFTWARE\McAfee\AVEngine /v EngineVersion32Major ^| find /i "EngineVersion32Major"') do set /a major=%%a 
for /f "tokens=3" %%b in ('reg query \\%%i\HKLM\SOFTWARE\McAfee\AVEngine /v EngineVersion32Minor ^| find /i "EngineVersion32Minor"') do set /a minor=%%b 
echo %%i: %major%.%minor% >> %LOGFILE% 
) 

のような出力が期待されます。

答えて

2

forの構文とは関係ありませんが、cmdはどのようにスクリプトを解析しますか。 How does the Windows Command Interpreter (CMD.EXE) parse scripts?

cmdブロック(括弧内のすべて)を解析すると、1行として処理されます。したがって、%var%は実際の内容に展開されます。変更はブロックが終了するまで考慮されません。ブロック内の新しいコンテンツを取得するには、delayed expansionを有効にする必要があります。これにより、パーサーはすべての反復ごとに新しいコンテンツを評価しなければなりません。また、構文はここ!var!

%var%から変更する必要があり、また、あなたが計算を行っていないとして、setコマンドから/aスイッチを除去し、あなたが結果を得ることができます(に等しいマイナーバージョンを想像し期待しないだろう0080は8進数(無効)として扱われ、スクリプトが中断されます)。また、望ましくない後続/先行スペースを避けるために、引用符(set "minor=%%b")で囲まれたvar名とvarコンテンツの両方に注意してください。

また、^| find /i "EngineVersion32Majorの部分は必要ありません。おそらくEngineVersion32Majorという名前のキーは、あなたが探しているものだけを内容にします。また、データを引用符で囲みます(スペースが表示されることはありません)。エコーを処理しないようにを"skip=1 tokens=3"に変更することもできます。

したがって

@echo off 
SetLocal EnableDelayedExpansion 
SET LOGFILE=C:\LogFile.log 
for /f %%i in (servers.txt) DO (
    for /f "tokens=3" %%a in ('reg query "\\%%i\HKLM\SOFTWARE\McAfee\AVEngine" /v "EngineVersion32Major"') do set "major=%%a" 
    for /f "tokens=3" %%b in ('reg query "\\%%i\HKLM\SOFTWARE\McAfee\AVEngine" /v "EngineVersion32Minor"') do set "minor=%%b" 
    echo %%i: !major!.!minor!>>%LOGFILE% 
) 
EndLocal 

また、これはブロック内で動作かかわらず、遅れて拡張が

call echo %%i: %%major%%.%%minor%%>>%LOGFILE% 

(ダブルパーセント記号に注意してください)別の問題、リダイレクトを内で使用される任意の時間を有効にするかしませんブロックすると、システムはファイル(またはストリーム)を開いて閉じます。

しかし

@echo off 
SetLocal EnableDelayedExpansion 
SET LOGFILE=C:\LogFile.log 
>>"%LOGFILE%" (
    for /f %%i in (servers.txt) DO (
    for /f "tokens=3" %%a in ('reg query "\\%%i\HKLM\SOFTWARE\McAfee\AVEngine" /v "EngineVersion32Major"') do set "major=%%a" 
    for /f "tokens=3" %%b in ('reg query "\\%%i\HKLM\SOFTWARE\McAfee\AVEngine" /v "EngineVersion32Minor"') do set "minor=%%b" 
    echo %%i: !major!.!minor! 
) 
) 
EndLocal 

ブロック内のプロセスのすべてのコマンドを、ファイルが開かれ、一度だけ閉じているので。これにより、特に大きなファイルのパフォーマンスが向上する可能性があります。ところで

>>"%LOGFILE%" (
    ... 
    ... 
) 

(
    ... 
    ... 
)>>"%LOGFILE%" 
+0

ブリリアントを使用することです!そんなに詳しく説明してくれてありがとう。私が言ったように、私はこれに対して比較的新しいもので、さまざまなことを一緒にマッシュしているようなものでした。乾杯。 – DMDMDM

0

と同じですdelayed expansionに多くのSOの記事を見つけるためにsearch機能を使用してください。

あなたのケースで簡単な方法は

call echo %%i: %%major%%.%%minor%% >> %LOGFILE% 
+0

おかげさまで、遅延拡張と呼ばれるものを研究することすら考えられませんでした。 – DMDMDM

+0

トップバーには検索機能があります。ボックスに 'delayed extended'と入力し、虫眼鏡を押してください。 – Magoo

関連する問題