PowerShell 技能连载 - 通过F12键跳转到函数定义

如果您将要编写又长又复杂,有很多函数的PowerShell代码,那么这篇文章对您有所帮助。在其它开发环境中,当您将光标停在一个函数上,并按下F12键,编辑器将跳转到函数的定义处。而PowerShell ISE并不会那么做。

然而,您可以为ISE增加这个功能。以下代码将在 AddOns 菜单处增加一个新的 Find Definition 命令,并且为其绑定键盘的 F12 热键。

下一次您在一大段脚本中点击某个函数,ISE将直接导航到该函数的定义处(当函数在脚本内定义时)。

function Find-Definition {
    $e = $psISE.CurrentFile.Editor
    $Column = $e.CaretColumn
    $Line = $e.CaretLine

    $AST = [Management.Automation.Language.Parser]::ParseInput($e.Text,[ref]$null,[ref]$null)
    $AST.Find({param($ast)
            ($ast -is [System.Management.Automation.Language.CommandAst]) -and
            (($ast.Extent.StartLineNumber -lt $Line -and $ast.Extent.EndLineNumber -gt $line) -or
            ($ast.Extent.StartLineNumber -eq $Line -and $ast.Extent.StartColumnNumber -le $Column) -or
            ($ast.Extent.EndLineNumber -eq $Line -and $ast.Extent.EndColumnNumber -ge $Column))}, $true) |
            Select-Object -ExpandProperty CommandElements |
            ForEach-Object {
                $name = $_.Value
                $AST.Find({param($ast)
                        ($ast -is [System.Management.Automation.Language.FunctionDefinitionAst]) -and
                        ($ast.Name -eq $name)}, $true) |
                        Select-Object -Last 1 |
                        ForEach-Object {
                            $e.SetCaretPosition($_.Extent.StartLineNumber,$_.Extent.StartColumnNumber)
                    }
            }
}

$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Goto Definition",{Find-Definition},'F12')
评论

PowerShell 技能连载 - 增加新的类型加速器

如果您发现您常常使用某些.NET类型,您可能会希望创建一些快捷方式,使您的生活变得更简单。

例如,System.IO.Path .NET类型有许多常用的路径功能:

[System.IO.Path]::GetExtension('c:\test.txt')
[System.IO.Path]::ChangeExtension('c:\test.txt', 'bak')

如果您觉得每次为了这个.NET类型敲入长长的代码太辛苦,只需要用这种方式增加一个快捷方式:

[PSObject].Assembly.GetType("System.Management.Automation.TypeAccelerators")::Add('Path', [System.IO.Path])

现在,您可以通过 Path 快捷方式获得完全一样的功能:

[Path]::GetExtension('c:\test.txt')
[Path]::ChangeExtension('c:\test.txt', 'bak')

要查看一个类型所支持的所有方法和属性,用以下的代码:

[Path] | Get-Member -Static
评论

PowerShell 技能连载 - 查找类型加速器

PowerShell维护着一系列.NET类型的缩写,使您编写代码更加自如。例如要将一个字符串转换成DateTime类型,您可以这样写:

[DateTime] '2013-07-02'

它的幕后机制只是一个名为 System.DateTime 类型的缩写。您可以通过 FullName 属性查看这些缩写实际上代表的类型:

[DateTime].FullName

若要获取所有支持的“类型加速器”(缩写),您可以使用以下代码。这段代码返回PowerShell实现的所有加速器。这段代码十分有用,因为它列出了PowerShell开发者认为十分重要的所有.NET内部类型。

[PSObject].Assembly.GetType("System.Management.Automation.TypeAccelerators")::Get |
    Sort-Object -Property Value

当您将结果通过管道输出到一个grid view窗口时,您可以方便地搜索类型加速器。只需要在grid view窗口顶部的搜索框内键入类型名的一部分即可:

[PSObject].Assembly.GetType("System.Management.Automation.TypeAccelerators")::Get |
    Sort-Object -Property Value |
    Out-GridView
评论

PowerShell 技能连载 - 多个返回值

一个PowerShell函数可以有多个返回值。要接收这些返回值,只需要将返回值赋给多个变量:

function Get-DateTimeInfo
{
    # Value 1
    Get-Date -Format 'dddd'

    # Value 2
    Get-Date -Format 'MMMM'

    # Value 3
    Get-Date -Format 'HH:mm:ss'
}

$day, $month, $time = Get-DateTimeInfo

"Today is $day, the month is $month, and it is $time"
评论

PowerShell 技能连载 - 汇总索引

2013 年

2013 年 09 月

2013 年 10 月

2013 年 11 月

2013 年 12 月

2014 年

2014 年 01 月

2014 年 02 月

2014 年 03 月

2014 年 04 月

2014 年 05 月

2014 年 06 月

2014 年 07 月

2014 年 08 月

2014 年 09 月

2014 年 10 月

2014 年 11 月

2014 年 12 月

2015 年

2015 年 01 月

2015 年 02 月

2015 年 03 月

2015 年 04 月

2015 年 05 月

2015 年 06 月

2015 年 07 月

2015 年 08 月

2015 年 09 月

