【问题标题】:Can't set Chrome as default browser from Powershell无法从 Powershell 将 Chrome 设置为默认浏览器
【发布时间】:2013-07-06 08:41:13
【问题描述】:

我正在运行以下 powershell 命令

$chromePath = "${Env:ProgramFiles(x86)}\Google\Chrome\Application\" 
$chromeApp = "chrome.exe"
$chromeCommandArgs = @('--make-default-browser')
Invoke-Expression “cmd.exe /C `"$chromePath$chromeApp`" $chromeCommandArgs”

不幸的是,当我运行它时,我收到以下错误消息。

cmd.exe : [1396:2128:0708/153347:ERROR:gpu_info_collector_win.cc(98)] 无法检索有效的 WinSAT 评估。 在行:1 字符:1 + cmd.exe /C "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --make- ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: ([1396:2128:0708...SAT 评估.:String) [], RemoteException + FullyQualifiedErrorId : NativeCommandError

[1396:2128:0708/153347:ERROR:shell_integration_win.cc(200)] Chrome 无法设置为默认浏览器。

什么可能导致此错误?我意识到执行命令有多种方式,但最重要的是使用--make-default-browser 开关执行 Chrome 失败。

【问题讨论】:

  • 这是特定于 PowerShell 的问题吗?换句话说,它是否可以通过标准命令行在您的机器上运行?
  • 我可以在 Chrome 的设置中进行设置。如果我直接运行cmd 不会引发错误,但似乎也没有设置设置。
  • 我喜欢这个准确描述我的问题并显示在我的 Google 搜索顶部的问题如何被否决,但排名最高的答案有一个死链接。

标签: powershell


【解决方案1】:

以下内容对我有用:

$chromePath = "${Env:ProgramFiles(x86)}\Google\Chrome\Application\" 
$chromeApp = "chrome.exe"
$chromeCommandArgs = "--make-default-browser"
& "$chromePath$chromeApp" $chromeCommandArgs

【讨论】:

  • 是的,我试过了。我现在想知道这是否是 Chrome/Win8 中的问题。我全新安装了 Win8,我使用 Chocolatey 安装了 chrome cinstm GoogleChrome
【解决方案2】:

WinSAT 是 Windows 系统评估工具。它测量系统性能:CPU、内存、图形和硬盘速度,并得出一个从 1 到 7.9 的数字,它应该代表您的系统性能。软件发行商(主要是图形密集型游戏)应该发布最低 WinSAT 分数,以便从他们的游戏中获得良好的体验。 (这是Win7之前的方案,具体使用到什么程度我不知道)。

无论如何,您可以转到控制面板,系统,您应该会在窗口中间看到“评级”。您可以点击它旁边的消息来获得评分。

我认为 Chrome 是在抱怨没有评级。 (虽然它是 Chrome 还是 CMD 是一个很大的歧义)尝试评估您的系统,看看它是否有效。

