Board logo

标题: [问题求助] 使用powershell 修改host文件 [打印本页]

作者: 5i365    时间: 2022-2-27 20:02     标题: 使用powershell 修改host文件

以前一直使用cmd批处理修改host文件, 刚刚在一段ps代码中添加修改host的代码, 就搜索了一下资源, 找到如下代码, 但是测试了一下, 不稳, 问题如下, 请高手指点, 感谢!
问题1. -enc ascii 这个参数居然会把原文件编码格式改为UTF8, 真是怪了
问题2.在已经有记录的情况下,仍然会追加记录
问题3.追加完后,用notepad2打开文件,提示换行符不一致
  1. $IP_URL = "127.0.0.1 www.bing.com"
  2. if ((Get-Content $env:windir\System32\drivers\etc\hosts | ?{ $_ -match "/s$IP_URL" }) -eq $null)
  3. {
  4. "`n$IP_URL" | Out-File "$env:windir\System32\drivers\etc\hosts" -Append -enc ascii
  5. echo "已添加!"
  6. }
  7. else
  8. {
  9. echo "已存在"
  10. }
复制代码

作者: idwma    时间: 2022-2-27 20:21

  1. $IP_URL = "127.0.0.1 www.bing.com"
  2. if ((Get-Content $env:windir\System32\drivers\etc\hosts | ?{ $_ -match "$($IP_URL -replace '\s+','\s+')" }) -eq $null)
  3. {
  4. "$IP_URL" | ac "$env:windir\System32\drivers\etc\hosts"
  5. echo "已添加!"
  6. }
  7. else
  8. {
  9. echo "已存在"
  10. }
复制代码

作者: 5i365    时间: 2022-2-27 20:50

回复 2# idwma


    感谢大侠帮忙, 现在可以了, 请教下面代码中把空格替换成空格什么意思?
$IP_URL -replace '\s+','\s+'
作者: idwma    时间: 2022-2-27 21:17

回复 3# 5i365


    你看这两个是一样的吗?
  1. $IP_URL = "127.0.0.1 www.bing.com"
  2. $IP_URL11 = "127.0.0.1   www.bing.com"
  3. $IP_URL -match $IP_URL11
  4. $IP_URL -match "$($IP_URL11 -replace '\s+','\s+')"
复制代码

作者: 5i365    时间: 2022-2-27 21:22

回复 4# idwma


感谢指点, 是不一样, 我其实不明白的是, 为什么要替换的和替换为的 是一样的正则表达, 按我的理解应该替换为'\s{1}'或'\s'

$IP_URL -match "$($IP_URL11 -replace '\s+','\s{1}')"
作者: idwma    时间: 2022-2-27 21:53

回复 5# 5i365

试试第一行多加几个空格前后增加中间穿插若干个空格
是不是感觉这个替换多于了,不加也可以的
作者: 5i365    时间: 2022-2-28 10:26

回复 6# idwma


    感谢指点, 确实感觉多余了, 不加怎么可以? 我试了不行, 返回false
作者: 5i365    时间: 2022-2-28 10:28

回复 6# idwma


    大侠, 如果是一次添加多行条目, 应该怎么改, 例如:
$IP_URL = @(
        "127.0.0.1 www.bing.com"
        "127.0.0.1 www.sina.com"
)
作者: idwma    时间: 2022-2-28 13:56

  1. $IP_URL = @(
  2.         "127.0.0.1 www.bing.com"
  3.         "127.0.0.1 www.sina.com"
  4. )
  5. $IP_URL -notmatch "$((Get-Content $env:windir\System32\drivers\etc\hosts | ?{ $_ -match "$($IP_URL -join '|')"}) -join '|')"|ac "$env:windir\System32\drivers\etc\hosts"
复制代码

作者: 5i365    时间: 2022-2-28 16:49

回复 9# idwma


    刚试了下, 没有生效
作者: 5i365    时间: 2022-2-28 17:36

回复 9# idwma


    老外的代码参考:
  1. # Uncomment lines with localhost on them:
  2. $hostsPath = "$env:windir\System32\drivers\etc\hosts"
  3. $hosts = get-content $hostsPath
  4. $hosts = $hosts | Foreach {if ($_ -match '^\s*#\s*(.*?\d{1,3}.*?localhost.*)')
  5.                            {$matches[1]} else {$_}}
  6. $hosts | Out-File $hostsPath -enc ascii
  7. # Comment lines with localhost on them:
  8. $hosts = get-content $hostsPath
  9. $hosts | Foreach {if ($_ -match '^\s*([^#].*?\d{1,3}.*?localhost.*)')
  10.                   {"# " + $matches[1]} else {$_}} |
  11.          Out-File $hostsPath -enc ascii