2015 年 10 月

2015 年 11 月

2015 年 12 月

2016 年

2016 年 01 月

2016 年 02 月

2016 年 08 月

2016 年 09 月

2016 年 10 月

2016 年 11 月

2016 年 12 月

2017 年

2017 年 01 月

2017 年 02 月

2017 年 03 月

2017 年 04 月

2017 年 05 月

2017 年 06 月

2017 年 07 月

2017 年 08 月

2017 年 09 月

2017 年 10 月

2017 年 11 月

2017 年 12 月

2018 年

2018 年 01 月

2018 年 02 月

2018 年 03 月

2018 年 04 月

2018 年 05 月

2018 年 06 月

2018 年 07 月

2018 年 08 月

2018 年 09 月

2018 年 10 月

2018 年 11 月

2018 年 12 月

2019 年

2019 年 01 月

2019 年 02 月

2019 年 03 月

2019 年 04 月

2019 年 05 月

2019 年 06 月

2019 年 07 月

2019 年 08 月

2019 年 09 月

2019 年 10 月

2019 年 11 月

2019 年 12 月

2020 年

2020 年 01 月

2020 年 02 月

2020 年 03 月

2020 年 04 月

2020 年 05 月

2020 年 06 月

2020 年 07 月

2020 年 08 月

2020 年 09 月

评论

PowerShell 技能连载 - 处理文件系统路径(第3部分)

在之前介绍的技巧中我们介绍了如何将文件系统路径转化为数组,并且通过改变或排除数组的一部分元素创建一个新的路径。
您可以通过将数组转化为 ArrayList 类型来使其变得更简单。现在,您可以非常容易地删除现有的或增加新的路径元素。

这个例子将第一个层文件夹重命名,排除第二层子文件夹,并在第4层子文件夹之后增加一个子文件夹:

$path = 'C:\users\Tobias\Desktop\functions.ps1'

[System.Collections.ArrayList]$array = $path -split '\\'
$array[1] = 'MyUsers'
$array.RemoveAt(2)
$array.Insert(3, 'NewSubFolder')
$array.Insert(4, 'AnotherNewSubFolder')
$array -join '\'

结果路径是:

C:\MyUsers\Desktop\NewSubFolder\AnotherNewSubFolder\functions.ps1
评论

PowerShell 技能连载 - 处理文件系统路径(第2部分)

当您将一个路径转换为数组来操作路径的各个部分时,如果您希望通过固定的数组下标来存取路径的部分,则该方法仅限于子文件夹的数量是固定的情况。

若要操作路径长度不固定的情况,试着利用变量。这个例子将会去除第1层和第2层子文件夹,无论路径有多长:

$path = 'C:\users\Tobias\Desktop\functions.ps1'

$array = $path -split '\\'
$length = $array.Count
$newpath = $array[,0+3..$length]
$newpath -join '\'

请注意提取新路径的数组元素的方法:

$newpath = $array[,0+3..$length]

这行代码取出第1个路径元素(下标为0)和第4个元素以及其之后的所有元素(下标从3开始)。

此处的奥秘是PowerShell支持多个数组下标。表达式 x..y 创建一个范围为x到y的数字型数组,其中x和/或y可以是变量。

当您需要增加单独的下标时,您必须将它们转化为数组,因为只有数组能被添加到数组中。这是为什么代码中下标0写成 ,0 的原因。这样写是为了创建一个只包含0的数组,并且这个数组可以被添加到数字范围的数组,并返回一个包含所有你需要的下标的数组。

评论

PowerShell 技能连载 - 处理文件系统路径(第1部分)

PowerShell允许您存取多个数组元素。通过使用 -help-join,您可以很方便地通过这种方式处理多个文件系统路径。

若要排除第二层和第三层文件夹,试试以下代码:

$path = 'C:\users\Tobias\Desktop\functions.ps1'
$array = $path -split '\\'
$newpath = $array[0,3,4]
$newpath -join '\'

若要重命名第二层子文件夹,试试以下代码:

$path = 'C:\users\Tobias\Desktop\functions.ps1'

$array = $path -split '\\'
$array[2] = 'OtherUser'
$array -join '\'
评论

定时休眠的命令

例如2个小时以后休眠:

timeout /t 7200 /nobreak & shutdown /h

注意事项:

  1. shutdown /h /t xxx 这样的组合是没用的。
  2. 注意倒计时过程中不能按 CTRL+C 组合键来中止倒计时,否则会立即休眠。正确中止倒计时的方法是直接关闭命令行窗口。
评论

用PowerShell统计关键词

本来开始打算大干一场的,结果发现区区4行代码搞定了。原来用PowerShell统计关键词这么欢乐啊。

$wordBreakers = ",. ()\\/';-<>_#"
$wordTemplate = '^Pub\w+'
cd D:\Dropbox\workdir\LandiStore\BOCISTDemo\src\Project

$content = (dir *.c -Recurse | % { cat $_} ) -join "`n"
$words = $content.Split($wordBreakers)
$words = $words | ? {$_ -Match $wordTemplate}
#$words | sort -Unique
$words | group | sort count -Descending | select Name, Count
评论