zoukankan      html  css  js  c++  java
  • PowerShell笔记

    本系列是一个重新学习PowerShell的笔记,内容引用自PowerShell中文博客

    处理函数的参数

    Powershell函数可以接受参数,并对参数进行处理。函数的参数有3个特性:

    1. 任意参数:内部变量(args 接受函数调用时接受的参数,)args是一个数组类型。
    2. 命名参数:函数的每一个参数可以分配一个名称,在调用时通过名称指定对应的参数。
    3. 预定义参数:函数在定义参数时可以指定默认值,如果调用时没有专门指定参数的值,就会保持默认值。

    万能参数$args

    (args 万能参数 给一个函数定义参数最简单的是使用)args这个内置的参数。
    它可以识别任意个参数。尤其适用哪些参数可有可无的函数。

    function sayHello
    {
        if($args.Count -eq 0)
        {
            "No argument!"
        }
        else
        {
            $args | foreach {"Hello,$($_)"}
        }
    }
    
    Write-Host -ForegroundColor "Red" "无参数调用"
    
    sayHello
    
    
    Write-Host -ForegroundColor "Red" "一个或多个参数调用"
    sayHello hua
    sayHello hua hua
    
    PS C:PowerShell>test.ps1                                                                                                                                                 无参数调用
    No argument!
    一个或多个参数调用
    Hello,hua
    Hello,hua
    Hello,hua
    

    指定参数名及默认值

    function Test($Str1 = "Hua",$str2 = "Hua") {
        $Str1 + $str2
    }
    Test
    Test -Str1 "h" -str2 "ua"
    
    PS C:PowerShell>test.ps1                                                                                                                                                 HuaHua
    hua
    

    指定参数类型

    
    function SetDate([DateTime]$Date,[int]$Days = 0,[string]$Description = "无") {   
        Write-Host -ForegroundColor "Green" $Date.Day
        $Date.AddDays($Days)
        Write-Host -ForegroundColor "Red" $Date.Day
        Write-Host -ForegroundColor "Red" $Description
    }
    
    SetDate '2020-01-01'
    SetDate '2020-11-01' -Days 6 -Description "HuaHua"
    #输入错误的日期
    SetDate '2020-15-01' -Days 6 -Description "HuaHua"
    
    PS C:PowerShell>test.ps1                                                                                                                                                 1
    
    2020年1月1日 0:00:00
    1
    无
    1
    2020年11月7日 0:00:00
    1
    HuaHua
    SetDate : Cannot process argument transformation on parameter 'Date'. Cannot convert value "2020-15-01" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."
    At test.ps1:11 char:9
    

    Switch 参数

    Powershell函数最简单的参数类型为布尔类型,除了使用Bool类型,也可以使用Switch关键字。
    下面的函数逆转字符串,但是可以通过(try 参数进行控制,如果没有指定)try的值,默认值为$false

    function  tryReverse( [switch]$try , [string]$source )
    {
        [string]$target=""
        if($try)
        {
            for( [int]$i = $source.length -1; $i -ge 0 ;$i--)
            {
                $target += $source[$i]
            }
            return $target
        }
        return $source
    }
    tryReverse -source www.mossfly.com
    tryReverse -try $true -source www.mossfly.com
    
    PS C:PowerShell> test.ps1                                                                                                                                                 www.mossfly.com
    moc.ylfssom.www
    

    指定函数的返回值

    一个或多个返回值

    Powershell不像它编程语言,它的函数可以有多个返回值。如果你直接调用函数,返回值会在控制台输出。当然你也可以将结果存储在一个变量中进一步处理。
    下面的例子演示返回一个值:

    function GetDate() {   
     return Get-Date
    }
    GetDate
    $d = GetDate
    $d.GetType().FullName
    
    PS C:PowerShell> test.ps1                                                                                                                                                 
    2021年9月14日 15:27:28
    System.DateTime
    
    

    下面的例子演示返回多个值

    function GetDate() {   
        $v = Get-Date
        $v.Year
        $v.Month
        $v.Day
    }
    GetDate
    $d = GetDate
    $d.GetType().FullName
    $d.Count
    $d[0]
    
    PS C:PowerShell> test.ps1                                                                                                                                                 2021
    9
    14
    System.Object[]
    3
    2021
    
    

    总结一下,如果一个函数返回一个值,像其它编程语言一样,这个值包括她的类型信息会直接返回。但是如果遇到多个返回值,Powershell会将所有的返回值自动构造成一个Object数组。可以通过索引访问数组。

    Return语句

    Powershell会将函数中所有的输出作为返回值,但是也可以通过return语句指定具体的我返回值。
    Return 语句会将指定的值返回,同时也会中断函数的执行,return后面的语句会被忽略。

    function GetDate() {   
        $v = Get-Date
        $v.Year
      return  $v.Month
        $v.Day
    }
    GetDate
    $d = GetDate
    $d.GetType().FullName
    $d.Count
    
    #return 语句之后的Day没有返回被截断
    PS C:PowerShell> test.ps1                                                                                                                                                 2021
    9
    System.Object[]
    

    访问返回值

    一个函数返回了一个值还是多个值,是可以验证的。下面的例子会产生随机数,如果没有指定个数,默认会返回一个随机数,否则会返回指定个数的随机数。
    
    Function lottery([int]$number=1)
    {
    $rand = New-Object system.random
    For ($i=1; $i -le $number; $i++) {
    $rand.next(1,50)
    }
    }
    # 参数为空时,返回值不是数组:
    $result = lottery
    $result -is [array]
    # False
    # 如果指定多个随机数是,返回值是数组类型:
    $result = lottery 10
    $result -is [array]
    
    PS C:PowerShell> test.ps1                                                                                                                                                 False
    True
    

    从函数的返回值中消除输出

    函数默认会将函数中的所有输出作为函数的返回值返回,这样很方便。但有时可能会将不必要的输出误以为返回值。写脚本程序时,可能需要自定义一些函数,这个函数可能只需要一个返回值,但是为了提高函数的可读性,可能会在函数增加一些注释输出行。

    Function Test()
    {
        "Try to calculate."
        "3.1415926"
        "Done."
    }
     
    #保存在变量中输出,
    $value=Test
    $value
    # Try to calculate.
    # 3.1415926
    # Done.
     
    #如果要过滤注释,只输出,不作为返回值,
    #可以使用Write-Host命令
    Function Test()
    {
        Write-Host "Try to calculate."
        "3.1415926"
        Write-Host "Done."
    }
    # 在变量值中保存返回值,在控制台输出注释行
    $value=Test
    # Try to calculate.
    # Done.
     
    # 测试返回值
    $value
    # 3.1415926
    

    使用调试信息报告

    可能输出这些函数中临时提示信息,给函数的返回值造成干扰。要解决这个问题,除了上述的Write-Host,也可以使用Write-Debug命令。

    Function Test()
    {
        Write-Debug "Try to calculate."
        "3.1415926"
        Write-Debug "Done."
    }
    # Debug调试信息只会在调试模式下被输出
    $value=Test
    # 3.1415926
     
    #如果你想通过显示调试信息调试函数,可以开启调试模式
    $DebugPreference="Continue"
    $value=Test
    # 调试: Try to calculate.
    # 调试: Done.
     
    # 测试返回值
    $value
    # 3.1415926
     
    #如果关闭调试模式,这些调试信息自然不会输出
    $DebugPreference="SilentlyContinue"
    $value=Test
    

    使用Write-Debug有两个优势,首先调试信息会自动高亮显示,便于分析。其次,这些调试信息只会在调试模式开启时输出,控制起来更加方便。当然最重要的是这些临时信息无论什么时候也不会混淆在返回值。

    抑制错误信息

    函数中的错误信息,也有可能作为返回值的一部分,因为默认这些错误信息会直接输出。

    Function ErrorTest()
    {
        #该进程不存在
        Stop-Process -Name "www.mossfly.com"
    }
    ErrorTest
     
    Stop-Process : 找不到名为“www.mossfly.com”的进程。请验证该进程名称,然后再次调用 cmdlet。
    所在位置 C:UsersbaozhenDesktoptest.ps1:6 字符: 17
    +     Stop-Process <<<<  -Name "www.mossfly.com"
        + CategoryInfo          : ObjectNotFound: (www.mossfly.com:String) [Stop-P
       rocess], ProcessCommandException
        + FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.
       Commands.StopProcessCommand
     
     很明显,类似这样的错误提示信息,对调试程序很重要,但如果你觉得它不重要,特意要隐藏,可以使用$ErrorActionPreference进行设置。
     
     Function ErrorTest()
    {
        #从这里开始隐藏所有的错误信息
        $ErrorActionPreference="SilentlyContinue"
        Stop-Process -Name "www.mossfly.com"
        #该进程不存在
    }
     
    #错误信息不会输出
    ErrorTest
    

    但是上面的做法并不明智,因为这样可能错过其它错误提示。所以最好的方式是处理完后,对$ErrorActionPreference进行复位。

    Function ErrorTest()
    {
        #从这里开始隐藏所有的错误信息
        $ErrorActionPreference="SilentlyContinue"
        Stop-Process -Name "www.mossfly.com"
        #该进程不存在
     
        #恢复$ErrorActionPreference,错误开始输出
        $ErrorActionPreference="Continue"
     
        2/0
    }
    ErrorTest
    试图除以零。
     
    所在位置 行:9 字符: 7
    + 2/ <<<< 0
    + CategoryInfo          : NotSpecified: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : RuntimeException
    

    查看支持的函数

    Powershell已经提供了许多用户能够使用的预定义函数,这些函数可以通过Function:PSDrive虚拟驱动器查看。

    PS C:PowerShell> Get-ChildItem function: | Format-Table Name,Definition                                                                                                                     
    Name                      Definition
    ----                      ----------
    A:                        Set-Location $MyInvocation.MyCommand.Name
    B:                        Set-Location $MyInvocation.MyCommand.Name
    C:                        Set-Location $MyInvocation.MyCommand.Name
    cd..                      Set-Location ..
    cd                       Set-Location 
    Clear-Host                ...
    ConvertFrom-SddlString    ...
    D:                        Set-Location $MyInvocation.MyCommand.Name
    E:                        Set-Location $MyInvocation.MyCommand.Name
    F:                        Set-Location $MyInvocation.MyCommand.Name
    Format-Hex                ...
    G:                        Set-Location $MyInvocation.MyCommand.Name
    Get-FileHash              ...
    Get-Verb                  ...
    H:                        Set-Location $MyInvocation.MyCommand.Name
    help                      ...
    I:                        Set-Location $MyInvocation.MyCommand.Name
    Import-PowerShellDataFile ...
    ImportSystemModules
    J:                        Set-Location $MyInvocation.MyCommand.Name
    K:                        Set-Location $MyInvocation.MyCommand.Name
    L:                        Set-Location $MyInvocation.MyCommand.Name
    M:                        Set-Location $MyInvocation.MyCommand.Name
    mkdir                     ...
    more                      ...
    N:                        Set-Location $MyInvocation.MyCommand.Name
    New-Guid                  ...
    New-TemporaryFile         ...
    O:                        Set-Location $MyInvocation.MyCommand.Name
    oss                       ...
    P:                        Set-Location $MyInvocation.MyCommand.Name
    Pause                     $null = Read-Host 'Press Enter to continue...'
    prompt                    ...
    PSConsoleHostReadLine     ...
    Q:                        Set-Location $MyInvocation.MyCommand.Name
    R:                        Set-Location $MyInvocation.MyCommand.Name
    S:                        Set-Location $MyInvocation.MyCommand.Name
    T:                        Set-Location $MyInvocation.MyCommand.Name
    TabExpansion2             ...
    U:                        Set-Location $MyInvocation.MyCommand.Name
    V:                        Set-Location $MyInvocation.MyCommand.Name
    W:                        Set-Location $MyInvocation.MyCommand.Name
    X:                        Set-Location $MyInvocation.MyCommand.Name
    Y:                        Set-Location $MyInvocation.MyCommand.Name
    Z:                        Set-Location $MyInvocation.MyCommand.Name
    

    从这些结果不但能够看出函数的名称,还能通过Definition列查看函数的内容。如果你想深入查看函数的内部定义可以直接访问Function:

    PS C:PowerShell> $function:prompt                                                                                                                                                           
    "PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) ";
    # .Link
    # https://go.microsoft.com/fwlink/?LinkID=225750
    # .ExternalHelp System.Management.Automation.dll-help.xml
    
    

    Powershell中的这些预定义的函数可以做很多重要的工作。

    Clear-Host 清除屏幕的缓存
    help,man 查看命令的帮助文档
    mkdir,md 通过new-Item创建子目录
    more 分屏输出管道结果
    prompt 返回提示文本
    TabExpansion Tab键的自动完成提示
    X: 调用Set-Location定位到指定的驱动器根目录
    如果你想查看当前Powershell环境中定义了多少个函数可以通过:

    PS C:PowerShell> (Dir function:).Count                                                                                                                                                      45
    

    自定义Prompt

    每次成功执行完一条命令,Powershell就会执行Prompt函数,提示用户进行下一步输入。
    默认设置中,prompt显示“PS” 和当前的工作目录。
    再接着是”>”或”>>”,具体情况要看当前Powershell控制台的的层数。
    当然你可以自定义prompt的,那就得覆盖prompt函数:

    PS C:PowerShell> pwd                                                                                                                                                                        
    Path
    ----
    C:PowerShell
    
    
    PS C:PowerShell> Function prompt{"Hua Hua"}                                                                                                                                                 Hua Hua                                                                                                                                                                                      Hua Huapwd                                                                                                                                                                                   
    Path
    ----
    C:PowerShell
    
    
    Hua Hua 
    

    这样的覆盖安全吗,显然安全,对预定义函数的重写,只会在当前控制台会话中有效,当你重新启动控制台时,自然会恢复如初。

    在控制台的任何位置输出文本(自定义光标的位置)
    因为控制台的内容存放在控制台屏幕的缓存中,因此你可以逐个访问内容的每一行或每一个字符。
    你甚至可以在控制台的屏幕的任何位置输出你想要输出的信息,接下来的函数会演示这个功能。
    要完成这个功能,需要使用$Host.UI.Rawui ,光标的位置通过屏幕的横坐标(X)和纵坐标(Y)确定,下面的函数会首先记住当前光标的位置,然后在横坐标上增加60个占位符,然后重置光标的位置至当前位置,最后通过prompt函数回复光标的原始位置。

    Hua H> function prompt
    >> {
    >>     $curPos = $host.ui.rawui.CursorPosition
    >>     $newPos = $curPos
    >>     $newPos.X+=60
    >>     $host.ui.rawui.CursorPosition = $newPos
    >>     Write-Host ("{0:D} {0:T}" -f (Get-Date)) -foregroundcolor Yellow
    >>     $host.ui.rawui.CursorPosition = $curPos
    >>     Write-Host ("PS " + $(get-location) +">") -nonewline -foregroundcolor Green
    >> " "
    >> }                                                                                                                                                                                         PS C:PowerShell>                                           2021年9月14日 16:57:04
    

    使用窗口标题栏

    在Windows控制台的标题栏有一部分空间,可以放置一些有用的信息,比如当前哪个用户登录在控制台,可以通过设置$host.UI.RawUI.WindowTitle来自定义控制台标题栏的文本。
    下面的例子就会演示设置标题栏文本,通过.NET方法获取当前用户信息,由于该方法会有几秒钟执行时间,为了效率考虑首先将用户信息保存在全局变量中,然后在Prompt函数中调用。

    $global:CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent()
    function prompt
    {
    $host.ui.rawui.WindowTitle = "Line: " + $host.UI.RawUI.CursorPosition.Y + " " + $CurrentUser.Name + " " + $Host.Name + " " + $Host.Version
    Write-Host ("PS " + $(get-location) +">")  -nonewline -foregroundcolor Green
    return " "
    }
    

    执行以后在标题栏会显示:Line: 72 ComputerNameuser ConsoleHost 2.0
    如果你使用管理员权限运行控制台时,Prompt函数还可以给出警告。使用WindowsPrincipal 辨别当前用户是否使用了管理员权限,你不需要了解下面的.NET代码,它会在全局变量中将布尔值赋值给$Admin。

    $CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent()
    $principal = new-object System.Security.principal.windowsprincipal($CurrentUser)
    $global:Admin = $principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::Administrator)
    Function prompt
    {
        # 输出标准的提示信息:
        Write-Host ("PS " + $(get-location)) -nonewline
        # The rest depends on whether you have admin rights or not:
        If ($admin)
        {
            $oldtitle = $host.ui.rawui.WindowTitle
            # 将"Administrator: " 显示在标题栏
            If (!$oldtitle.StartsWith("Administrator: "))
            {
                $host.ui.rawui.WindowTitle ="Administrator: " + $oldtitle
            }
            #  Prompt结尾显示红色的尖括号
            Write-Host ">" -nonewline -foregroundcolor Red
         }
         Else
         {
            Write-Host ">" -nonewline
          }
         return " "
    }
    

    没有管理员权限时,标题栏文本:Windows Powershell
    有管理员权限时,标题栏文本:Administrator :管理员 : Windows Powershell

    Clear-Host:删除屏幕缓存

    很可能,你已经注意到了,cls可以删除屏幕的缓存。
    事实上,cls只是Clear-Host函数的别名,但是却看不到这个函数的内容。

    PS C:PowerShell> $function:Clear-Host
    At line:1 char:16
    + $function:Clear-Host
    +                ~~~~~
    Unexpected token '-Host' in expression or statement.
        + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
        + FullyQualifiedErrorId : UnexpectedToken
    

    在Powershell中短斜杠是个特殊字符,如果一个函数名中包含了特殊字符就应当把它放在花括号中。

    PS C:PowerShell> ${function:Clear-Host}                    
    
    $RawUI = $Host.UI.RawUI
    $RawUI.CursorPosition = @{X=0;Y=0}
    $RawUI.SetBufferContents(
        @{Top = -1; Bottom = -1; Right = -1; Left = -1},
        @{Character = ' '; ForegroundColor = $rawui.ForegroundColor; BackgroundColor = $rawui.BackgroundColor})
    # .Link
    # https://go.microsoft.com/fwlink/?LinkID=225747
    # .ExternalHelp System.Management.Automation.dll-help.xml
    

    盘符名预定义函数C:,D:,E:

    这些盘符名称可以作为单独的一个函数,是怎么做到的呢?

    PS C:PowerShell> $function:C:                              
    Set-Location $MyInvocation.MyCommand.Name
    

    函数过滤器、管道

    一个函数能够访问和进一步处理另外一条命令的结果吗?答案是肯定的,这被称为管道。管道有两种模式,一种是顺序处理模式,一种是流处理模式。

    低效率的顺序模式:$input

    在最简单的情况下,你的函数不是真正支持管道。只能对前一个命令执行后的结果处理。前一个命令执行的结果通过被自动保存在$input变量中,$input是一个数组,它可以包含许多元素,一个元素,甚至一个元素都没有,这取决于具体的环境。

    下面的例子,是一个函数,仅仅输出$input的内容。

    PS C:PowerShell> function OutPut {
    >>    $input
    >> }                                                                                                                    PS C:PowerShell> 1,2,3 | OutPut                                                                                        1
    2
    3
    
    PS C:PowerShell> "222",1 | OutPut                                                                                      222
    1
    PS C:PowerShell> dir | OutPut                                                                                          
    
        Directory: C:PowerShell
    
    
    Mode                LastWriteTime         Length Name
    ----                -------------         ------ ----
    -a----        2021/9/14     13:51             58 test.txt
    

    到目前为止,这个函数只是仅仅输出了管道的结果,并没有其它比较强大的功能。
    在接下来的例子中,函数将会对管道的结果做进一步处理。函数名MarkEXE,将会检查Dir的结果,并高亮标记后缀名为EXE的文件名为红色。

    Function MarkEXE {
        # 保存控制台当前的前景色
        $oldcolor = $host.ui.rawui.ForegroundColor
        # 通过循环逐条检查管道的结果
        Foreach ($element in $input) {
            # 如果后缀名为.exe,设置为前景色为红色
            If ($element.name.toLower().endsWith(".exe")) {
                $host.ui.Rawui.ForegroundColor = "red"
            }
            Else {
                # 否则恢复默认的前景色
                $host.ui.Rawui.ForegroundColor = $oldcolor
            }
            # 输出数组元素
            $element
        }
        # 最后,重置控制台的前景色:
        $host.ui.Rawui.ForegroundColor = $oldcolor
    }
    
    Dir | MarkEXE
    
    PS C:PowerShell> New-Item test.exe                                                                                     
    
        Directory: C:PowerShell
    
    
    Mode                LastWriteTime         Length Name
    ----                -------------         ------ ----
    -a----        2021/9/15     10:46              0 test.exe
    
    
    PS C:PowerShell> ls                                                                                                    
    
        Directory: C:PowerShell
    
    
    Mode                LastWriteTime         Length Name
    ----                -------------         ------ ----
    -a----        2021/9/15     10:46              0 test.exe
    -a----        2021/9/14     13:51             58 test.txt
    
     PS C:PowerShell> test.ps1                                                                            
    
        Directory: C:PowerShell
    
    
    Mode                LastWriteTime         Length Name
    ----                -------------         ------ ----
    -a----        2021/9/15     10:46              0 test.exe
    -a----        2021/9/14     13:51             58 test.txt
    

    过滤器:高效率 流模式

    管道的低效率顺序模式在处理大容量数据时很容易出现问题,其结果是巨大的内存占用和进程等待。
    如果你的函数支持高效率的流模式,在处理管道结果时仅占用很小的内存。
    事实上,针对之前MarkEXE函数,你只需要替换”function” 关键字 为 “filter”它就会开始流模式处理,这样你再也不用过分的担心忍受程序的无休止的响应和崩溃的危险。
    你也可以递归处理全盘目录,甚至处理极其庞大的数据。例如:

    PS C:PowerShell> Dir C:PowerShell -recurse | MarkEXE
    

    当MarkEXE每次被调用时,它只会对当前目录下的每个单独的元素进行处理。
    对于过滤器filters来说,$input 一直都是一个独立的元素。
    这也就是为什么在过滤器中$input一点用也没有的道理。
    此时,最好使用$_ 变量,因为它代表了当前处理的数据。
    这样还可以简化MarkExe,因为过滤器自身已经扮演了循环的角色了,你没有必要再写专门的循环处理了。

    Filter MarkEXE
    {
        # 记录当前控制台的背景色
        $oldcolor = $host.ui.rawui.ForegroundColor
        # 当前的管道元素保存在 $_ 变量中
        # 如果后缀名为 ".exe",
        # 改变背景色为红色:
        If ($_.name.toLower().endsWith(".exe"))
        {
            $host.ui.Rawui.ForegroundColor = "red"
        }
        Else
        {
            # 否则使用之前的背景色
            $host.ui.Rawui.ForegroundColor = $oldcolor
        }
        # 输出当前元素
        $_
        # 最后恢复控制台颜色:
        $host.ui.Rawui.ForegroundColor = $oldcolor
    }
    
    Dir | MarkEXE
    
    PS C:PowerShell> test.ps1                                                                            
    
        Directory: C:PowerShell
    
    
    Mode                LastWriteTime         Length Name
    ----                -------------         ------ ----
    -a----        2021/9/15     10:46              0 test.exe
    -a----        2021/9/14     13:51             58 test.txt
    

    开发真正的管道函数

    过滤器在函数中属于高级应用,因为它可以立即处理管道结果的每一个元素。但是过滤器必须每次重复执行预定义命令的结果。
    对于MarkEXE 函数,每次执行的过程中要记录和更新控制台的背景颜色,也要花费资源和时间。
    事实上,过滤器只是特殊的函数。如果一个函数内部使用了管道,你就可以定义三个基础的任务区了:第一步,完成函数的初始化,完成函数执行的预备步骤;第二步处理递归调用所得的结果;最后进行收尾工作。
    这三个任务区分别可以使用begin,process,end 语句块。

    function MarkEXE {  
        
        begin {
            # 记录当前控制台的背景色
            $oldcolor = $host.ui.rawui.ForegroundColor
            
        }
        
        process {
            # 当前的管道元素保存在 $_ 变量中
            # 如果后缀名为 ".exe",
            # 改变背景色为红色:
            If ($_.name.toLower().endsWith(".exe")) {
                $host.ui.Rawui.ForegroundColor = "red"
            }
            Else {
                # 否则使用之前的背景色
                $host.ui.Rawui.ForegroundColor = $oldcolor
            }
            # 输出当前元素
            $_
        }
        
        end {
            # 最后恢复控制台颜色:
            $host.ui.Rawui.ForegroundColor = $oldcolor
        }
    }
    
    
    Dir | MarkEXE
    
    PS C:PowerShell> test.ps1                                                                            
    
        Directory: C:PowerShell
    
    
    Mode                LastWriteTime         Length Name
    ----                -------------         ------ ----
    -a----        2021/9/15     10:46              0 test.exe
    -a----        2021/9/14     13:51             58 test.txt
    
  • 相关阅读:
    bzoj3530 [SDOI2014]数数
    bzoj3940 Censoring
    线性代数基础
    hdu1085 Holding Bin-Laden Captive!
    hdu1028 Ignatius and the Princess III
    luogu2000 拯救世界
    博弈论入门
    树hash
    luogu2173 [ZJOI2012]网络
    luogu1501 [国家集训队]Tree II
  • 原文地址:https://www.cnblogs.com/MerLin-LiuNian/p/15271780.html
Copyright © 2011-2022 走看看