簡體   English   中英

使用try塊測試文件是否在Powershell中被鎖定

[英]Using a try block to test if a file is locked in powershell

我想知道使用try塊來測試文件是否被鎖定的錯誤形式。 這是背景。 我需要將應用程序的文本輸出同時發送到兩台串行打印機。 我的解決方案是使用MportMon和Powershell腳本。 它應該起作用的方式是應用程序默認打印到MportMon虛擬打印機端口,該端口實際上在“ dropbox”文件夾中創建一個唯一命名的文件。 Powershell腳本使用filesystemwatcher來監視文件夾,並且在創建新文件時,它將獲取文本內容並將其推出兩台串行打印機,然后刪除該文件,以免填滿該文件夾。 嘗試從虛擬打印機創建的文件中讀取文本時遇到問題。 我發現由於文件仍被鎖定而出現錯誤。 為了解決該問題,我使用了FSM來實現邏輯,而不是每次嘗試從文件中獲取內容之前都不檢查鎖,而是使用try塊嘗試從文件中讀取內容,如果失敗,則嘗試從文件中讀取內容。 catch塊只是重申了FSM所在的狀態,並且重復該過程直到成功。 看來工作正常,但我在某處讀到它的不良做法。 此方法是否存在危險,還是安全可靠? 下面是我的代碼。

$fsw = New-Object system.io.filesystemwatcher
$q = New-Object system.collections.queue
$path = "c:\DropBox"
$fsw.path = $path
$state = "waitforQ"
[string]$tempPath = $null

    Register-ObjectEvent -InputObject $fsw -EventName created -Action {
    $q.enqueue( $event.sourceeventargs.fullpath )
    }

    while($true) {
    switch($state)
    {
        "waitforQ" {
                    echo "waitforQ"
                    if ($q.count -gt 0 ) {$state = "retrievefromQ"}
                    }
        "retrievefromQ"  {
                    echo "retrievefromQ"
                    $tempPath = $q.dequeue()
                    $state = "servicefile"
                    }
        "servicefile"  {
                        echo " in servicefile "

                    try
                        {
                        $text = Get-Content -ErrorAction stop $tempPath 
                        #echo "in try"
                        $text | out-printer db1
                        $text | out-printer db2
                         echo " $text "
                        $state = "waitforQ"
                        rm $tempPath
                        }
                    catch
                        {
                        #echo "in catch" 
                        $state = "servicefile"
                        }
                    }

           Default {    $state = "waitforQ"  }
    }
    }

我不會說測試文件以查看是否已鎖定是不好的做法,但是它不如檢查其他進程使用的句柄那么干凈。 我個人會像您一樣測試文件,但會進行一些調整以使其更安全/更好。

  • 該切換語句看起來很復雜(對我而言),我將其替換為簡單的if-test。 “如果文件在隊列中,請繼續,否則,請等待”。
  • 您需要放慢速度。.在鎖定文件時,您將嘗試盡可能多地讀取該文件。 這是浪費資源,因為當前應用程序要花一些時間才能將其保存並將數據保存到HDD。 添加一些暫停。 您不會注意到它們,但是您的CPU會喜歡它們。 當隊列中沒有文件時,也是如此。
  • 您可能會受益於添加超時(例如最多50次嘗試讀取文件),以避免在從未釋放一個特定文件的情況下腳本卡住的情況。

嘗試:

$fsw = New-Object system.io.filesystemwatcher
$q = New-Object system.collections.queue
$path = "c:\DropBox"
$fsw.path = $path
$MaxTries = 50  #50times * 0,2s sleep = 10sec timeout
[string]$tempPath = $null

Register-ObjectEvent -InputObject $fsw -EventName created -Action {
    $q.enqueue( $event.sourceeventargs.fullpath )
}

while($true) {
    if($q.Count -gt 0) {

        #Get next file in queue
        $tempPath = $q.dequeue()

        #Read file
        $text = $null
        $i = 0
        while($text -eq $null) {

            #If locked, wait and try again
            try {
                $text = Get-Content -Path $tempPath -ErrorAction Stop
            } catch {
                $i++
                if($i -eq $MaxTries) {
                    #Max attempts reached. Stops script
                    Write-Error -Message "Script is stuck on locked file '$tempPath'" -ErrorAction Stop
                } else {                
                    #Wait
                    Start-Sleep -Milliseconds 200
                }

            }
        }

        #Print file
        $text | Out-Printer db1
        $text | Out-Printer db2
        echo " $text "

        #Remove temp-file
        Remove-Item $tempPath

    }

    #Relax..
    Start-Sleep -Milliseconds 500

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM