0

基本的に:

初めてのポスターはこちら...私は過去2日間、SOだけでなく、インターネット全体で答えを探してきました。アンインストール中に実行されるバッチファイル(.bat)が必要です。config(.cfg)ファイルを開き、エントリを見つけて削除し、アンインストールを終了します。

私がこれまでに持っているもの:

バッチファイルを実行してエントリを構成ファイルに追加するインストーラーがあります。

[Area.01]
Title=Unique to entry
Location=Unique to entry
Active=Required but in all entries
Layer=Required with Unique Number
Required=Required but in all entries

[Area.02]
Title=Unique to entry
Location=Unique to entry
Active=Required but in all entries
Layer=Required with Unique Number
Required=Required but in all entries

Install Batchファイルで構成をスキャンし、次のエントリ番号、エントリの内容、およびエントリのインデックスを保存するREGISTRYキーを追加します。したがって、論理的には次のエントリはになります[Area.03]。ただし、このファイルには100を超えるエントリが含まれています。

私が欲しいのは、バッチファイルがレジストリエントリを読み取り、それを実行しエントリを検索し、エントリ全体を削除することです。これが、私がここにいる理由です。これが私がこれまでに持っているものです:

@echo off

REG QUERY "HKLM\SOFTWARE\Name of File" /v SceneryCFGPath
IF ERRORLEVEL 1 GOTO ERROR1
FOR /F "tokens=3 skip=2" %%i IN ('REG QUERY "HKLM\SOFTWARE\Name of File" /v SceneryCFGPath') DO SET VAR1=%%i
CD "%VAR1%"

REG QUERY "HKLM\SOFTWARE\Name of File" /v SceneryIndex
IF ERRORLEVEL 1 GOTO ERROR2
FOR /F "tokens=3 skip=2" %%i IN ('REG QUERY "HKLM\SOFTWARE\Name of File" /v SceneryIndex') DO SET VAR2=%%i
TYPE scenery.cfg | FINDSTR /V Area.%VAR2%
REG DELETE "HKLM\SOFTWARE\Name of File" /F
GOTO END

:ERROR1
ECHO There was an Error while changing to Directory "%VAR1%"...
PAUSE
GOTO ERROR2

:ERROR2
ECHO There was an Error while unregistering from Scenery Library ! Please delete the Area manually...
PAUSE
GOTO END

:END
del "%~f0"

を使用するFINDSTRと、エントリは正常に検出されますが、最初の行のみ[Area.03]が削除されます。私がする必要があるのは、それとそのエントリの他の部分を削除することです。

FINDSTRに他のエントリを含めようとしたとき:

TYPE scenery.cfg | FINDSTR /V /N Area.%VAR2% | Title | Active | Layer | Required

エントリごとにこれらの行をすべて削除します。

これはWindowsXP、Vista、7、32、64ビットシステムで実行されるため、私はこれをバッチファイルにすることを強く望んでいます。 これらの特定のWindowsシステムにはすべてCMD.EXEがあるため、追加のライブラリやプログラムは必要ありません。

設定ファイルのエントリ全体を削除することを除いて、すべてが完全に機能しています。誰かを混乱させないことを願っていますが、助けていただければ幸いです。

Sven2157

4

1 に答える 1

1

あなたが尋ねた問題を解決する前に、あなたのエラー処理に関して対処すべき他のいくつかの問題があります。

特定のレジストリキー値が存在するかどうかをテストし、見つからない場合は、存在しないキー値を出力しようとします。それはうまくいきません;-)

見つかったパス値にCDを挿入しようとしましたが、パスが有効であるという保証はありません。おそらくエラーをチェックしたいと思うでしょう。また、現在のドライブがパスのドライブと一致しない可能性があるため、CD / D(またはPUSHD)を使用する必要があります。

レジストリキーと値のペアごとに2つのREGQUERY操作を使用します。1つは存在をテストし、もう1つは値を解析します。キー値ごとに1つのREGQUERYのみが必要です。

バッチファイルは、終了時に自分自身を削除しています。これにより、「バッチファイルが見つかりません」というエラーが発生します。おそらく気にしないかもしれませんが、このバッチを呼び出すときは、おそらくstdoutをnulにリダイレクトする必要があります。

バッチファイルは削除すると自動的に削除されるため、エラー処理を簡素化できます。エラーごとに個別のルーチンは必要ありません。一般的なエラールーチンを呼び出すだけで、エラーメッセージが渡されます。エラールーチンは、完了すると終了ルーチンにフォールスルーする可能性があり、バッチが強制終了されます。したがって、エラー呼び出しから戻ることを心配する必要はありません。

上記のすべてのアイデアを以下のコードに組み込みました。

