Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Powershell 设置内容:进程无法访问文件';C:\WINDOWS\system32\drivers\etc\hosts';因为它正被另一个进程使用_Powershell_Windows 10_Hosts - Fatal编程技术网

Powershell 设置内容:进程无法访问文件';C:\WINDOWS\system32\drivers\etc\hosts';因为它正被另一个进程使用

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

我有以下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:\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,捕获仍会触发,因此我认为他的环境配置也不是问题所在。