Set-Content:流不可读 - 试图理解失败的原因以及如何更优雅地失败

Set-Content:流不可读 - 试图理解失败的原因以及如何更优雅地失败

我的 PowerShell 脚本中有以下行

(Get-Content C:\Windows\System32\drivers\etc\hosts -Raw) -replace '[\d]+\.[\d]+\.[\d]+\.[\d]+ local.mywebsite.com',"$ipAddress local.mywebsite.com" | Set-Content -Path C:\Windows\System32\drivers\etc\hosts

$ipAddress是在其他地方设置的变量)

我通过这样做获得管理员权限:

param([switch]$Elevated)

function Test-Admin
{
  $currentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
  $currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
}

if ((Test-Admin) -eq $false)  {
    if ($elevated) {
        # tried to elevate, did not work, aborting
    } else {
        Start-Process powershell.exe -Verb RunAs -ArgumentList ('-noprofile -noexit -file "{0}" -elevated ' -f ($myinvocation.MyCommand.Definition))
    }
    exit
}

当我运行该脚本时出现以下错误:

Set-Content : Stream was not readable.
At C:\path\to\setup.ps1:20 char:145
+ ... mywebsite.com" | Set-Content -Path C:\Windows\System32\drivers\etc\hosts
+                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (C:\Windows\System32\drivers\etc\hosts:String) [Set-Content], ArgumentE
   xception
    + FullyQualifiedErrorId : GetContentWriterArgumentError,Microsoft.PowerShell.Commands.SetContentCommand

我不明白。为什么我处于管理员模式,流就不可读?

此外,当我遇到此错误时,我的 hosts 文件会被清空,因此它并不是真正意义上的正常失败。它被清空这一事实意味着它能够写入 hosts 文件,这很奇怪,因为它无法读取该文件。

如果无法读取 hosts 文件,我希望它的内容没有被擦除......

此外,虽然新的管理员:Windows PowerShell 窗口已打开,但即使脚本执行已终止,我仍无法在管理员模式下在记事本中打开 hosts 文件,而不会出现以下错误:

hosts
The file is in use.
Enter a new name or close the file that's open in another program.

由于 PowerShell 脚本将命令返回给 CLI,我不知道为什么它仍保持文件打开...

有任何想法吗?

答案1

我建议使用 try/catch 和String.IsNullOrEmpty()

try
{
    $strHosts = (Get-Content C:\Windows\System32\drivers\etc\hosts -Raw)
    if([string]::IsNullOrEmpty($strHosts)) {
        Write-Error -Message "Get-Content hosts empty" -ErrorAction Stop
    }
}
catch
{
    Write-Output "Unable to read hosts file"
}

try
{
    $strHosts -replace '[\d]+\.[\d]+\.[\d]+\.[\d]+ local.mywebsite.com',"$ipAddress local.mywebsite.com" | Set-Content -Path C:\Windows\System32\drivers\etc\hosts
}
catch
{
    Write-Output "Unable to write hosts file"
}

我还让你的正则表达式更加健壮,允许 IP 和主机名之间有任意数量的空格。

相关内容