复制代码
-----------------------------------------------------------------------------------------------
  1. function setHostEntries([hashtable] $entries) {
  2.     $hostsFile = "$env:windir\System32\drivers\etc\hosts"
  3.     $newLines = @()
  4.     $c = Get-Content -Path $hostsFile
  5.     foreach ($line in $c) {
  6.         $bits = [regex]::Split($line, "\s+")
  7.         if ($bits.count -eq 2) {
  8.             $match = $NULL
  9.             ForEach($entry in $entries.GetEnumerator()) {
  10.                 if($bits[1] -eq $entry.Key) {
  11.                     $newLines += ($entry.Value + '     ' + $entry.Key)
  12.                     Write-Host Replacing HOSTS entry for $entry.Key
  13.                     $match = $entry.Key
  14.                     break
  15.                 }
  16.             }
  17.             if($match -eq $NULL) {
  18.                 $newLines += $line
  19.             } else {
  20.                 $entries.Remove($match)
  21.             }
  22.         } else {
  23.             $newLines += $line
  24.         }
  25.     }
  26.     foreach($entry in $entries.GetEnumerator()) {
  27.         Write-Host Adding HOSTS entry for $entry.Key
  28.         $newLines += $entry.Value + '     ' + $entry.Key
  29.     }
  30.     Write-Host Saving $hostsFile
  31.     Clear-Content $hostsFile
  32.     foreach ($line in $newLines) {
  33.         $line | Out-File -encoding ASCII -append $hostsFile
  34.     }
  35. }
  36. $entries = @{
  37.     'aaa.foo.local' = "127.0.0.1"
  38.     'bbb.foo.local' = "127.0.0.1"
  39.     'ccc.foo.local' = "127.0.0.1"
  40. };
  41. setHostEntries($entries)
复制代码
--------------------------------------------------------------
  1. $domainName = "www.abc.com"
  2. $rplaceStr = ""
  3. $rHost = "C:\Windows\System32\drivers\etc\hosts"
  4. $items = Get-Content $rHost | Select-String $domainName
  5. Write-host $items
  6. foreach( $item in $items)
  7. {
  8. (Get-Content $rHost) -replace $item, $rplaceStr| Set-Content $rHost
  9. }
复制代码

作者: 5i365    时间: 2022-2-28 18:02

本帖最后由 5i365 于 2022-2-28 18:22 编辑

回复 9# idwma


    自己想了个办法, 但是如果host最后一行不是空行, 则第一行网址会跑到前一行的后面
测试了一下, add-content 确实有这个问题, 文件中最后一行没有空行, 就追加到最后一行的末尾了
  1. $Hosts = "$env:windir\System32\drivers\etc\hosts"
  2. $urls = @(
  3. "www.baidu.com"
  4. "www.bing.com"
  5. ) |
  6. foreach{
  7. if ((gc $Hosts | Select-String $_) -eq $null)
  8. {
  9. ac $hosts "127.0.0.1 $_"
  10. }
  11. }
复制代码

作者: idwma    时间: 2022-2-28 18:24

  1. $IP_URL = @(
  2.         "127.0.0.1 www.bing.com"
  3.         "127.0.0.1 www.sina.com"
  4. )
  5. $a=(Get-Content "$env:windir\System32\drivers\etc\hosts" | ?{ $_ -match "$($IP_URL -join '|')"}) -join '|'
  6. if ($a -eq '')
  7. {
  8. $IP_URL | ac "$env:windir\System32\drivers\etc\hosts"
  9. echo "已添加!"
  10. }
  11. else
  12. {
  13. $IP_URL -notmatch "$a" | ac "$env:windir\System32\drivers\etc\hosts"
  14. echo "已存在"
  15. }
复制代码

作者: 5i365    时间: 2022-2-28 18:29

回复 13# idwma


    大侠, 使用ac和out-file都有这个问题, 最后一行没有空行, 就会追加到最后一行的末尾
作者: idwma    时间: 2022-2-28 18:57

回复 14# 5i365
  1. $Hosts = "$env:windir\System32\drivers\etc\hosts"
  2. $a=gc $Hosts
  3. $urls = @(
  4. "www.baidu.com"
  5. "www.bing.com"
  6. ) |
  7. foreach{
  8. if($a[-1] -ne ''){ac $hosts ''}elseif ((gc $Hosts | Select-String $_) -eq $null)
  9. {
  10. ac $hosts "127.0.0.1 $_"
  11. }
  12. }
复制代码

作者: 5i365    时间: 2022-2-28 19:01

回复 15# idwma


    还是不行, 多了两个空行
