在PowerShell脚本中打开文件流时出现意外行为

时间:2016-10-11 00:08:19

标签: .net powershell filestream dfs system.io.file

我正在尝试创建一个附加(或创建,然后追加)现有文件的脚本。此文件正在与另一个系统连接,因此为了避免在我附加文件时正在读取文件,我在其上创建了无共享锁定。脚本似乎与我无法理解的一个例外完美配合。这是代码示例:

$ErrorActionPreference = "Stop"
try
{
    [System.IO.FileStream]$file1 = [System.IO.File]::Open("test.txt", [System.IO.FileMode]::Append,[System.IO.FileAccess]::Write, [System.IO.FileShare]::None)
}
catch
{
    Write-Host "Unable to create a lock on this file"
}

有一个条件不会触发catch块 - 如果文件已经通过PowerShell控制台锁定,并且此代码是从脚本运行而不是直接在窗口中键入。如果我先在Excel中打开文件,catch块始终有效。如果我通过在控制台中输入代码来执行此代码,它也始终有效。但是如果我首先通过在控制台中键入文件来锁定文件,然后运行一个尝试执行相同操作的脚本,则不会抛出任何异常并且不会触发catch块。

我在这里缺少什么?

更新:我做了其他问题排查,这是我的调查结果。首先,如何重现这个:

  • 创建名为test.txt
  • 的文件
  • 创建一个名为test1.ps1的脚本,将上面的代码放在其中
  • 在控制台中运行此命令:

    [System.IO.FileStream]$file2 = [System.IO.File]::Open("test.txt", [System.IO.FileMode]::Append,[System.IO.FileAccess]::Write, [System.IO.FileShare]::None)
    
  • 现在执行test1.ps1脚本

脚本的catch块不会触发...在我的工作环境中!我在家测试,它按预期工作。所以我回去工作并再次测试,这次使用PC本地驱动器上的文件,它工作。使其不起作用的一个区别是我正在处理的文件位于我公司的DFS命名空间中。我在我的电脑上映射的本地网络驱动器上试了一下它运行正常。

因此,无论出于何种原因,PowerShell都不会对DFS命名空间上由PowerShell锁定的文件做出反应。我尝试过的每个其他应用程序都检测到锁定:记事本和Excel拒绝读取文件,当我在PDF文档上测试时,Acrobat也不会打开它。但PowerShell并没有抱怨,甚至在没有错误的情况下处理所有后续方法 - 这些都没有效果; <{1}}和CopyTo()方法不会失败,但文件不会更改。

1 个答案:

答案 0 :(得分:1)

当您将上述代码作为脚本运行时,当脚本(或更准确地说,PowerShell进程)终止时,文件/句柄会自动关闭。您需要保持脚本运行以保持句柄打开,例如通过在Open()调用后添加无限循环:

$ErrorActionPreference = "Stop"
try {
    $writeStream = [IO.File]::Open($FilePath,[IO.FileMode]::Append,[IO.FileAccess]::Write, [IO.FileShare]::None)
    do {
        Start-Sleep -Milliseconds 100
    } while ($true)
} catch {
    Write-Host "Unable to create a lock on this file"
}