设置内容:进程无法访问文件'C:WINDOWSsystem32driversetchosts',因为它正被另一个进程使用



我有以下PowerShell脚本:

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
}
function UpdateHosts {
param ($hostName)
Write-Host $hostName
try {
$strHosts = (Get-Content C:WINDOWSsystem32driversetchosts -Raw)
if([string]::IsNullOrEmpty($strHosts)) {
Write-Error "Get-Content hosts empty"
exit
}
} catch {
Write-Error "Unable to read hosts file"
Write-Error $_
exit
}
try {
$strHosts -replace "[d]+.[d]+.[d]+.[d]+ $hostName","$ipAddress $hostName" | Set-Content -Path C:WINDOWSsystem32driversetchosts
} catch {
Write-Error "Unable to write hosts file"
Write-Error $_ 
exit
}
}
$ipAddress = "127.0.0.1"
UpdateHosts -hostName local.pap360.com

有时,当我运行它时,我得到以下错误:

Set-Content:进程无法访问文件"C:WINDOWSsystem32driversetchosts",因为该文件正在被其他进程使用。

当我在记事本中打开C:WINDOWSsystem32driversetchosts时,它是空白的。ie。

我的问题是……我怎样才能避免这种情况的发生?如果Set-Content不能访问hosts文件写入它,那么它如何能够擦除它的内容?为什么catch块不能工作?

下面是完整的错误:

Set-Content : The process cannot access the file 'C:WINDOWSsystem32driversetchosts' because it is being used by
another process.
At C:pathtotest.ps1:36 char:92
+ ...  $hostName" | Set-Content -Path C:WINDOWSsystem32driversetchosts
+                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : WriteError: (C:WINDOWSsystem32driversetchosts:String) [Set-Content], IOException
+ FullyQualifiedErrorId : GetContentWriterIOError,Microsoft.PowerShell.Commands.SetContentCommand

我也不明白为什么它是断断续续的。是否有一些Windows进程每分钟打开一次hosts文件?

首先,检查您的防火墙或防病毒软件是否限制访问该文件。如果不是这种情况,并且'一些'其他进程当前正在锁定hosts文件,也许在读写文件之前添加一个测试会有所帮助:

function Test-LockedFile {
param (
[parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[Alias('FullName', 'FilePath')]
[ValidateScript({Test-Path $_ -PathType Leaf})]
[string]$Path
)
$file = [System.IO.FileInfo]::new($Path)
# old PowerShell versions use:
# $file = New-Object System.IO.FileInfo $Path
try {
$stream = $file.Open([System.IO.FileMode]::Open,
[System.IO.FileAccess]::ReadWrite,
[System.IO.FileShare]::None)
if ($stream) { $stream.Close() }
return $false   # file is not locked
}
catch {
return $true    # file is locked
}
}

然后像这样使用:

function UpdateHosts {
param ($hostName)
Write-Host $hostName
$path = 'C:WINDOWSsystem32driversetchosts'
# test if the file is readable/writable
# you can of course also put this in a loop to keep trying for X times
# until Test-LockedFile -Path $path returns $false.
if (Test-LockedFile -Path $path) {
Write-Error "The hosts file is currently locked"
}
else {
try {
$strHosts = (Get-Content $path -Raw -ErrorAction Stop)
if([string]::IsNullOrEmpty($strHosts)) {
Write-Error "Get-Content hosts empty"
exit
}
} 
catch {
Write-Error "Unable to read hosts file:`r`n$($_.Exception.Message)"
exit
}
try {
$strHosts -replace "[d]+.[d]+.[d]+.[d]+s+$hostName", "$ipAddress $hostName" | 
Set-Content -Path $path -Force -ErrorAction Stop
} 
catch {
Write-Error "Unable to write hosts file:`r`n$($_.Exception.Message)"
exit
}
}
}

最新更新