win10下,cmd,power shell设置默认编码为‘UTF-8’?

想在cmd,power shell输出‘UTF-8’编码的字符串,结果出问题了。 虽然,chcp 65001 可以暂时的解决,但是又想一劳永逸,设置c…
关注者
117
被浏览
271,525

11 个回答

注:以下内容在非Windows平台上写的,可能会有拼写错误,如果有,请指正,我会尽快修正。

可以用Powershell的配置文件($PROFILE)来实现。

$PROFILE默认文件不存在,需要创建。

New-Item $PROFILE -ItemType File -Force

此时会在文档下产生一个ps1文件,该文件会在Powershell启动的时候加载。

在这个配置文件里加上一句:

[System.Console]::OutputEncoding=[System.Text.Encoding]::GetEncoding(65001)

当然,这里就涉及到了Powershell的执行策略(Execution Policy)的问题,你需要设置允许 Powershell执行脚本,我是用的Unrestricted 策略:

Set-ExecutionPolicy Unrestricted

=============下面的内容很无聊的===============

分享一下自己电脑上的$PROFILE吧

# User profile

# Set encoding
[System.Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding(936);

# Create frequent commands
New-Alias -Name vim -Value "D:\Program Files\Sublime Text\sublime_text.exe";
New-Alias -Name vscode -Value "D:\Program Files\VSCode\Code.exe";
$HOSTS = "$env:SystemRoot\system32\drivers\etc\hosts";
Set-Location D:\Scripts;

# Create administrative credential
$pwd = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String("base64_encoded_string"));
$secpwd = ConvertTo-SecureString -AsPlainText -String $pwd -Force;
$adm = New-Object System.Management.Automation.PSCredential("domain\username", $secpwd);

# Set a default password, for reseting account password
$defaultPassword = ConvertTo-SecureString -AsPlainText -String '1234@abcd' -Force;

# Personalize console
$Host.UI.RawUI.WindowTitle = "Windows Powershell " + $Host.Version;
Write-Host -ForegroundColor Green "`n`t`t`tWelcome to Windows Powershell!`n";

# Enable AD management
Import-Module ActiveDirectory | Out-Null;

# Enable Exchange management
$exchange = New-PSSession -URI http://exchangeserver.domain.com/powershell -ConfigurationName microsoft.exchange -Credential $adm
Import-PSSession $exchange -DisableNameChecking | Out-Null

# Enable Skype for Business management
$sfb = New-PSSession -ConnectionUri 'https://sfbserver.domain.com/ocspowershell' -Credential $adm
Import-PSSession $sfb -DisableNameChecking | Out-Null

# Define function to use Internet Explorer
function Use-InternetExplorer {
    param(
        # Parameter help description
        [Parameter(Mandatory=$true)]
        $Uri
    )

    $URL = "http://" + $Uri;

    Get-Process -Name iexplore -ErrorVariable verIE -ErrorAction SilentlyContinue | Out-Null
    if($verIE){
        Start-Process 'C:\Program Files\internet explorer\iexplore.exe'
    }

    Start-Sleep -Seconds 1;

    $navOpenInNewTab = 0x800
    $App = New-Object -ComObject shell.application
    $IE = $App.Windows() | Select-Object -Last 1
    $IE.navigate($URL, $navOpenInNewTab)
}

function Exit {
    Remove-PSSession $exchange
    Remove-PSSession $sfb
    Exit-PSSession
}

function Invoke-InternalWeb {
    param (
        # webname
        [Parameter(Mandatory=$true)]
        [string]$Name,

        # domain
        [Parameter(Mandatory=$false)]
        [ValidateSet("domain1.com","domain2.com","domain3.com")]
        [string]$Domain="domain1.com"
    )

    $URL = 'http://' + $Name + '.' + $Domain
    Start-Process $URL -ErrorAction SilentlyContinue;

}

Unix业界发明UTF-8之前,微软已经决定只支持UTF-16LE。这造成Windows控制台程序支持UTF-8非常困难。(即65001是一个残缺的代码页)

真想不出错,要么采用Win10引入的Windows Terminal,要么采用MinTTY等第三方终端模拟器。

还有一种方法是控制台程序都用Cygwin的API写,也就绕过了微软的UTF-8 bug。

补充:Win11有望修复控制台程序的UTF-8缺陷。