我在 Windows 使用的脚本,从 cmd 到 WSL 1 到 WSL 2,最后又回到了 PowerShell。Shell 在 Linux/Mac OS 上确实好用,但如果要用 IDE 开发,WSL 1 的开发环境不受 JetBrains 支持了,而从 JetBrains 的 Windows 版本访问 WSL 2 会巨慢。所以还是回归到 PowerShell 吧。而且,PowerShell 正如其名,其语法会比 Shell 强大。

PowerShell 的独特之处在于,它接受并返回 .NET 对象而非文本。 这个特点让它可以更轻松地在一个管道中串联不同的命令。

相信学完 PowerShell,对 .Net 体系也会更加熟悉,说不定就去学 C# 了(逃

# 执行策略

不管会不会 PowerShell,只要你在 Windows 10 上运行 ps1 脚本,你都得接触这块。

tldr:在管理员权限的 Powershell 7 下执行:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned

关于执行策略 - PowerShell | Microsoft Docs (opens new window)

最严格最不严格依次为:

  • Restricted:所有脚本都不能运行
  • AllSigned:所有脚本都需要签名才能运行(Windows 10 默认)
  • RemoteSigned:本地脚本可以直接运行,从 Internet 下载的脚本需要签名才能运行(Windows Server 默认)
  • Unrestricted:所有脚本都能运行。但从 Internet 下载的未签名脚本运行前会有警告
  • Bypass:所有脚本都能运行,且没有警告

另外还有两个特殊的:

  • Default,即在 Windows 10 上为 Restricted,Windows Server 上为 RemoteSigned
  • Undefined,当前作用域未设置执行策略,遵循低一级作用域的策略。如果所有执行策略都是 Undefined,则按 Default 执行。

执行域从最高到最低如下所示(MachinePolicy 最高,LocalMachine 最低):

PS C:\Tools\git\blog> Get-ExecutionPolicy -List    

        Scope ExecutionPolicy
        ----- ---------------
MachinePolicy       Undefined
   UserPolicy       Undefined
      Process       Undefined
  CurrentUser       Undefined
 LocalMachine    Unrestricted

默认设置的是最低一级的 LocalMachine,需要管理员权限才能修改。

# 教程

# Get-Help Get-Commmand

这两个命令是初学时最重要的命令。

Get-Command # 查找命令
Get-Help    # 查找命令的帮助

# Get-Help

PS C:\Users\liu> Get-help Get-Help

NAME
    Get-Help

SYNTAX
    Get-Help [[-Name] <string>] [-Path <string>] [-Category {Alias | Cmdlet | Provider | General | FAQ | Glossary | HelpFile | ScriptCommand | Function | Filter | ExternalScript | All | DefaultHelp | DscResource | Class | Configuration}] [-Full] [-Component <string[]>] [-
    Functionality <string[]>] [-Role <string[]>] [<CommonParameters>]

    Get-Help [[-Name] <string>] -Detailed [-Path <string>] [-Category {Alias | Cmdlet | Provider | General | FAQ | Glossary | HelpFile | ScriptCommand | Function | Filter | ExternalScript | All | DefaultHelp | DscResource | Class | Configuration}] [-Component <string[]>]
    [-Functionality <string[]>] [-Role <string[]>] [<CommonParameters>]

    Get-Help [[-Name] <string>] -Examples [-Path <string>] [-Category {Alias | Cmdlet | Provider | General | FAQ | Glossary | HelpFile | ScriptCommand | Function | Filter | ExternalScript | All | DefaultHelp | DscResource | Class | Configuration}] [-Component <string[]>] [-Functionality <string[]>] [-Role <string[]>] [<CommonParameters>]

    Get-Help [[-Name] <string>] -Parameter <string[]> [-Path <string>] [-Category {Alias | Cmdlet | Provider | General | FAQ | Glossary |HelpFile | ScriptCommand | Function | Filter | ExternalScript | All | DefaultHelp | DscResource | Class | Configuration}] [-Component<string[]>] [-Functionality <string[]>] [-Role <string[]>] [<CommonParameters>]

    Get-Help [[-Name] <string>] -Online [-Path <string>] [-Category {Alias | Cmdlet | Provider | General | FAQ | Glossary | HelpFile | ScriptCommand | Function | Filter | ExternalScript | All | DefaultHelp | DscResource | Class | Configuration}] [-Component <string[]>] [-Functionality <string[]>] [-Role <string[]>] [<CommonParameters>]

    Get-Help [[-Name] <string>] -ShowWindow [-Path <string>] [-Category {Alias | Cmdlet | Provider | General | FAQ | Glossary | HelpFile | ScriptCommand | Function | Filter | ExternalScript | All | DefaultHelp | DscResource | Class | Configuration}] [-Component <string[]>] [-Functionality <string[]>] [-Role <string[]>] [<CommonParameters>]


ALIASES
    None


REMARKS
    Get-Help cannot find the Help files for this cmdlet on this computer. It is displaying only partial help.
        -- To download and install Help files for the module that includes this cmdlet, use Update-Help.
        -- To view the Help topic for this cmdlet online, type: "Get-Help Get-Help -Online" or
           go to https://go.microsoft.com/fwlink/?LinkID=2096483.