作者: 5i365    时间: 2022-2-28 19:25

回复 15# idwma


    搞定了, 把if移到上面去就行了
  1. $Hosts = "$env:windir\System32\drivers\etc\hosts"
  2. $a = gc $Hosts
  3. if ($a[-1] -ne '') { ac $hosts '' }
  4. $urls = @(
  5. "www.baidu.com"
  6. "www.bing.com"
  7. ) |
  8. foreach{
  9. if ((gc $Hosts | Select-String $_) -eq $null)
  10. {
  11. ac $hosts "127.0.0.1 $_"
  12. }
  13. }
复制代码

作者: 5i365    时间: 2022-2-28 20:15

本帖最后由 5i365 于 2022-2-28 20:19 编辑

回复 15# idwma

分享老外写的, 用PS对话框的形式来改HOST, 里面有控件的位置, 尺寸之类的, 感觉应该可以去掉, 应该可以精简, 以前看到过有类似的, 才几行代码就行!
  1. Add-Type -AssemblyName System.Windows.Forms
  2. Add-Type -AssemblyName System.Drawing
  3. $hostsfilelocation = "$env:windir\System32\drivers\etc\hosts"
  4. $readhostsfile = Get-Content $hostsfilelocation
  5. $form = New-Object System.Windows.Forms.Form
  6. $form.Text = 'Update HOSTS File'
  7. $form.Size = New-Object System.Drawing.Size(300, 200)
  8. $form.StartPosition = 'CenterScreen'
  9. $AddHosts = New-Object System.Windows.Forms.Button
  10. $AddHosts.Location = New-Object System.Drawing.Point(55, 120)
  11. $AddHosts.Size = New-Object System.Drawing.Size(90, 25)
  12. $AddHosts.Text = 'Add Record'
  13. $AddHosts.DialogResult = [System.Windows.Forms.DialogResult]::OK
  14. $form.AcceptButton = $AddHosts
  15. $form.Controls.Add($AddHosts)
  16. $CancelButton = New-Object System.Windows.Forms.Button
  17. $CancelButton.Location = New-Object System.Drawing.Point(170, 120)
  18. $CancelButton.Size = New-Object System.Drawing.Size(75, 25)
  19. $CancelButton.Text = 'Cancel'
  20. $CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
  21. $form.CancelButton = $CancelButton
  22. $form.Controls.Add($CancelButton)
  23. $Hostslabel = New-Object System.Windows.Forms.Label
  24. $Hostslabel.Location = New-Object System.Drawing.Point(10, 20)
  25. $Hostslabel.Size = New-Object System.Drawing.Size(280, 20)
  26. $Hostslabel.Text = 'Enter New HOSTNAME/FQDN:'
  27. $form.Controls.Add($Hostslabel)
  28. $HoststextBox = New-Object System.Windows.Forms.TextBox
  29. $HoststextBox.Location = New-Object System.Drawing.Point(10, 40)
  30. $HoststextBox.Size = New-Object System.Drawing.Size(260, 20)
  31. $form.Controls.Add($HoststextBox)
  32. $IPlabel = New-Object System.Windows.Forms.Label
  33. $IPlabel.Location = New-Object System.Drawing.Point(10, 60)
  34. $IPlabel.Size = New-Object System.Drawing.Size(280, 20)
  35. $IPlabel.Text = 'Enter IP:'
  36. $form.Controls.Add($IPlabel)
  37. $IPtextBox = New-Object System.Windows.Forms.TextBox
  38. $IPtextBox.Location = New-Object System.Drawing.Point(10, 80)
  39. $IPtextBox.Size = New-Object System.Drawing.Size(260, 20)
  40. $form.Controls.Add($IPtextBox)
  41. $form.Topmost = $true
  42. $form.Add_Shown({ ($HoststextBox, $IPtextbox).Select() })
  43. $result = $form.ShowDialog()
  44. if ($result -eq [System.Windows.Forms.DialogResult]::OK)
  45. {
  46. $inputhosts = $HoststextBox.Text
  47. $inputip = $IPtextBox.Text
  48. $newrecord = "$inputip $inputhosts"
  49. Add-Content -Path $hostsfilelocation -Value $newrecord
  50. }
复制代码

作者: idwma    时间: 2022-2-28 20:26

这么绕的吗,直接用记事本打开不好吗
作者: 5i365    时间: 2022-3-1 07:52

回复 19# idwma


  嗯, 偶尔改手动更方便些, 改多台电脑时, 用批处理改不用到电脑旁边, 不用远程就改, 非常方便




欢迎光临 批处理之家 (http://bathome.net./) Powered by Discuz! 7.2