Powershell 设置内容:进程无法访问文件';C:\WINDOWS\system32\drivers\etc\hosts';因为它正被另一个进程使用
我有以下PowerShell脚本:Powershell 设置内容:进程无法访问文件';C:\WINDOWS\system32\drivers\etc\hosts';因为它正被另一个进程使用,powershell,windows-10,hosts,Powershell,Windows 10,Hosts,我有以下PowerShell脚本: param([switch]$Elevated) function Test-Admin { $currentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent()) $currentUser.IsInRole([Security.Principal.WindowsBuiltinRole
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:\WINDOWS\system32\drivers\etc\hosts -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:\WINDOWS\system32\drivers\etc\hosts
} catch {
Write-Error "Unable to write hosts file"
Write-Error $_
exit
}
}
$ipAddress = "127.0.0.1"
UpdateHosts -hostName local.pap360.com
有时,当我运行它时,会出现以下错误:
设置内容:进程无法访问文件“C:\WINDOWS\system32\drivers\etc\hosts”,因为其他进程正在使用该文件
当我在记事本中打开C:\WINDOWS\system32\drivers\etc\hosts时,它是空白的。我所有的数据都被删除了
我的问题是。。。我怎样才能防止这种情况发生
例如,如果设置内容
无法访问主机文件进行写入,那么它如何能够擦除其内容?为什么catch
块不起作用
以下是全部错误:
Set-Content : The process cannot access the file 'C:\WINDOWS\system32\drivers\etc\hosts' because it is being used by
another process.
At C:\path\to\test.ps1:36 char:92
+ ... $hostName" | Set-Content -Path C:\WINDOWS\system32\drivers\etc\hosts
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (C:\WINDOWS\system32\drivers\etc\hosts:String) [Set-Content], IOException
+ FullyQualifiedErrorId : GetContentWriterIOError,Microsoft.PowerShell.Commands.SetContentCommand
我也不明白为什么这样断断续续。是否有某个Windows进程每分钟打开主机文件一次或类似的时间?首先,检查您的防火墙或AV软件是否没有限制对该文件的访问。 如果情况并非如此,并且“某些”其他进程当前正在锁定主机文件,那么在读取或写入文件之前添加测试可能会有所帮助:
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:\WINDOWS\system32\drivers\etc\hosts'
# 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
}
}
}
至于捕获不起作用的原因,请在Get/Set内容命令中添加-EA“Stop”。看看这篇文章,看看是否是同一个问题:@RetiredGeek我同意,但文件访问错误似乎是终止错误,因此无论如何都应该触发捕获。这在我这方面是一个考验。注意:即使将
$ErrorActionPreference
设置为SilentlyContinue,捕获仍会触发,因此我认为他的环境配置也不是问题所在。