看起来真是让人头大。其实 Get-Help 只需要关注 6 个互斥的参数(其实这 6 个也不需要完全关注):

Get-Help Get-Help -Full
Get-Help Get-Help -Detailed
Get-Help Get-Help -Examples
Get-Help Get-Help -Online
Get-Help Get-Help -Parameter <string[]>
Get-Help Get-Help -ShowWindow

读者可以试一试每个命令是什么效果。

一般用 -ShowWindow 或者 -Online 就可以了。简写就直接 help -s Get-Helphelp 函数不是 Get-Help 命令,可以理解为 help 这个函数执行了 Get-Help | more)。

# Get-Command

这个命令可以用来确定命令。

PS C:\Users\liu> Get-Command Get-Process

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Cmdlet          Get-Process                                        7.0.0.0    Microsoft.PowerShell.Management

当然用 help 也不错。当 help 有多条结果时,它会列出所有命令;当 help 只有一条结果时,它会执行 Get-Help | more

PS C:\Users\liu> help process

Name                              Category  Module                    Synopsis
----                              --------  ------                    --------
Enter-PSHostProcess               Cmdlet    Microsoft.PowerShell.Core …
Exit-PSHostProcess                Cmdlet    Microsoft.PowerShell.Core …
Get-PSHostProcessInfo             Cmdlet    Microsoft.PowerShell.Core …
Debug-Process                     Cmdlet    Microsoft.PowerShell.Man… Debugs one or more processes running on the local computer.
Get-Process                       Cmdlet    Microsoft.PowerShell.Man… Gets the processes that are running on the local computer.
Start-Process                     Cmdlet    Microsoft.PowerShell.Man… Starts one or more processes on the local computer.
Stop-Process                      Cmdlet    Microsoft.PowerShell.Man… Stops one or more running processes.
Wait-Process                      Cmdlet    Microsoft.PowerShell.Man… Waits for the processes to be stopped before accepting more input.
Get-AppvVirtualProcess            Function  AppvClient                …
Start-AppvVirtualProcess          Function  AppvClient                …
Stop-ComputeProcess               Cmdlet    HostComputeService        Stop-ComputeProcessGet-ComputeProcess                Cmdlet    HostComputeService        Get-ComputeProcessGet-VMProcessor                   Cmdlet    Hyper-V                   Get-VMProcessorSet-VMProcessor                   Cmdlet    Hyper-V                   Set-VMProcessorConvertTo-ProcessMitigationPolicy Cmdlet    ProcessMitigations        ConvertTo-ProcessMitigationPolicyGet-ProcessMitigation             Cmdlet    ProcessMitigations        Get-ProcessMitigationSet-ProcessMitigation             Cmdlet    ProcessMitigations        Set-ProcessMitigation

# 关于...

如果你觉得命令的帮助文档太枯燥,可以看看概念性帮助文章。

PowerShell 中的概念性帮助文章以 about_ 开头,例如 about_Comparison_Operators。要查看所有about_ 文章,请键入Get-Help about_*。要查看特定文章,请键入Get-Help about_<article-name>,例如 Get-Help about_Comparison_Operators

Get-Help about_* 好像不是很好用,其实可以直接搜索“关于”:搜索 | Microsoft Docs (opens new window)

或者查看以下链接:

# select 和 where

有 SQL 那味了

Get-Process | Select-Object Name -Unique
Get-Command | Select-Object -First 3
Get-Command | Select-Object -Last 3
Get-Process | Where-Object {$_.ProcessName -Like "p*"}

更有意思的是,Select-ObjectWhere-Object 的别名是 selectwhere!太对了太对了,哥。

# Get-Member

可以查询一个对象的结果(属性、方法)等。

Get-Process | Get-Member
# Get-Member 返回的也是一个对象
Get-Process | Get-Member | Get-Member

# Get-Alias

查询一个命令的 Alias,在命令行敲的时候就会短很多,不过写脚本或者写教程的话建议还是使用全名。

Get-Alias -Definition Get-Member

# 启动时执行的 Profile

Powershell 也支持诸如 .bashrc .profile 的启动时执行的 powershell 脚本。

PS C:\Users\liu> $PROFILE
C:\Users\liu\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

PS C:\Users\liu> $PROFILE.AllUsersAllHosts
C:\Program Files\PowerShell\7\profile.ps1

PS C:\Users\liu> $PROFILE.AllUsersCurrentHost
C:\Program Files\PowerShell\7\Microsoft.PowerShell_profile.ps1

PS C:\Users\liu> $PROFILE.CurrentUserAllHosts
C:\Users\liu\Documents\PowerShell\profile.ps1

一共有四个变量。建议改 $PROFILE.AllUsersAllHosts

# 数组

关于数组 - PowerShell | Microsoft Docs (opens new window)

# 自然换行

PowerShell 中允许在以下字符后面自然换行:

  • 管道符号 |
  • 逗号 ,
  • 三种左括号 ( [ {
  • (不常用)分号 ;
  • (不常用)等号 =
  • (不常用)单、双引号 ' "
Get-Service |
    Where-Object CanPauseAndContinue -eq $true |
        Select-Object -Property *

如果命令太长、实在想换行,可以使用反引号 `

Get-Help `
    -Full `
    Get-Member