0

現在、次のコードを使用してディレクトリを検索し、見つかった.msiを別のディレクトリにコピーします。別のプログラムで使用されている場合は、.msiをコピーしたくありません。StackExchangeで、ファイルが使用されているかどうかを確認する他の方法を示す他の質問を見ましたが、Rename-Itemコマンドの周りにtry/catchブロックを使用する方が簡単な解決策のように見えました。スクリプトでアイテムの名前を変更できない場合は、の次のアイテムに移動し$fileます$listoffiles。私がそれを機能させることができる唯一の方法は、以下にリストされたコードを使用することでした。ただし、結果のエラーメッセージを希望どおりにフォーマットできないようで、-ErrorAction Stop必要ないようです。ブロックでエラーが発生した場合、エラーはtryブロックに移動するだけではいけませんcatchか?また、エラーメッセージの3つの変数のうち2つだけがログファイルに書き出されます。

現在のコード:

$listofFiles=(Get-ChildItem -Path $outputPath -Filter "*.msi" | where {$_.Name -notlike "*.Context.msi" -and $_.LastAccessTime -gt (Get-Date).AddMinutes(-15)})

foreach ($file in $listofFiles){
    $y = ($file -split ("\\"))
    $msiFolder = $y[4]

    #Tests to see if $file currently in use
    try{
        Rename-Item -Path $file -NewName $file -ErrorVariable renameError -ErrorAction Stop 
    }
    catch{
        "$logTime ERROR Could not copy $msiFolder: $renameError.Exception.Message()" >> $copyLog
        continue
    }   

    #Code that copies files that are not in use.

現在、エラーは次のように表示されます。

02/18/13 13:43:25 ERROR Could not copy  System.Management.Automation.ActionPreferenceStopException: Command execution stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: The process cannot access the file because it is being used by another process.
   at System.Management.Automation.StatementListNode.ExecuteStatement(ParseTreeNode statement, Array input, Pipe outputPipe, ArrayList& resultList, ExecutionContext context)
   at System.Management.Automation.StatementListNode.Execute(Array input, Pipe outputPipe, ArrayList& resultList, ExecutionContext context)
   at System.Management.Automation.TryStatementNode.Execute(Array input, Pipe outputPipe, ArrayList& resultList, ExecutionContext context).Exception.Message()

私はそれが次のように見えることを望みます:

02/18/13 13:34:34 ERROR Could not copy ABC_CLIENT: The process cannot access the file because it is being used by another process.

質問

  1. $ msiFolderがログメッセージに表示されないのはなぜですか?
  2. エラーメッセージを単純化するにはどうすればよいですか?
  3. try / catchブロックを使用して、foreachループの反復から抜け出すためのより良い方法はありますか?

アップデート1:

私はクリア$errorして実行しました:

Rename-Item -Path $file -NewName $file -ErrorAction SilentlyContinue
if (!$?){"$logTime ERROR Could not copy $file: $error[0].Exception.Message()" >> $copyLog}

結果は次のとおりです。

02/18/13 14:52:59 ERROR Could not copy  The process cannot access the file because it is being used by another process.[0].Exception.Message()

なぜ$logTime印刷されるのに他の変数は印刷されないのですか?

アップデート2: 私が使用した最終的なコード:

Rename-Item -Path $file -NewName $file -ErrorAction SilentlyContinue 
if (!$?){
    "$logTime ERROR Could not copy ${msiFolder}: $($error[0].Exception.Message)" >> $copyLog
    continue
}
4

1 に答える 1

1

try/catch を使用する場合は、Rename-Item から取得した非終了エラーを終了エラーに変換する必要があります。そのため、 -ErrorAction Stop を使用して catch ブロックを呼び出す必要があります。ただし、これを別の方法で行うこともできます。

foreach ($file in $listofFiles){
    $y = ($file -split ("\\"))
    $msiFolder = $y[4]

    #Tests to see if $file currently in use
    Rename-Item -Path $file -NewName $file -ErrorVariable renameError -ErrorAction SilentlyContinue
    if (!$?) {
        "$logTime ERROR Could not copy ${msiFolder}: $($error[0].Exception.Message)" >> $copyLog
        continue
    }   

    #Code that copies files that are not in use.
}

自動変数$?は、最後のコマンドが成功したかどうかを示します。

$msiFolder が出力されない理由については、分割操作を確認します。$y.count が >= 5 であることを確認します。

于 2013-02-18T19:05:27.867 に答える