繁体   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