上周我遇到了一个奇怪的问题
我修改了应该测试文件是否被锁定的代码以及我曾经在互联网上找到的代码(基本上类似于https://superuser.com/questions/876288/how-do-i-detect-and-skip-locked-files-in-a-powershell-script)到
1)处理超时和
2)正确处理不存在的文件(和目录)。
所以这是我的代码:
function Test-IsFileLocked {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $True, Position = 0)]
[ValidateNotNullOrEmpty()]
[System.IO.FileInfo] $File
, [ref] $MSecsPassed
)
try {
$Stream = $File.Open([System.IO.FileMode]"Open", [System.IO.FileAccess]"Read", [System.IO.FileShare]"None")
}
# The follwing catch block seems to cause the problem that the 'IO.FileNotFoundException' gets caught after some time (although it is still a simple 'IO.IOException.)
# Outcomment it by removing the '#' in front of '<# ...' to see how all works nicely...
#<#
catch [System.IO.DirectoryNotFoundException] {
Write-Host "System.IO.DirectoryNotFoundException: '$($_.Exception)'`nType = '$($_.Exception.GetType().FullName)'`nType = '$($_.GetType().FullName)'" -ForegroundColor:Yellow
return $False
}
#>
catch [System.IO.FileNotFoundException] {
Write-Host "Caught a 'FileNotFoundException' exception, although the exception still is of type of a simple 'System.IO.IOException'! MSecs passed: $($MSecsPassed.Value)" -ForegroundColor:Red
Write-Host "FileNotFoundException: '$($_.Exception)'`nType = '$($_.Exception.GetType().FullName)'`nType = '$($_.GetType().FullName)'" -ForegroundColor:Yellow
#if ($_.Exception.GetType().FullName -eq 'System.IO.IOException') {
# return $True
#} else {
return $False
#}
} catch [System.IO.IOException] {
#Write-Host "System.IO.IOException: '$($_.Exception)'`nType = '$($_.Exception.GetType().FullName)'`nType = '$($_.GetType().FullName)'"
if ($_.Exception.GetType().FullName -eq 'System.IO.IOException') {
return $True
} else {
return $False
}
} catch {
Write-Host "Any Exception: '$($_.Exception)'`nType = '$($_.Exception.GetType().FullName)'`nType = '$($_.GetType().FullName)'" -ForegroundColor:Yellow
if ($_.Exception.GetType().FullName -eq 'System.IO.IOException') {
return $True
} else {
return $False
}
} finally {
if ($Stream) {
$Stream.Dispose()
}
}
return $False
}
function Wait-UntilFileIsAccessible {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $True, Position = 0)]
[ValidateNotNullOrEmpty()]
[System.IO.FileInfo] $File
, [Parameter(Position = 1)]
[uint32] $CheckIntervalInMSecs
, [Parameter(Position = 2)]
[uint32] $Timeout
)
if (!$CheckIntervalInMSecs) {
$CheckIntervalInMSecs = 500
}
[double] $SecondsPassed = 0.0
[double] $SecondsAdder = [double]$CheckIntervalInMSecs / 1000.0
[uint32] $MSecsPassed = 0
#Write-Verbose "Waiting for '$($File.Fullname)' to get unlocked!"
while (Test-IsFileLocked -File:$File -MSecsPassed:([ref]$MSecsPassed)) {
Start-Sleep -MilliSeconds:$CheckIntervalInMSecs
$MSecsPassed += $CheckIntervalInMSecs
if ($Timeout) {
$SecondsPassed += $SecondsAdder
if (([uint32]$SecondsPassed) -ge $Timeout) {
return $False
}
}
}
#Write-Vebose "'$($File.Fullname)' now isn't locked anymore"
return $True
}
如果我用
调用此代码Wait-UntilFileIsAccessible -File:'C:\LockedByMSWord.txt' -Timeout:30
其中&#39; C:\ LockedByMSWord.txt&#39;是一个实际锁定的现有文件(例如用MS Word打开)然后经过一段时间(在大多数情况下为16500毫秒),&#39; IO.FileNotFoundException&#39; 会被捕获,尽管抛出异常似乎是&#39; IO.IOException&#39; 类型。
如果我再重复拨打“等待直到发现可用”的电话。然后通常Powershell会立即发现这个“错误”的错误。例外。
它驱使我疯了,我尝试了不同的东西,直到我删除了捕获&#39; IO.DirectoryNotFoundException&#39; IO.DirectoryNotFoundException&#39; (最初用于测试目的)只是为了找出一切都按预期工作。
我在这里做错了(我的意思是捕获这个&#39; IO.DirectoryNotFoundException&#39;异常的代码),我是否误解了某些内容或者这可能是一个Powershell错误?
这是Powershell 4和ErrorActionPreference设置为&#39;继续&#39;。
另外一些代码显然只是出于测试目的(我不需要在Test-IsFileLocked中输入参数MSecsPassed并正常输出到主机)
P.S。:我知道如何解决它,但如果我在代码中做错了,或者这可能是Powershell中的错误,我想反馈我的问题。
谢谢,
帕特里克