【问题标题】:Unexpected behavior when opening a file stream in a PowerShell script在 PowerShell 脚本中打开文件流时出现意外行为
【发布时间】:2016-10-11 00:08:19
【问题描述】:

我正在尝试创建一个附加(或创建,然后附加)到现有文件的脚本。该文件正在与另一个系统连接,因此为了避免在我追加文件时正在读取文件的情况,我正在对其创建一个非共享锁。脚本似乎可以完美运行,但有一个我无法理解的异常。这是一个代码示例:

$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 命名空间中。我在我的 PC 上映射的本地网络驱动器上尝试了它,它运行良好。

因此,无论出于何种原因,PowerShell 都不会像预期的那样对 DFS 命名空间上的 PowerShell 锁定的文件做出反应。我尝试过的所有其他应用程序都会检测到锁定:记事本和 Excel 拒绝读取文件,当我在 PDF 文档上测试它时,Acrobat 也不会打开它。但是PowerShell没有抱怨,甚至处理所有后续方法都没有错误——没有任何效果; CopyTo() 和 Flush() 方法没有失败,但文件没有改变。

【问题讨论】:

  • 还有一条评论:如果我用 Open、CreateNew 或 Truncate 替换 Append 方法,它会触发 catch 块。 Append、Create 和 OpenOrCreate 方法没有。

标签: .net powershell filestream microsoft-distributed-file-system system.io.file


【解决方案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"
}

【讨论】:

  • 对不起,这是我的第一个脚本,所以也许我不明白你的答案......我的问题是没有锁定文件,问题是:如果文件已经被锁定powershell,脚本实例没有检测到它。 Open 语句并没有像我预期的那样失败。
  • 无法复制。请描述您具体做什么,以及您如何具体做到这一点。
  • 我做了更多的测试,我认为它要么是一个错误,要么就是这样设计的。我将我的发现添加到原始帖子中。
猜你喜欢
  • 2022-08-05
  • 2011-08-17
  • 1970-01-01
  • 2020-10-21
  • 1970-01-01
  • 1970-01-01
  • 2018-06-06
  • 1970-01-01
  • 2015-08-01
相关资源
最近更新 更多