Set-Content偶尔因“流不可读”而失败

时间:2018-02-23 18:00:58

标签: powershell

我有一些PowerShell脚本在构建之前准备文件。其中一个操作是替换文件中的某些文本。我使用以下简单函数来实现此目的:

function ReplaceInFile {
    Param(
        [string]$file,
        [string]$searchFor,
        [string]$replaceWith
    )

    Write-Host "- Replacing '$searchFor' with '$replaceWith' in $file"

    (Get-Content $file) |
    Foreach-Object { $_ -replace "$searchFor", "$replaceWith" } |
    Set-Content $file
}

此函数偶尔会因错误而失败:

Set-Content : Stream was not readable.
At D:\Workspace\powershell\ReplaceInFile.ps1:27 char:5
+     Set-Content $file
+     ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (D:\Workspace\p...AssemblyInfo.cs:String) [Set-Content], ArgumentException
    + FullyQualifiedErrorId : GetContentWriterArgumentError,Microsoft.PowerShell.Commands.SetContentCommand

发生这种情况时,结果是一个空文件,一个不快乐的构建。任何想法为什么会这样?我应该做些什么?

5 个答案:

答案 0 :(得分:6)

抱歉,我不知道为什么会发生这种情况,但您可以试试我的Replace-TextInFile 功能。如果我没记错的话,我也会使用Get-contet来解决类似问题:

function Replace-TextInFile
{
    Param(
        [string]$FilePath,
        [string]$Pattern,
        [string]$Replacement
    )

    [System.IO.File]::WriteAllText(
        $FilePath,
        ([System.IO.File]::ReadAllText($FilePath) -replace $Pattern, $Replacement)
    )
}

答案 1 :(得分:2)

使用-Raw上的Get-Content开关将完整地读取该文件作为单个字符串。替换其中的所有值比使代码逐行迭代要快得多。

尝试

(Get-Content $file -Raw) -replace $searchFor, $replaceWith | Set-Content $file

答案 2 :(得分:1)

也许您的文件被另一个进程锁定了?您可以使用图库中的findopenfile模块来查看是否存在锁:https://www.powershellgallery.com/packages/FindOpenFile

或在sysinternals进程浏览器中搜索句柄。 https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer

答案 3 :(得分:0)

joelsand所述,Martin Brandl的答案可以稍作改进。

function Replace-TextInFile
{
    Param(
        [string]$FilePath,
        [string]$Pattern,
        [string]$Replacement, 
        [System.Text.Encoding] $Encoding
    )

    if($Encoding) {
        [System.IO.File]::WriteAllText(
            $FilePath,
            ([System.IO.File]::ReadAllText($FilePath, $Encoding) -replace $Pattern, $Replacement),
            $Encoding
        )
    } else { 
        [System.IO.File]::WriteAllText(
            $FilePath,
            ([System.IO.File]::ReadAllText($FilePath) -replace $Pattern, $Replacement)
        )
    }
}

示例:

$encoding = [System.Text.Encoding]::UTF8
Replace-TextInFile -FilePath $fullPath -Pattern $pattern -Replacement $replacement -Encoding $encoding

答案 4 :(得分:0)

我遇到了这个问题,结果发现我尝试更改的文件是在Visual Studio中打开的解决方案的一部分。在运行之前关闭Visual Studio即可解决问题!