【讨论】:

    【解决方案3】:

    改编自this archived poshcode user script,您可以通过它在 Chrome、Firefox、Internet Explorer、Opera 和 Safari 之间切换。像这样添加Set-DefaultBrowser 函数:

    function Set-DefaultBrowser
    {
        param($defaultBrowser)
    
        $regKey      = "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\{0}\UserChoice"
        $regKeyFtp   = $regKey -f 'ftp'
        $regKeyHttp  = $regKey -f 'http'
        $regKeyHttps = $regKey -f 'https'
    
        switch -Regex ($defaultBrowser.ToLower())
        {
            # Internet Explorer
            'ie|internet|explorer' {
                Set-ItemProperty $regKeyFtp   -name ProgId IE.FTP
                Set-ItemProperty $regKeyHttp  -name ProgId IE.HTTP
                Set-ItemProperty $regKeyHttps -name ProgId IE.HTTPS
                break
            }
            # Firefox
            'ff|firefox' {
                Set-ItemProperty $regKeyFtp   -name ProgId FirefoxURL
                Set-ItemProperty $regKeyHttp  -name ProgId FirefoxURL
                Set-ItemProperty $regKeyHttps -name ProgId FirefoxURL
                break
            }
            # Google Chrome
            'cr|google|chrome' {
                Set-ItemProperty $regKeyFtp   -name ProgId ChromeHTML
                Set-ItemProperty $regKeyHttp  -name ProgId ChromeHTML
                Set-ItemProperty $regKeyHttps -name ProgId ChromeHTML
                break
            }
            # Safari
            'sa*|apple' {
                Set-ItemProperty $regKeyFtp   -name ProgId SafariURL
                Set-ItemProperty $regKeyHttp  -name ProgId SafariURL
                Set-ItemProperty $regKeyHttps -name ProgId SafariURL
                break
            }
            # Opera
            'op*' {
                Set-ItemProperty $regKeyFtp   -name ProgId Opera.Protocol
                Set-ItemProperty $regKeyHttp  -name ProgId Opera.Protocol
                Set-ItemProperty $regKeyHttps -name ProgId Opera.Protocol
                break
            }
        } 
    
    }
    

    然后使用您想要的浏览器调用它,如下所示:

    Set-DefaultBrowser cr # cr|ff|ie|op|sa
    

    您可以像这样检查注册表中设置的值是否正确:

    (Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\ftp\UserChoice').ProgId
    (Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice').ProgId
    (Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice').ProgId
    

    我已经使用以下版本的所有 5 种浏览器进行了测试:

    • 铬 = 39
    • 火狐=34
    • Internet Explorer = 11
    • 歌剧 = 11
    • Safari = 5

    延伸阅读How Does Your Browser Know that It’s Not The Default?

    【讨论】:

    • 我刚刚在 Windows 10 中尝试过,但没有成功。它刚刚触发了以下 Windows 错误:An app caused a problem with your default browser setting, so it was reset to Microsoft Edge.
    • @Sam,这是一个已知的 Windows 10 问题。请参阅:winhelponline.com/blog/windows-10-resetting-file-associationswinaero.com/blog/…
    • 我只是想知道如何将 Opera 添加到 lis 选项中。
    • @jorgemits 作为最后一个选项已经存在
    【解决方案4】:

    在寻找答案的过程中,我找到了 Kolbicz 博客,它展示了如何使用 SetDefaultBrowser.exe 执行此操作。这要简单得多。设置默认浏览器 - SetDefaultBrowserSetUserFTA 设置用户对默认程序的选择。

    我从@TechSpud 获取代码并进行了一些更改。还包括来自Disassambler's Github Win10-Initial-Setup-Script 的一些功能并删除了 Safari。 我手动进行了更改以查看注册表中所做的更改,并观察到浏览器 ProgID 的哈希值也发生了更改:

    <dl>
    <dt>opera</dt><dd>https: 84VcShSmrms=   <br>http: EBgmhN4KR60=  <br>ProgID: OperaStable</dd>
    <dt>vivaldi</dt><dd>https: wxeuCoUyJR0= <br>http: Pr6mP1NhKy0=  <br>ProgID: VivaldiHTM.AQHSUMD27WSPRY7GH5RXFKR6WM</dd>
    <dt>chrome</dt><dd>https: /vl+ronxuA4=  <br>http: k9Da/QqU74c=  <br>ProgID: ChromeHTML</dd>
    <dt>firefox</dt><dd>https: IhKJ36zo2D8= <br>http: yWnRoYQTfbs=  <br>ProgID: FirefoxURL-308046B0AF4A39CB</dd>
    <dt>chromium</dt><dd>https: EWoUqQneOv4=    <br>http: Kh+mL2zZByo=  <br>ProgID: ChromiumHTM</dd>
    <dt>edge</dt><dd>https: kQz/gLoO7oo=    <br>http: 1cwyZ2KB040=  <br>ProgID: AppX90nv6nhay5n6a98fnetv7tpk64pp35es</dd>
    <dt>brave</dt><dd>https: 90HsnuS5S6M=   <br>http: wlBpCu412iI=  <br>ProgID: BraveHTML</dd>
    <dt>waterfox</dt><dd>https: j9aaZZ30p3Y=    <br>http: e3oYc6aZ6UA=  <br>ProgID: WaterfoxURL-6F940AC27A98DD61</dd>
    <dt>ie</dt><dd>https: m1UWOHOva/s= <br>http: 98qL1nQ8CNQ=  <br>ProgID: IE.HTTPS</dd>
    </dl>
    

    我提取了代码中的所有哈希值并进行了测试。工作!

    Function Restart {
        Write-Output "Restarting..."
        Restart-Computer
    }
    Function ChangeTheDefaultBrowser {
        param($defaultBrowser)
    
        $regKey = "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\{0}\UserChoice"
        $regKeyHttp = $regKey -f 'http'
        $regKeyHttps = $regKey -f 'https'
    
        switch -Regex ($defaultBrowser.ToLower()) {
            # Brave Browser
            # https://brave.com
            'bb|brave' {
                Write-Output "`nChanging to Brave as the default browser $ThisUser..."
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name ProgId BraveHTML
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name Hash wlBpCu412iI=
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name ProgId BraveHTML
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name Hash 90HsnuS5S6M=
                break
            }
            # Google Chrome
            # https://www.google.com/chrome/
            'gc|google|chrome' {
                Write-Output "`nChanging to Chrome as the default browser..."
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name ProgId ChromeHTML
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name Hash k9Da/QqU74c=
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name ProgId ChromeHTML
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name Hash /vl+ronxuA4=
                break
            }
            # Chromium Browser
            # https://www.chromium.org/getting-involved/download-chromium
            'cb|chromium' {
                Write-Output "`nChanging to Chromium as the default browser..."
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name ProgId ChromiumHTM
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name Hash Kh+mL2zZByo=
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name ProgId ChromiumHTM
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name Hash EWoUqQneOv4=
                break
            }
            # Microsoft Edge
            # https://www.microsoft.com/pt-br/windows/microsoft-edge
            'me|edge' {
                Write-Output "`nChanging to Edge as the default browser..."
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name ProgId AppX90nv6nhay5n6a98fnetv7tpk64pp35es
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name Hash 1cwyZ2KB040=
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name ProgId AppX90nv6nhay5n6a98fnetv7tpk64pp35es
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name Hash kQz/gLoO7oo=
                break
            }
            # Internet Explorer
            # https://www.microsoft.com/pt-br/download/internet-explorer.aspx
            'ie|internet|explorer' {
                Write-Output "`nChanging to Explorer as the default browser..."
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name ProgId IE.HTTP
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name Hash 98qL1nQ8CNQ=
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name ProgId IE.HTTPS
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name Hash m1UWOHOva/s=
                break
            }
            # Mozilla Firefox
            # https://www.mozilla.org/
            'ff|firefox' {
                Write-Output "`nChanging to Firefox as the default browser..."
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name ProgId FirefoxURL-308046B0AF4A39CB
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name Hash yWnRoYQTfbs=
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name ProgId FirefoxURL-308046B0AF4A39CB
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name Hash IhKJ36zo2D8=
                break
            }
            # Opera Browser
            # https://www.opera.com/
            'ob|opera' {
                Write-Output "`nChanging to Opera as the default browser..."
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name ProgId OperaStable
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name Hash EBgmhN4KR60=
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name ProgId OperaStable
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name Hash 84VcShSmrms=
                break
            }
            # The Waterfox Project
            # https://www.waterfoxproject.org/
            'wf|waterfox' {
                Write-Output "`nChanging to Waterfox as the default browser..."
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name ProgId WaterfoxURL-6F940AC27A98DD61
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name Hash e3oYc6aZ6UA=
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name ProgId WaterfoxURL-6F940AC27A98DD61
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name Hash j9aaZZ30p3Y=
                break
            }
            # Vivaldi
            # https://vivaldi.com
            'vi|vivaldi' {
                Write-Output "`nChanging to Vivaldi as the default browser..."
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name ProgId VivaldiHTM.AQHSUMD27WSPRY7GH5RXFKR6WM
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name Hash Pr6mP1NhKy0=
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name ProgId VivaldiHTM.AQHSUMD27WSPRY7GH5RXFKR6WM
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name Hash wxeuCoUyJR0=
                break
            }
        } 
    
        # thanks to http://newoldthing.wordpress.com/2007/03/23/how-does-your-browsers-know-that-its-not-the-default-browser/
    
    }
    Function RestoreTheDefaultBrowser {
        param($defaultBrowser)
    
        $regKey = "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\{0}\UserChoice"
        #$HKLMregKey = "Computador\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\{0}\"
        $regKeyHttp = $regKey -f 'http'
        $regKeyHttps = $regKey -f 'https'
    
        switch -Regex ($defaultBrowser.ToLower()) {
            # Why, Mister Anderson?! Why?!
            # Microsoft Edge
            # https://www.microsoft.com/pt-br/windows/microsoft-edge
            'me|edge' {
                Write-Output "`nChanging back to Edge..."
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name ProgId AppX90nv6nhay5n6a98fnetv7tpk64pp35es
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttp  -name Hash 1cwyZ2KB040=
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name ProgId AppX90nv6nhay5n6a98fnetv7tpk64pp35es
                Set-ItemProperty -Force -PassThru -Verbose $regKeyHttps -name Hash kQz/gLoO7oo=
                break
            }
        }
    }
    
    # Uncomment one of the lines below
    #ChangeTheDefaultBrowser bb
    #ChangeTheDefaultBrowser gc
    #ChangeTheDefaultBrowser cb
    #ChangeTheDefaultBrowser me
    #ChangeTheDefaultBrowser ie
    #ChangeTheDefaultBrowser ff
    #ChangeTheDefaultBrowser ob
    #ChangeTheDefaultBrowser wf
    ChangeTheDefaultBrowser vi
    Write-Host "`n Changes made for the current user"
    # Wait for keypress
    Write-Host "`n Is necessary to restart your computer"
    WaitForKey
    # Restart computer
    Restart
    

    但是再次测试后,Edge 又开始被设置为默认值,我不知道为什么。我认为这是“了不起”的 Windows 10 在做它的事情,在某种程度上,确实如此。每次您设置默认浏览器时,即使是相同的浏览器、相同的版本、相同的机器、相同的用户配置文件,无论是几秒钟后,哈希值都会发生变化。所以代码可以正常工作。

    【讨论】:

    • 您应该将关于“The Kolbicz Blog”的内容放在答案的顶部而不是底部,以获得更好的可见性。
    【解决方案5】:

    您可以使用以下 PowerShell 脚本将默认浏览器更改为 Mozilla:

    function Set-DefaultBrowser {
        Add-Type -AssemblyName 'System.Windows.Forms'
        Start-Process $env:windir\system32\control.exe -LoadUserProfile -Wait `
            -ArgumentList '/name Microsoft.DefaultPrograms /page pageDefaultProgram\pageAdvancedSettings?pszAppName=Firefox-308046B0AF4A39CB'
        Sleep 2
        [System.Windows.Forms.SendKeys]::SendWait("{TAB}{TAB}{DOWN}{DOWN} {DOWN} {DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN} {DOWN} {TAB} ")
    }
    Set-DefaultBrowser
    

    【讨论】:

      【解决方案6】:

      以下代码适用于 GCP Windows 10 服务器映像:

      function Set-DefaultBrowser {
          Add-Type -AssemblyName 'System.Windows.Forms'
          Start-Process $env:windir\system32\control.exe -LoadUserProfile -Wait `
              -ArgumentList '/name Microsoft.DefaultPrograms /page pageDefaultProgram\pageAdvancedSettings?pszAppName=Firefox-308046B0AF4A39CB'
          Sleep 10
          [System.Windows.Forms.SendKeys]::SendWait("{TAB}{TAB}{TAB}{TAB}{TAB} {ENTER}{ENTER} ")
      }
      
      Set-DefaultBrowser
      

      【讨论】:

      • 我使代码更短/更简单:start ms-settings:defaultapps Sleep 10 # wait 10sec for it to open # tabs down to default browser, &amp; selects the first one, would have to enter {DOWN} however many times to select another browser, its in alphabatical format [System.Windows.Forms.SendKeys]::SendWait("{TAB 5} {ENTER 2}") Sleep 2 # wait 2sec then press Alt+F4 to close Settings. If I didn't wait the default browser didn't get changed [System.Windows.Forms.SendKeys]::SendWait("%{F4}")
      【解决方案7】:

      我在here 上找到了一个不错的脚本,您可以轻松地使用它来更改默认浏览器:

      <#
      .SYNOPSIS
          Set File Type Association Windows 8/10
      .DESCRIPTION
          Set File/Protocol Type Association Default Application Windows 8/10
      .NOTES
          Version    : 1.1.0
          Author(s)  : Danyfirex & Dany3j
          Credits    : https://bbs.pediy.com/thread-213954.htm
                       LMongrain - Hash Algorithm PureBasic Version
          License    : MIT License
          Copyright  : 2020 Danysys. <danysys.com>
        
      .EXAMPLE
          Get-FTA
          Show All Application Program Id
      .EXAMPLE
          Get-FTA .pdf
          Show Default Application Program Id for an Extension
          
      .EXAMPLE
          Set-FTA AcroExch.Document.DC .pdf
          Set Acrobat Reader DC as Default .pdf reader
       
      .EXAMPLE
          Set-FTA Applications\SumatraPDF.exe .pdf
          Set Sumatra PDF as Default .pdf reader
      .EXAMPLE
          Set-PTA ChromeHTML http
          Set Google Chrome as Default for http Protocol
      .EXAMPLE
          Register-FTA "C:\SumatraPDF.exe" .pdf -Icon "shell32.dll,100"
          Register Application and Set as Default for .pdf reader
      .LINK
          https://github.com/DanysysTeam/PS-SFTA
          
      #>
      
      function Get-FTA {
        [CmdletBinding()]
        param (
          [Parameter(Mandatory = $false)]
          [String]
          $Extension
        )
      
        
        if ($Extension) {
          Write-Verbose "Get File Type Association for $Extension"
          
          $assocFile = (Get-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice"-ErrorAction SilentlyContinue).ProgId
          Write-Output $assocFile
        }
        else {
          Write-Verbose "Get File Type Association List"
      
          $assocList = Get-ChildItem HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\* |
          ForEach-Object {
            $progId = (Get-ItemProperty "$($_.PSParentPath)\$($_.PSChildName)\UserChoice" -ErrorAction SilentlyContinue).ProgId
            if ($progId) {
              "$($_.PSChildName), $progId"
            }
          }
          Write-Output $assocList
        }
        
      }
      
      
      function Register-FTA {
        [CmdletBinding()]
        param (
          [Parameter( Position = 0, Mandatory = $true)]
          [ValidateScript( { Test-Path $_ })]
          [String]
          $ProgramPath,
      
          [Parameter( Position = 1, Mandatory = $true)]
          [Alias("Protocol")]
          [String]
          $Extension,
          
          [Parameter( Position = 2, Mandatory = $false)]
          [String]
          $ProgId,
          
          [Parameter( Position = 3, Mandatory = $false)]
          [String]
          $Icon
        )
      
        Write-Verbose "Register Application + Set Association"
        Write-Verbose "Application Path: $ProgramPath"
        if ($Extension.Contains(".")) {
          Write-Verbose "Extension: $Extension"
        }
        else {
          Write-Verbose "Protocol: $Extension"
        }
        
        if (!$ProgId) {
          $ProgId = "SFTA." + [System.IO.Path]::GetFileNameWithoutExtension($ProgramPath).replace(" ", "") + $Extension
        }
        
        $progCommand = """$ProgramPath"" ""%1"""
        Write-Verbose "ApplicationId: $ProgId" 
        Write-Verbose "ApplicationCommand: $progCommand"
        
        try {
          $keyPath = "HKEY_CURRENT_USER\SOFTWARE\Classes\$Extension\OpenWithProgids"
          [Microsoft.Win32.Registry]::SetValue( $keyPath, $ProgId, ([byte[]]@()), [Microsoft.Win32.RegistryValueKind]::None)
          $keyPath = "HKEY_CURRENT_USER\SOFTWARE\Classes\$ProgId\shell\open\command"
          [Microsoft.Win32.Registry]::SetValue($keyPath, "", $progCommand)
          Write-Verbose "Register ProgId and ProgId Command OK"
        }
        catch {
          throw "Register ProgId and ProgId Command FAIL"
        }
        
        Set-FTA -ProgId $ProgId -Extension $Extension -Icon $Icon
      }
      
      
      function Remove-FTA {
        [CmdletBinding()]
        param (
          [Parameter(Mandatory = $true)]
          [Alias("ProgId")]
          [String]
          $ProgramPath,
      
          [Parameter(Mandatory = $true)]
          [String]
          $Extension
        )
        
        function local:Remove-UserChoiceKey {
          param (
            [Parameter( Position = 0, Mandatory = $True )]
            [String]
            $Key
          )
      
          $code = @'
          using System;
          using System.Runtime.InteropServices;
          using Microsoft.Win32;
          
          namespace Registry {
            public class Utils {
              [DllImport("advapi32.dll", SetLastError = true)]
              private static extern int RegOpenKeyEx(UIntPtr hKey, string subKey, int ulOptions, int samDesired, out UIntPtr hkResult);
          
              [DllImport("advapi32.dll", SetLastError=true, CharSet = CharSet.Unicode)]
              private static extern uint RegDeleteKey(UIntPtr hKey, string subKey);
              public static void DeleteKey(string key) {
                UIntPtr hKey = UIntPtr.Zero;
                RegOpenKeyEx((UIntPtr)0x80000001u, key, 0, 0x20019, out hKey);
                RegDeleteKey((UIntPtr)0x80000001u, key);
              }
            }
          }
      '@
      
          try {
            Add-Type -TypeDefinition $code
          }
          catch {}
      
          try {
            [Registry.Utils]::DeleteKey($Key)
          }
          catch {} 
        } 
      
        function local:Update-Registry {
          $code = @'
          [System.Runtime.InteropServices.DllImport("Shell32.dll")] 
          private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
          public static void Refresh() {
              SHChangeNotify(0x8000000, 0, IntPtr.Zero, IntPtr.Zero);    
          }
      '@ 
      
          try {
            Add-Type -MemberDefinition $code -Namespace SHChange -Name Notify
          }
          catch {}
      
          try {
            [SHChange.Notify]::Refresh()
          }
          catch {} 
        }
      
        if (Test-Path -Path $ProgramPath) {
          $ProgId = "SFTA." + [System.IO.Path]::GetFileNameWithoutExtension($ProgramPath).replace(" ", "") + $Extension
        }
        else {
          $ProgId = $ProgramPath
        }
      
        try {
          $keyPath = "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice"
          Write-Verbose "Remove User UserChoice Key If Exist: $keyPath"
          Remove-UserChoiceKey $keyPath
      
          $keyPath = "HKCU:\SOFTWARE\Classes\$ProgId"
          Write-Verbose "Remove Key If Exist: $keyPath"
          Remove-Item -Path $keyPath -Recurse -ErrorAction Stop | Out-Null
          
        }
        catch {
          Write-Verbose "Key No Exist: $keyPath"
        }
      
        try {
          $keyPath = "HKCU:\SOFTWARE\Classes\$Extension\OpenWithProgids"
          Write-Verbose "Remove Property If Exist: $keyPath Property $ProgId"
          Remove-ItemProperty -Path $keyPath -Name $ProgId  -ErrorAction Stop | Out-Null
          
        }
        catch {
          Write-Verbose "Property No Exist: $keyPath Property: $ProgId"
        } 
      
        Update-Registry
        Write-Output "Removed: $ProgId" 
      }
      
      
      function Set-FTA {
      
        [CmdletBinding()]
        param (
          [Parameter(Mandatory = $true)]
          [String]
          $ProgId,
      
          [Parameter(Mandatory = $true)]
          [Alias("Protocol")]
          [String]
          $Extension,
            
          [String]
          $Icon
        )
        
        if (Test-Path -Path $ProgId) {
          $ProgId = "SFTA." + [System.IO.Path]::GetFileNameWithoutExtension($ProgId).replace(" ", "") + $Extension
        }
      
        Write-Verbose "ProgId: $ProgId"
        Write-Verbose "Extension/Protocol: $Extension"
      
      
        function local:Update-RegistryChanges {
          $code = @'
          [System.Runtime.InteropServices.DllImport("Shell32.dll")] 
          private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
          public static void Refresh() {
              SHChangeNotify(0x8000000, 0, IntPtr.Zero, IntPtr.Zero);    
          }
      '@ 
      
          try {
            Add-Type -MemberDefinition $code -Namespace SHChange -Name Notify
          }
          catch {}
      
          try {
            [SHChange.Notify]::Refresh()
          }
          catch {} 
        }
        
      
        function local:Set-Icon {
          param (
            [Parameter( Position = 0, Mandatory = $True )]
            [String]
            $ProgId,
      
            [Parameter( Position = 1, Mandatory = $True )]
            [String]
            $Icon
          )
      
          try {
            $keyPath = "HKEY_CURRENT_USER\SOFTWARE\Classes\$ProgId\DefaultIcon"
            [Microsoft.Win32.Registry]::SetValue($keyPath, "", $Icon) 
            Write-Verbose "Write Reg Icon OK"
            Write-Verbose "Reg Icon: $keyPath"
          }
          catch {
            Write-Verbose "Write Reg Icon Fail"
          }
        }
      
      
        function local:Write-ExtensionKeys {
          param (
            [Parameter( Position = 0, Mandatory = $True )]
            [String]
            $ProgId,
      
            [Parameter( Position = 1, Mandatory = $True )]
            [String]
            $Extension,
      
            [Parameter( Position = 2, Mandatory = $True )]
            [String]
            $ProgHash
          )
          
      
          function local:Remove-UserChoiceKey {
            param (
              [Parameter( Position = 0, Mandatory = $True )]
              [String]
              $Key
            )
      
            $code = @'
            using System;
            using System.Runtime.InteropServices;
            using Microsoft.Win32;
            
            namespace Registry {
              public class Utils {
                [DllImport("advapi32.dll", SetLastError = true)]
                private static extern int RegOpenKeyEx(UIntPtr hKey, string subKey, int ulOptions, int samDesired, out UIntPtr hkResult);
            
                [DllImport("advapi32.dll", SetLastError=true, CharSet = CharSet.Unicode)]
                private static extern uint RegDeleteKey(UIntPtr hKey, string subKey);
        
                public static void DeleteKey(string key) {
                  UIntPtr hKey = UIntPtr.Zero;
                  RegOpenKeyEx((UIntPtr)0x80000001u, key, 0, 0x20019, out hKey);
                  RegDeleteKey((UIntPtr)0x80000001u, key);
                }
              }
            }
      '@
        
            try {
              Add-Type -TypeDefinition $code
            }
            catch {}
      
            try {
              [Registry.Utils]::DeleteKey($Key)
            }
            catch {} 
          } 
      
          
          try {
            $keyPath = "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice"
            Write-Verbose "Remove Extension UserChoice Key If Exist: $keyPath"
            Remove-UserChoiceKey $keyPath
          }
          catch {
            Write-Verbose "Extension UserChoice Key No Exist: $keyPath"
          }
        
      
          try {
            $keyPath = "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\$Extension\UserChoice"
            [Microsoft.Win32.Registry]::SetValue($keyPath, "Hash", $ProgHash)
            [Microsoft.Win32.Registry]::SetValue($keyPath, "ProgId", $ProgId)
            Write-Verbose "Write Reg Extension UserChoice OK"
          }
          catch {
            throw "Write Reg Extension UserChoice FAIL"
          }
        }
      
      
        function local:Write-ProtocolKeys {
          param (
            [Parameter( Position = 0, Mandatory = $True )]
            [String]
            $ProgId,
      
            [Parameter( Position = 1, Mandatory = $True )]
            [String]
            $Protocol,
      
            [Parameter( Position = 2, Mandatory = $True )]
            [String]
            $ProgHash
          )
            
      
          try {
            $keyPath = "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\$Protocol\UserChoice"
            Write-Verbose "Remove Protocol UserChoice Key If Exist: $keyPath"
            Remove-Item -Path $keyPath -Recurse -ErrorAction Stop | Out-Null
          
          }
          catch {
            Write-Verbose "Protocol UserChoice Key No Exist: $keyPath"
          }
        
      
          try {
            $keyPath = "HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\$Protocol\UserChoice"
            [Microsoft.Win32.Registry]::SetValue( $keyPath, "Hash", $ProgHash)
            [Microsoft.Win32.Registry]::SetValue($keyPath, "ProgId", $ProgId)
            Write-Verbose "Write Reg Protocol UserChoice OK"
          }
          catch {
            throw "Write Reg Protocol UserChoice FAIL"
          }
          
        }
      
        
        function local:Get-UserExperience {
          [OutputType([string])]
            
          $userExperienceSearch = "User Choice set via Windows User Experience"
          $user32Path = [Environment]::GetFolderPath([Environment+SpecialFolder]::SystemX86) + "\Shell32.dll"
          $fileStream = [System.IO.File]::Open($user32Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)
          $binaryReader = New-Object System.IO.BinaryReader($fileStream)
          [Byte[]] $bytesData = $binaryReader.ReadBytes(5mb)
          $fileStream.Close()
          $dataString = [Text.Encoding]::Unicode.GetString($bytesData)
          $position1 = $dataString.IndexOf($userExperienceSearch)
          $position2 = $dataString.IndexOf("}", $position1)
      
          Write-Output $dataString.Substring($position1, $position2 - $position1 + 1)
        }
        
      
        function local:Get-UserSid {
          [OutputType([string])]
          $userSid = ((New-Object System.Security.Principal.NTAccount([Environment]::UserName)).Translate([System.Security.Principal.SecurityIdentifier]).value).ToLower()
          Write-Output $userSid
        }
      
      
        function local:Get-HexDateTime {
          [OutputType([string])]
      
          $now = [DateTime]::Now
          $dateTime = [DateTime]::New($now.Year, $now.Month, $now.Day, $now.Hour, $now.Minute, 0)
          $fileTime = $dateTime.ToFileTime()
          $hi = ($fileTime -shr 32)
          $low = ($fileTime -band 0xFFFFFFFFL)
          $dateTimeHex = ($hi.ToString("X8") + $low.ToString("X8")).ToLower()
          Write-Output $dateTimeHex
        }
        
        function Get-Hash {
          [CmdletBinding()]
          param (
            [Parameter( Position = 0, Mandatory = $True )]
            [string]
            $BaseInfo
          )
      
      
          function local:Get-ShiftRight {
            [CmdletBinding()]
            param (
              [Parameter( Position = 0, Mandatory = $true)]
              [long] $iValue, 
                  
              [Parameter( Position = 1, Mandatory = $true)]
              [int] $iCount 
            )
          
            if ($iValue -band 0x80000000) {
              Write-Output (( $iValue -shr $iCount) -bxor 0xFFFF0000)
            }
            else {
              Write-Output  ($iValue -shr $iCount)
            }
          }
          
      
          function local:Get-Long {
            [CmdletBinding()]
            param (
              [Parameter( Position = 0, Mandatory = $true)]
              [byte[]] $Bytes,
          
              [Parameter( Position = 1)]
              [int] $Index = 0
            )
          
            Write-Output ([BitConverter]::ToInt32($Bytes, $Index))
          }
          
      
          function local:Convert-Int32 {
            param (
              [Parameter( Position = 0, Mandatory = $true)]
              $Value
            )
          
            [byte[]] $bytes = [BitConverter]::GetBytes($Value)
            return [BitConverter]::ToInt32( $bytes, 0) 
          }
      
          [Byte[]] $bytesBaseInfo = [System.Text.Encoding]::Unicode.GetBytes($baseInfo) 
          $bytesBaseInfo += 0x00, 0x00  
          
          $MD5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
          [Byte[]] $bytesMD5 = $MD5.ComputeHash($bytesBaseInfo)
          
          $lengthBase = ($baseInfo.Length * 2) + 2 
          $length = (($lengthBase -band 4) -le 1) + (Get-ShiftRight $lengthBase  2) - 1
          $base64Hash = ""
      
          if ($length -gt 1) {
          
            $map = @{PDATA = 0; CACHE = 0; COUNTER = 0 ; INDEX = 0; MD51 = 0; MD52 = 0; OUTHASH1 = 0; OUTHASH2 = 0;
              R0 = 0; R1 = @(0, 0); R2 = @(0, 0); R3 = 0; R4 = @(0, 0); R5 = @(0, 0); R6 = @(0, 0); R7 = @(0, 0)
            }
          
            $map.CACHE = 0
            $map.OUTHASH1 = 0
            $map.PDATA = 0
            $map.MD51 = (((Get-Long $bytesMD5) -bor 1) + 0x69FB0000L)
            $map.MD52 = ((Get-Long $bytesMD5 4) -bor 1) + 0x13DB0000L
            $map.INDEX = Get-ShiftRight ($length - 2) 1
            $map.COUNTER = $map.INDEX + 1
          
            while ($map.COUNTER) {
              $map.R0 = Convert-Int32 ((Get-Long $bytesBaseInfo $map.PDATA) + [long]$map.OUTHASH1)
              $map.R1[0] = Convert-Int32 (Get-Long $bytesBaseInfo ($map.PDATA + 4))
              $map.PDATA = $map.PDATA + 8
              $map.R2[0] = Convert-Int32 (($map.R0 * ([long]$map.MD51)) - (0x10FA9605L * ((Get-ShiftRight $map.R0 16))))
              $map.R2[1] = Convert-Int32 ((0x79F8A395L * ([long]$map.R2[0])) + (0x689B6B9FL * (Get-ShiftRight $map.R2[0] 16)))
              $map.R3 = Convert-Int32 ((0xEA970001L * $map.R2[1]) - (0x3C101569L * (Get-ShiftRight $map.R2[1] 16) ))
              $map.R4[0] = Convert-Int32 ($map.R3 + $map.R1[0])
              $map.R5[0] = Convert-Int32 ($map.CACHE + $map.R3)
              $map.R6[0] = Convert-Int32 (($map.R4[0] * [long]$map.MD52) - (0x3CE8EC25L * (Get-ShiftRight $map.R4[0] 16)))
              $map.R6[1] = Convert-Int32 ((0x59C3AF2DL * $map.R6[0]) - (0x2232E0F1L * (Get-ShiftRight $map.R6[0] 16)))
              $map.OUTHASH1 = Convert-Int32 ((0x1EC90001L * $map.R6[1]) + (0x35BD1EC9L * (Get-ShiftRight $map.R6[1] 16)))
              $map.OUTHASH2 = Convert-Int32 ([long]$map.R5[0] + [long]$map.OUTHASH1)
              $map.CACHE = ([long]$map.OUTHASH2)
              $map.COUNTER = $map.COUNTER - 1
            }
      
            [Byte[]] $outHash = @(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
            [byte[]] $buffer = [BitConverter]::GetBytes($map.OUTHASH1)
            $buffer.CopyTo($outHash, 0)
            $buffer = [BitConverter]::GetBytes($map.OUTHASH2)
            $buffer.CopyTo($outHash, 4)
          
            $map = @{PDATA = 0; CACHE = 0; COUNTER = 0 ; INDEX = 0; MD51 = 0; MD52 = 0; OUTHASH1 = 0; OUTHASH2 = 0;
              R0 = 0; R1 = @(0, 0); R2 = @(0, 0); R3 = 0; R4 = @(0, 0); R5 = @(0, 0); R6 = @(0, 0); R7 = @(0, 0)
            }
          
            $map.CACHE = 0
            $map.OUTHASH1 = 0
            $map.PDATA = 0
            $map.MD51 = ((Get-Long $bytesMD5) -bor 1)
            $map.MD52 = ((Get-Long $bytesMD5 4) -bor 1)
            $map.INDEX = Get-ShiftRight ($length - 2) 1
            $map.COUNTER = $map.INDEX + 1
      
            while ($map.COUNTER) {
              $map.R0 = Convert-Int32 ((Get-Long $bytesBaseInfo $map.PDATA) + ([long]$map.OUTHASH1))
              $map.PDATA = $map.PDATA + 8
              $map.R1[0] = Convert-Int32 ($map.R0 * [long]$map.MD51)
              $map.R1[1] = Convert-Int32 ((0xB1110000L * $map.R1[0]) - (0x30674EEFL * (Get-ShiftRight $map.R1[0] 16)))
              $map.R2[0] = Convert-Int32 ((0x5B9F0000L * $map.R1[1]) - (0x78F7A461L * (Get-ShiftRight $map.R1[1] 16)))
              $map.R2[1] = Convert-Int32 ((0x12CEB96DL * (Get-ShiftRight $map.R2[0] 16)) - (0x46930000L * $map.R2[0]))
              $map.R3 = Convert-Int32 ((0x1D830000L * $map.R2[1]) + (0x257E1D83L * (Get-ShiftRight $map.R2[1] 16)))
              $map.R4[0] = Convert-Int32 ([long]$map.MD52 * ([long]$map.R3 + (Get-Long $bytesBaseInfo ($map.PDATA - 4))))
              $map.R4[1] = Convert-Int32 ((0x16F50000L * $map.R4[0]) - (0x5D8BE90BL * (Get-ShiftRight $map.R4[0] 16)))
              $map.R5[0] = Convert-Int32 ((0x96FF0000L * $map.R4[1]) - (0x2C7C6901L * (Get-ShiftRight $map.R4[1] 16)))
              $map.R5[1] = Convert-Int32 ((0x2B890000L * $map.R5[0]) + (0x7C932B89L * (Get-ShiftRight $map.R5[0] 16)))
              $map.OUTHASH1 = Convert-Int32 ((0x9F690000L * $map.R5[1]) - (0x405B6097L * (Get-ShiftRight ($map.R5[1]) 16)))
              $map.OUTHASH2 = Convert-Int32 ([long]$map.OUTHASH1 + $map.CACHE + $map.R3) 
              $map.CACHE = ([long]$map.OUTHASH2)
              $map.COUNTER = $map.COUNTER - 1
            }
          
            $buffer = [BitConverter]::GetBytes($map.OUTHASH1)
            $buffer.CopyTo($outHash, 8)
            $buffer = [BitConverter]::GetBytes($map.OUTHASH2)
            $buffer.CopyTo($outHash, 12)
          
            [Byte[]] $outHashBase = @(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
            $hashValue1 = ((Get-Long $outHash 8) -bxor (Get-Long $outHash))
            $hashValue2 = ((Get-Long $outHash 12) -bxor (Get-Long $outHash 4))
          
            $buffer = [BitConverter]::GetBytes($hashValue1)
            $buffer.CopyTo($outHashBase, 0)
            $buffer = [BitConverter]::GetBytes($hashValue2)
            $buffer.CopyTo($outHashBase, 4)
            $base64Hash = [Convert]::ToBase64String($outHashBase) 
          }
      
          Write-Output $base64Hash
        }
      
        Write-Verbose "Getting Hash For $ProgId   $Extension"
      
        $userSid = Get-UserSid
        $userExperience = Get-UserExperience
        $userDateTime = Get-HexDateTime
        Write-Debug "UserDateTime: $userDateTime"
        Write-Debug "UserSid: $userSid"
        Write-Debug "UserExperience: $userExperience"
      
        $baseInfo = "$Extension$userSid$ProgId$userDateTime$userExperience".ToLower()
        Write-Verbose "baseInfo: $baseInfo"
      
        $progHash = Get-Hash $baseInfo
        Write-Verbose "Hash: $progHash"
        
        #Handle Extension Or Protocol
        if ($Extension.Contains(".")) {
          Write-Verbose "Write Registry Extension: $Extension"
          Write-ExtensionKeys $ProgId $Extension $progHash
      
        }
        else {
          Write-Verbose "Write Registry Protocol: $Extension"
          Write-ProtocolKeys $ProgId $Extension $progHash
        }
      
         
        if ($Icon) {
          Write-Verbose  "Set Icon: $Icon"
          Set-Icon $ProgId $Icon
        }
      
        Update-RegistryChanges 
      
      }
      
      function Set-PTA {
        [CmdletBinding()]
        param (
          [Parameter(Mandatory = $true)]
          [String]
          $ProgId,
      
          [Parameter(Mandatory = $true)]
          [String]
          $Protocol,
            
          [String]
          $Icon
        )
      
        Set-FTA -ProgId $ProgId -Protocol $Protocol -Icon $Icon
      }
      
      Set-PTA ChromeHTML http
      Set-PTA ChromeHTML https
      Set-FTA ChromeHTML .pdf
      Set-FTA ChromeHTML .htm
      Set-FTA ChromeHTML .html
      

      当您查看此 regkey 时,您可以找到 Chrome、Edge、Firefox 等的标识符: HKEY_CLASSES_ROOT\.html\OpenWithProgids

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-09
        • 1970-01-01
        • 2018-10-07
        • 1970-01-01
        相关资源
        最近更新 更多