また、変更したフォームを単に画面にエコーするのではなく、実際に「scenery.cfg」ファイルを変更したいとします。出力を新しいファイルにリダイレクトしてから、新しいファイルの名前を古い名前に変更して、元のファイルを破棄します。

さて、元の質問にたどり着くために、バッチには、2つのマーカーライン間のラインの範囲を便利に抽出するネイティブユーティリティがありません。非ネイティブユーティリティに依存したくないので、ループ内の各行を処理し、その行を含めるかどうかを決定する必要があります。

これを行う2つの簡単な方法があります。注-どのコードもテストされていません。コンセプトはすべて健全ですが、修正が簡単なはずのばかげたバグを導入した可能性があります

1-単一のループを使用して各行を調べ、選択した領域が見つかったときにその行の除外を開始し、次の領域が開始したときに再開します

このコードは、SET検索と置換を使用して、行に問題の文字列が含まれているかどうかをテストします。

ファイルを読み取るための古典的な手法は、FOR/Fループです。しかし、それは空白行を取り除きます。そのため、コードが拡張されて、各[Area.nn]セクションの前に空白行が追加されます。遅延拡張が必要ですが、!遅延拡張が有効になっている場合、を含むFOR変数値が破損します。そのため、ループ内で遅延拡張のオンとオフを切り替えます。それがファイルに表示されないことがわかっている場合!は、上部で遅延拡張を有効にして、ループ内からSETLOCALとENDLOCALを削除するだけです。

@echo off
setlocal disableDelayedExpansion
set regPath="HKLM\SOFTWARE\Name of File"

set "myPath="
for /f "tokens=3 skip=2" %%A in ('reg query %regPath% /v SceneryCFGPath') do set "myPath=%%A"
if not defined myPath call :error Unable to locate SceneryCFGPath
cd /d "%myPath%" 2>nul || call :error Unable to CD to "%myPath%"

set "area="
for /f "tokens=3 skip=2" %%A IN ('reg query %regPath% /v SceneryIndex') do set "area=%%A"
if not defined area call :error Unable to unregister from Scenery Library ! Please delete the Area manually...

>scenery.cfg.new (
  set "del="
  for /f "delims=" %%A in (scenery.cfg) do (
    set "ln=%%A"
    setlocal enableDelayedExpansion
    if "!ln:[Area.%area%=!" neq "!ln!" (
        set del=1
    ) else if "!ln:[Area.=!" neq "!ln!" (
        set "del="
        echo(
    )
    if not defined del echo !ln!
    endlocal
  )
)
move /y scenery.cfg.new scenery.cfg

reg delete %regPath% /f
goto end

:error
echo ERROR: %*
pause

:end
del "%~f0"

2-FINDSTRを使用して選択した領域の開始を検索し、2番目のFINDSTRを使用して次の領域の開始を検索します。

/ Nオプションは、一致する行の行番号を取得するために使用されます。FOR / Fは、結果を解析して値に割り当てるために使用されます。次の領域が見つかったら、GOTOは2番目のループから抜け出す必要があります。

最後に、3番目のFOR / Fを使用して、FINDSTRコマンドが前に付いた行番号を持つファイルを読み取ります。各行が解析され、適切な行が除外されます。

行が。で始まる場合、このコードは正しく機能しないことに注意してください:。この制限はもう少しコードを追加することで取り除くことができますが、あなたの場合は必要ないと思います。

@echo off
setlocal disableDelayedExpansion
set regPath="HKLM\SOFTWARE\Name of File"

set "myPath="
for /f "tokens=3 skip=2" %%A in ('reg query %regPath% /v SceneryCFGPath') do set "myPath=%%A"
if not defined myPath call :error Unable to locate SceneryCFGPath
cd /d "%myPath%" 2>nul || call :error Unable to CD to "%myPath%"

set "area="
for /f "tokens=3 skip=2" %%A IN ('reg query %regPath% /v SceneryIndex') do set "area=%%A"
if not defined area call :error Unable to unregister from Scenery Library ! Please delete the Area manually...

set "beginDel="
for /f "delims=:" %%N in ('findstr /nbc:"[Area.%area%]" scenery.cfg') do set beginDel=%%N
if not defined beginDel goto end

set "endDel="
for /f "delims=:" %%N in ('findstr /nbc:"[Area." scenery.cfg') do if %%N gtr beginDel (
  set endCond=if %%A gre %%N
  goto :break
)
:break

>scenery.cfg.new (
  for /f "tokens=1* delims=:" %%A in ('findstr /n "^" scenery.cfg') do (
    if %%A lss %beginDel% %endCond% echo(%%B
  )
)
move /y scenery.cfg.new scenery.cfg

reg delete %regPath% /f
goto end

:error
echo ERROR: %*
pause

:end
del "%~f0"
于 2012-07-21T20:24:43.250 に答える