zoukankan      html  css  js  c++  java
  • Powershell快速入门

    Powershell快速入门

    来源:

    https://blog.csdn.net/u011054333/article/details/72567590

    https://blog.csdn.net/u011054333/article/details/72568190

    https://blog.csdn.net/u011054333/article/details/72798046

    一说起 Shell 编程,我们大家想到的应该都是Linux 下的 Shell 编程。其实 Windows 下也可以使用功能强大的 Shell 来编写程序,这就是今天我要介绍的 Powershell。从名字就可以看出来,Powershell的功能很强大,所以才敢叫Powershell。

    如果需要看官方文档的话,点击这里。虽然有一些机翻的意味,但是完全可以看。

    需要说明一点,Powershell是构建在.NET平台上的,所有命令传递的都是.NET对象。所以为了更好地使用Powershell,最好有一点.NET编程基础,这样学习Powershell就会感觉非常轻松和愉快。

    安装Powershell

    这里我介绍的是 Powershell 5.0 ,它在 Windows Server 2016 和Windows 10 操作系统中是默认安装的。如果使用的是比较旧的操作系统例如 Windows 7 或者 Windows 8.1 ,就需要手动安装 Powershell 5.0 。下载也很简单,到这里下载 WMF 5.0,它包含了 Powershell 5.0 和一系列工具。

    如果要查看当前Powershell版本的话,也很简单。在Powershell窗口中使用下面的命令即可查看相关信息。

    C:Usersasddf> $PSVersionTable
    
    Name                           Value                                                               
    ----                           -----                                                               
    PSVersion                      5.1.15063.296                                                       
    PSEdition                      Desktop                                                             
    PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                             
    BuildVersion                   10.0.15063.296                                                      
    CLRVersion                     4.0.30319.42000                                                     
    WSManStackVersion              3.0                                                                 
    PSRemotingProtocolVersion      2.3                                                                 
    SerializationVersion           1.1.0.1 

    启动Powershell

    启动 Powershell 很简单,从运行对话框或者开始菜单中搜索powershell即可。这样就可以打开 Powershell 命令行窗口了。默认情况下这是一个蓝色的窗口。

    在64位操作系统下,有两个版本的 Powershell 。默认情况下,我们使用64位版本就可以了。如果有特殊需求的话,可以选择启动带x86字样的32位版本的 Powershell 。

    Powershell窗口

    启动Powershell ISE

    在终端中敲命令是一件很麻烦的事情,有没有什么集成环境可以让我们进行交互式学习呢?当然是有的,Windows 附带了一个交互式环境,叫做Powershell ISE,可以帮助我们更方便的学习和使用 Powershell。

    启动 Powershell ISE也很简单,在Windows 10下,直接在开始菜单中输入 ISE,就可以打开Powershell ISE了。

    Windows Powershell ISE

    命令介绍

    首先说明一下,和 Linux Shell 不同,Powershell 的命令基本上都是动词-名词形式的。这样做的好处是命令作用很容易就可以看出,缺点就是输入稍微有些麻烦,习惯了Linux 的简洁的同学可能会不太适应。

    Powershell 和Linux Shell 还有一个不同点在于Powershell 是基于 .NET平台的,它的命令叫做cmdletcmdlet功能比普通的Linux 命令更强,因为cmdlet接受的参数不是字符串,而是 .NET 对象,这使得Powershell 的功能更加强大和灵活。

    获取命令

    如果想要获取当前会话中所有可用的内置命令,可以使用命令Get-Command,它的别名是gcm

    PS C:Usersasddf> Get-Command 
    
    CommandType     Name                                               Version    Source
    -----------     ----                                               -------    ------
    Cmdlet          Get-Command                                        3.0.0.0    Microsoft.PowerShell.Core
    .....

    如果希望列出指定名称的命令,可以使用Name参数。

    PS C:Usersasddf> Get-Command -Name Get-Command
    
    CommandType     Name                                               Version    Source
    -----------     ----                                               -------    ------
    Cmdlet          Get-Command                                        3.0.0.0    Microsoft.PowerShell.Core

    获取别名

    有些命令比较常用,除了动词-名词版本外,Powershell还提供了和Linux 一样的别名来简化输入。我们可以使用-CommandType Alias参数来显示所有的命令别名。下面列举了一部分输出,可以看到,微软为了照顾Linux用户,很多命令都缩写为Linux 命令的形式。

    PS C:Usersasddf> Get-Command -CommandType Alias
    
    CommandType     Name                                               Version    Source
    -----------     ----                                               -------    ------
    Alias           % -> ForEach-Object
    Alias           ? -> Where-Object
    Alias           ac -> Add-Content
    Alias           blsmba ->                                          2.0.0.0    SmbShare
    Alias           cat -> Get-Content
    Alias           cd -> Set-Location
    Alias           chdir -> Set-Location
    Alias           clc -> Clear-Content
    Alias           clear -> Clear-Host
    Alias           clhy -> Clear-History
    Alias           cli -> Clear-Item
    Alias           clp -> Clear-ItemProperty
    Alias           cls -> Clear-Host

    当然,如果你观察仔细的话,会发现命令类型这一栏有Aliascmdlet以及function三种类型。所以我在前面使用了“内置命令”这个词。函数基本上就是最简单的命令,例如清屏(Clear-Host),不能接受参数,功能比较基本。cmdlet则是功能强大的命令,可以接受各类参数,还能复合使用。Alias则是前两者的别名,作用是简化输入。

    获取动词/名词

    当然,如果想查找特定动词/名词的命令也是可以的。比方说,如果我想查找所有以Get开头的命令,可以使用下面的命令。

    PS C:Usersasddf> Get-Command -Verb Get

    相应的,如果我想获取所有名词是Help的命令,可以使用下面的命令。

    PS C:Usersasddf> Get-Command -Noun Help
    
    CommandType     Name                                               Version    Source
    -----------     ----                                               -------    ------
    Cmdlet          Get-Help                                           3.0.0.0    Microsoft.PowerShell.Core
    Cmdlet          Save-Help                                          3.0.0.0    Microsoft.PowerShell.Core
    Cmdlet          Update-Help                                        3.0.0.0    Microsoft.PowerShell.Core

    上面的命令都只列出了内置命令。如果需要包含包括普通程序在内的所有命令,可以使用通配符。

    PS C:Usersasddf> Get-Command *

    获取帮助

    如果要获取一个命令的帮助,可以使用Get-Help。如果使用上面介绍的列出别名的命令的话,会发现这个命令的别名是man,恰好就是Linux 系统下的获取帮助的命令。当然它们的功能也很相似。

    比方说,我们要查看一下清除屏幕这个命令的帮助,就可以简单的输入下面的命令。Powershell 会自动将别名解析为实际命令名称。所以我们可以看到,cls实际上是Clear-Host命令的别名。

    PS C:Usersasddf> man cls
    
    名称
        Clear-Host
    
    摘要
    
    
    语法
        Clear-Host [<CommonParameters>]
    
    
    说明
    
    
    相关链接
        https://go.microsoft.com/fwlink/?LinkID=225747
    
    备注
        若要查看示例,请键入: "get-help Clear-Host -examples".
        有关详细信息,请键入: "get-help Clear-Host -detailed".
        若要获取技术信息,请键入: "get-help Clear-Host -full".
        有关在线帮助,请键入: "get-help Clear-Host -online"

    其实从这个命令的帮助信息来看,我们就可以获得大部分信息。比方说,如果我们要查看这个命令的在线帮助,就可以如同上面的备注所说,在命令上添加-online参数,这样就会打开浏览器跳转到这个命令的在线帮助页上。

    值得一提的还有帮助参数-?、如果一个命令添加了帮助参数,那么Powershell 不会实际执行这个命令,而是显示它的帮助信息。

    服务管理

    原来,如果我们使用批处理来管理Windows服务的话,一般情况下用的是sc这个命令。这个命令的作用有很多,其中一项就是启动和停止Windows服务。不过在Powershell下有更好用的服务管理命令,功能也更加强大。

    首先我们先查看一下有什么管理服务的命令,只需要查询一下名词是service的命令即可。可以看到这些命令涵盖了从创建服务到管理服务的各个方面,功能很丰富。

    PS C:Usersasddf> Get-Command -Noun service
    
    CommandType     Name                                               Version    Source
    -----------     ----                                               -------    ------
    Cmdlet          Get-Service                                        3.1.0.0    Microsoft.PowerShell.Management
    Cmdlet          New-Service                                        3.1.0.0    Microsoft.PowerShell.Management
    Cmdlet          Restart-Service                                    3.1.0.0    Microsoft.PowerShell.Management
    Cmdlet          Resume-Service                                     3.1.0.0    Microsoft.PowerShell.Management
    Cmdlet          Set-Service                                        3.1.0.0    Microsoft.PowerShell.Management
    Cmdlet          Start-Service                                      3.1.0.0    Microsoft.PowerShell.Management
    Cmdlet          Stop-Service                                       3.1.0.0    Microsoft.PowerShell.Management
    Cmdlet          Suspend-Service                                    3.1.0.0    Microsoft.PowerShell.Management

    比方说,我们要查询一下当前计算机安装了哪些和MySQL相关的服务,就可以用下面的命令。

    PS C:Usersasddf> Get-Service mysql*
    
    Status   Name               DisplayName
    ------   ----               -----------
    Running  MySQL57            MySQL57

    然后如果需要停止服务也很简单,需要注意停止服务的话需要管理员权限,因此Powershell需要在管理员模式下运行。

    PS C:WINDOWSsystem32> Stop-Service  MySQL57
    警告: 正在等待服务“MySQL57 (MySQL57)”停止...

    其他命令就不介绍了,配合帮助命令可以很快学习如何使用。

    应用实例

    最后直接从网上找了个例子来看看Powershell的实际作用。我们可以从中了解到Powershell的强大特性,用它帮助我们方便地管理Windows操作系统。

    Office互操作

    这里贴一个网络上的例子,我是从知乎上看到的。运行一下会直接打开Excel并填充数据,然后画出占用内存前十的程序的饼状图,一气呵成。我第一次运行的时候简直惊呆了。

    # create new excel instance
     $objExcel = New-Object -comobject Excel.Application
     $objExcel.Visible = $True
     $objWorkbook = $objExcel.Workbooks.Add()
     $objWorksheet = $objWorkbook.Worksheets.Item(1)
    
     # write information to the excel file
    $i = 0
    $first10 = (ps | sort ws -Descending | select -first 10)
    $first10 | foreach -Process {$i++; $objWorksheet.Cells.Item($i,1) = $_.name; $objWorksheet.Cells.Item($i,2) = $_.ws}
    $otherMem = (ps | measure ws -s).Sum - ($first10 | measure ws -s).Sum
    $objWorksheet.Cells.Item(11,1) = "Others"; $objWorksheet.Cells.Item(11,2) = $otherMem
    
    # draw the pie chart
    $objCharts = $objWorksheet.ChartObjects()
    $objChart = $objCharts.Add(0, 0, 500, 300)
    $objChart.Chart.SetSourceData($objWorksheet.range("A1:B11"), 2)
    $objChart.Chart.ChartType = 70
    $objChart.Chart.ApplyDataLabels(5)

    当然其实Powershell能做的事情非常多。微软自从Powershell出现之后就一直推动Windows和Powershell的互操作。到现在为止大概大部分Windows管理和配置功能都可以使用Powershell来进行。

    一开始我也对Powershell不太了解。不过了解了一点之后,我感觉Powershell的功能确实对得起它的名字。我已经决定学习完Powershell之后,将来在所有可以使用Powershell的地方全部使用它,享受命令行管理系统的快感。

    这一部分着重于介绍Powershell的程序知识,让我们能够编写功能强大的Powershell脚本,执行比较复杂的任务。

    变量

    变量使用$变量名创建和引用。举个例子,Get-Location命令用于获取当前工作目录位置,它的别名是pwd。那么我们可以使用下面的命令来创建一个变量,存储当前目录位置。

    C:Usersasddf> $current=pwd

    然后我们访问$current,就可以获取实际值了。

    C:Usersasddf> $current
    
    Path          
    ----          
    C:Usersasddf

    如果知道这个命令返回的实际是.NET对象的话,我们还可以更进一步,比方说直接访问这个对象的Path属性,获取值。

    C:Usersasddf> $current.Path
    C:Usersasddf

    还有一个命令Get-Member,别名是gm,用于获取对象的属性。比方说,我们将Get-Location命令的结果通过管道传递给Get-Member命令,就会显示下面的输出。如果不了解.NET的话,可能感觉比较陌生。但是如果你懂得.NET和C#的话,就会像我一样大喊一声:“卧槽,还能这样玩?!”

    C:Usersasddf> Get-Location|Get-Member
    
    
       TypeName:System.Management.Automation.PathInfo
    
    Name         MemberType Definition                                               
    ----         ---------- ----------                                               
    Equals       Method     bool Equals(System.Object obj)                           
    GetHashCode  Method     int GetHashCode()                                        
    GetType      Method     type GetType()                                           
    ToString     Method     string ToString()                                        
    Drive        Property   System.Management.Automation.PSDriveInfo Drive {get;}    
    Path         Property   string Path {get;}                                       
    Provider     Property   System.Management.Automation.ProviderInfo Provider {get;}
    ProviderPath Property   string ProviderPath {get;}

    如果我们要获取对象的所有属性,使用MemberType参数。

    C:Usersasddf> pwd|gm -MemberType Property

    我们还可以在变量上调用方法, 比如说将路径转换为全小写。

    
    C:Usersasddf> $current.Path.ToLower()
    c:usersasddf

    最后,如果不再需要一个变量,可以使用Remove-Variable删除变量,它的别名是rv

    C:Usersasddf> Remove-Variable current

    操作符

    来看看Powershell中支持的操作符。

    数学运算符

    首先,基本的数学运算符都是支持的。

    PS D:Desktop> $i=5
    PS D:Desktop> $sum=3+4*($i-3)/2
    PS D:Desktop> $sum
    7

    前置后置自增自减运算符也是支持的。

    PS D:Desktop> $i=0
    PS D:Desktop> $i--
    PS D:Desktop> $i++
    PS D:Desktop> ++$i
    PS D:Desktop> --$i

    比较运算符

    然后是比较运算符,这些和Linux Shell中很相似,有大于(-gt),大于等于(-ge),小于(-lt),小于等于(-le),等于(-eq),不等于(-ne)几个。

    字符串匹配运算符

    -like-notlike用于?*这样的通配符。

    PS D:Desktop> 'hello' -like '?ello'
    True
    PS D:Desktop> 'hello' -notlike '?ello'
    False
    PS D:Desktop> 'hello' -like '*o'
    True

    -match-notmatch用于正则表达式。

    PS D:Desktop> 'aabcc' -match 'a*b?c+'
    True
    PS D:Desktop> 'aab' -match 'a*b?c+'
    False

    包含和替换运算符

    -contains查找序列中是否包含某个元素。

    PS D:Desktop> 'hello','zhang3' -contains 'zhang3'
    True

    -replace用于替换字符串中某个部分,当然正则表达式也是支持的。

    PS D:Desktop> 'hello zhang3' -replace 'zhang3','yitian'
    hello yitian

    分隔和连接运算符

    -split-join用于将一个字符串分为几个子部分,或者将几个子部分组合为一个字符串。

    PS D:Desktop> 'A B C DE' -split ' '
    A
    B
    C
    DE
    PS D:Desktop> 'A','B','C' -join ','
    A,B,C

    上面这些运算符都是大小写不敏感的,如果需要大小写敏感的功能,可以在运算符前面添加c前缀。

    PS D:Desktop> 'yitian' -match 'Yitian'
    True
    PS D:Desktop> 'yitian' -cmatch 'Yitian'
    False

    逻辑运算符

    逻辑运算符有与(-and)、或(-or)、非(-not!)以及异或(xor)几个,并且支持短路计算。

    如果需要使用真值和假值字面量,可以使用$true$false

    类型运算符

    Powershell 和.NET平台绑定,所以它是一门强类型的脚本。因此我们可以在脚本中判断数据的类型,只要使用-is-isnot运算符即可,类型需要写到方括号中。这里的类型可以是所有合适的.NET类型。

    PS D:Desktop> 3.14 -is [Double]
    True
    PS D:Desktop> 3.14 -isnot [Float]
    True

    重定向运算符

    这个稍微比较麻烦一点。

    首先是>>>运算符,用于将标准输出流重定向到文件,前者会覆盖已有文件,后者则是追加到已有文件末尾。

    然后我们来说说日志级别,如果有使用过某些语言的日志框架的话,就很好理解了。在这里,2代表错误、3代表警告、4代表信息、5代表调试信息。n>n>>运算符就是用于将对应级别的输出重定向到文件的,这两者的区别和前面相同。n>&1将对应级别的输出和标准输出一起重定向到文件。

    最后就是*>*>>了,这两者将所有输出信息重定向到文件。

    需要注意,Powershell使用Unicode编码来输出信息。如果你需要使用其他类型的编码,就不能使用重定向运算符了,而应该使用Out-File命令。

    特殊运算符

    &运算符将它后面的命令设置为后台运行,当运行的命令需要阻塞当前终端的时候很有用。

    .\运算符用于执行一个脚本或命令。如果执行的是Powershell脚本,那么脚本会在自己的作用域中执行,也就是说在当前环境下无法访问被执行的脚本中的变量。

    []运算符用于转换变量的类型,比如说下面的代码,就将pi变量转换为了Float类型。

    [Float]$pi = 3.14
    $pi -is [Float]

    .运算符用于调用.NET对象的成员,它也可以用于执行脚本。当它用于执行脚本的时候,脚本会在当前作用域中执行。所以脚本结束之后,我们可以访问脚本中的元素。

    ::运算符用于调用类中的静态成员,例如下面就会调用.NET平台中DateTime类的Now属性。

    PS D:Desktop> [DateTime]::Now
    
    2017年5月18日 22:45:42

    ..运算符用于创建一个范围闭区间,例如下面这样。

    PS D:Desktop> 1..3
    1
    2
    3
    PS D:Desktop> 3..1
    3
    2
    1

    -f运算符用于格式化数据,例如下面这样。格式化方法和C#中的完全相同,所以如果不熟悉的话直接看在C#中如何格式化数据就行了。

    PS D:Desktop> 'My name is {0}, I am {1} years old' -f 'yitian',24
    My name is yitian, I am 24 years old

    $运算符可以将字符串内部的变量转换为实际的值,例如下面这样。需要注意使用内插操作符的时候,外部字符串需要使用双引号,否则Powershell会直接输出字符串内容。

    PS D:Desktop> $name='yitian'
    PS D:Desktop> $age=24
    PS D:Desktop> "My name is $name, I am $age years old."
    My name is yitian, I am 24 years old.

    @()运算符用于将一系列值转换为一个数组。假如在脚本中有一个函数可能返回0、1或多个值,就可以使用这个操作符,将一系列值合并为一个数组,方便后续处理。

    ,逗号运算符如果放置在单个值前面,就会创建一个包含这个值的单元素数组。

    条件判断

    if判断

    Powershell中的条件判断和一般的编程语言以及Shell编程都很类似,直接看代码就能理解。

    $condition = $true
    
    if ($condition -eq $true) {
        Write-Output "condition is $true"
    }
    elseif ($condition -ne $true ) {
        Write-Output "condition is $false"
    }
    else {
        Write-Output "other ocndition"
    }

    switch判断

    如果需要多重判断,可以考虑使用switch语句。一个典型的switch如下所示。

    $n = 4
    switch ($n) {
        1 {"n is 1"}
        2 {"n is 2"}
        3 {"n is 3"}
        default {"n is others"}
    }

    其实细说起来,这个switch的坑还是不少的。例如,switch语句可以接受多个值来测试,在switch语句中还可以编写多个case相同的语句。这里我就不细说了,想具体了解的话直接看官方文档 about_Switch吧。

    循环语句

    提醒一下,不管是哪种循环语句,在循环体内都可以使用breakcontinue中断/继续循环。

    do循环

    首先来看看do-while循环,先执行循环体,然后判断是否满足条件,如果满足条件则继续执行。

    $i = 0
    do {
        $i++
        Write-Output $i
    }while ($i -ne 3)

    然后是do-until循环,和do-while类似,不过当条件不满足的时候才会继续循环,如果满足条件则退出循环。

    $i = 0
    do {
        $i++
        Write-Output $i
    }until ($i -eq 3)

    while循环

    while循环是先判断循环条件,满足条件时执行循环。

    $i = 0
    while ($i -lt 3) {
        Write-Output $i
        $i++
    }

    for循环

    for循环可以看做是while循环的另一种形式,常用于固定次数的循环。

    for ($i = 0; $i -ne 3; $i++) {
        Write-Output $i
    }

    for-each循环

    for-each循环用于遍历一个集合中的所有元素。

    $array = @(1, 2, 3, 4)
    foreach ($i in $array) {
        Write-Output $i
    }

    值得一提的是,for-each语句用在管道上时,还有以下一种用法。

    <command> | foreach {<beginning command_block>}{<middle command_block>}{<ending command_block>}

    使用这种方法时,for-each后面可以跟三个语句块,第一个语句块是开始语句块,在循环前执行一次,常用来初始化一些数据;第三个是结束语句块,在循环结束之后执行一次,常用于统计一些循环数据;第二个就是正常的循环语句块,会循环多次。

    函数

    定义函数

    定义函数使用function关键字。

    function hello {
        Write-Output 'Hello Powershell'
    }

    定义好函数之后,就可以使用函数名来调用函数了。

    hello

    函数的参数

    函数当然也可以带参数了,参数列表有两种写法:第一种是C风格的,参数列表写在函数名后面,使用小括号分隔开;第二种方式是在方法体中,使用param关键字声明参数。这两种方法是完全等价的,当然我习惯上还是喜欢使用第一种方式。

    Powershell是一种强类型的脚本语言,所以可以在参数列表上添加参数类型,参数类型是可选的,不过我还是推荐写的时候带上类型,方便阅读和类型检查。

    function Say-Hello ([string] $name) {
        Write-Output "Hello, $name"
    }
    
    function Say-Hello2 {
        param([string] $name)
        Write-Output "Hello, $name"
    }

    调用带参数的函数时,需要向调用命令那样,使用-参数名来传递参数,例如下面这样。

    Say-Hello -name 'yitian'

    默认参数

    Powershell支持默认参数,直接用赋值号=在参数列表上指定参数默认值即可。

    
    function Say-Hello3 {
        param([string] $name = 'zhang3')
        Write-Output "Hello, $name"
    }

    位置参数

    Powershell也支持位置参数,它会把所有参数包装到$args数组中,所以我们可以通过这个变量访问所有位置的参数。例如下面,将所有参数合并一个字符串,然后打印出来。

    function Say-Hellos {
        $names = $args -join ','
        Write-Output "Hello, $names"
    }

    这个函数调用时候需要指定多个参数,注意不要在多个参数之间添加括号,否则会变成一个数组参数,而不是多个参数。

    Say-Hellos 'yitian' 'zhang3' 'li4'

    开关参数

    开关参数没有类型,作用仅仅是标志是或者否。如果在使用函数的时候带上开关参数,那么它就是开的状态,否则就是关的状态。开关参数需要指定参数类型为switch

    function Answer-Hello ([switch] $yes) {
        if ($yes) {
            Write-Output "Hi"
        }
    }

    然后在调用时就可以看出区别了。

    Answer-Hello -yes
    Answer-Hello 

    函数返回值

    最后来说说函数返回值。这个其实也很简单,只要使用return语句就可以了。

    function Add ([double]$a, [double]$b) {
        $c = $a + $b
        return $c
    }

    然后我们调用函数,就可以看到结果了。

    Add -a 3 -b 5

    关于Powershell编程的知识就介绍到这里,其实如果看看官方文档的话,就知道这里介绍的也仅仅是一部分而已。不过这一部分对于我们日常使用和学习基本上也够用了。

    如果要查看详细帮助的话,可以运行一下下面的命令,这样会显示所有和Powershell相关的帮助文档。

    Get-Help about*

    然后,就可以阅读自己感兴趣的部分了。比方说,如果我们想了解用Powershell编写类,就可以使用下面的命令。如果想在浏览器中浏览器在线版本,加上-online参数即可。

    Get-Help about_Classes

    参考资料

    https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_operators?f=255&MSPPError=-2147217396

    http://windowsitpro.com/powershell/windows-powershell-operators

    好像关于Powershell说的已经差不多了,所以最后一篇文章就来使用Powershell写一些脚本,帮助我们完成一些日常工作。

    文件管理

    常用命令

    先来看看常用的文件管理命令。

    Set-Location命令用于切换工作目录,它的别名是cd

    Get-Location命令用于获取当前工作目录,它的别名是pwd

    Get-ChildItem命令用于获取当前目录下的所有文件。

    Get-Item命令用于获取给定文件的信息。

    还有文件移动、删除、复制、粘贴、重命名等命令,输入Get-Command -Noun item就可以看到这些命令,这里就不做介绍了。

    获取文件信息

    获取文件信息可以利用命令Get-Item。下面获取了我电脑上的cmder.exe可执行文件的信息。

    λ  Get-Item .Cmder.exe
    
    
        目录: D:devtoolscmder_mini
    
    
    Mode                LastWriteTime         Length Name
    ----                -------------         ------ ----
    -a----        2016/12/2      7:15         130560 Cmder.exe

    默认只列出这么三个属性,当然其实文件属性远不止这些。我们可以通过管道,将文件信息对象传递给命令Select-Object,让它帮我们显示所有属性。这里只粘贴了一点点内容,其实文件信息很长,大家可以自行尝试。

    λ  Get-Item .Cmder.exe|Select-Object *
    
    
    PSPath            : Microsoft.PowerShell.CoreFileSystem::D:devtoolscmder_miniCmder.exe
    PSParentPath      : Microsoft.PowerShell.CoreFileSystem::D:devtoolscmder_mini

    过滤文件

    Get-ChildItem显示当前当前文件的时候,会显示所有文件。有时候我们可能仅仅需要搜索或者过滤部分文件。

    首先,如果是比较简单的需求,可以使用?*通配符来搞定,问号用于匹配任意单个字符,星号用于匹配任意多个字符。比方说,我想要列出所有.md格式的文件,就可以使用下面的命令。

    PS D:devtoolscmder_mini> Get-ChildItem *.md
    
    
        目录: D:devtoolscmder_mini
    
    
    Mode                LastWriteTime         Length Name
    ----                -------------         ------ ----
    -a----        2016/12/2      7:14          73491 CHANGELOG.md
    -a----        2016/12/2      7:14           1784 CONTRIBUTING.md
    -a----        2016/12/2      7:14          10039 README.md

    有时候可能需要使用正则表达式来查找文件,不过好像Get-ChildItem没有正则表达式查询的命令行,不过我们可以使用Where-Object命令来自定义查询。如果了解C#语言的LINQ的话,应该可以猜到,这个命令对应于LINQ的where语句。

    下面同样是查找所有.md格式的文件,不过这次使用了Where-Object和正则表达式,其中Where-Object里面的$_是形式变量,代表每次迭代的文件。如果了解过C#的LINQ,或者Java 8的流类库,应该对这种形式会比较熟悉。

    Get-ChildItem|Where-Object {$_ -match 'w*.md$'}

    如果仅仅为了搜索文件名的话,这种方式好像一点优势都没有。实际上Where-Object的功能非常强大。比方说,我现在想查找大于5kb的所有.md格式文件,那么就可以这么写。这里又用到了Powershell的一个方便的特性,文件大小单位,KB GB MB TB等单位都支持。当然其实并不仅仅可以查询文件大小属性,基本上所有文件信息都可以用来查询。

     Get-ChildItem|Where-Object {$_ -match 'w*.md$' -and $_.Length/1kb -gt 5}

    最后,Get-ChildItem不仅可以列出当前文件夹下的所有内容,还可以递归查询所有子文件夹。比方说,我要查找一下迅雷文件夹下所有可执行文件,就可以使用下面的命令。如果添加-Depth参数的话,还可以指定递归深度。

     Get-ChildItem -Recurse *.exe

    修改hosts

    访问谷歌的一种方式就是更改hosts文件。这里就用Powershell做一个修改hosts的功能。

    首先先来介绍一个命令Invoke-WebRequest,利用它我们可以获取网页内容、下载文件甚至是填写表单。这个命令的别名是iwrcurlwget。我们就使用它来下载网上的hosts文件。

    剩余就没有什么难度了,无非就是读写文件、追加文件、复制和粘贴这种基本操作。最后写完这个功能发现有一百多行,就不往这里复制粘贴了。如果有兴趣的话,可以直接看我的Github上面的脚本

    进程管理

    查看进程

    首先我们看看有多少和进程相关的命令,这个很简单,只要查看一下名词是Process的命令即可。

    PS C:WINDOWSsystem32> Get-Command -Noun process
    
    CommandType     Name                                               Version    Source
    -----------     ----                                               -------    ------
    Cmdlet          Debug-Process                                      3.1.0.0    Microsoft.PowerShell.Management
    Cmdlet          Get-Process                                        3.1.0.0    Microsoft.PowerShell.Management
    Cmdlet          Start-Process                                      3.1.0.0    Microsoft.PowerShell.Management
    Cmdlet          Stop-Process                                       3.1.0.0    Microsoft.PowerShell.Management
    Cmdlet          Wait-Process                                       3.1.0.0    Microsoft.PowerShell.Management

    使用这些命令,我们就可以非常方便的管理进程了。比方说,我想查询现在运行的所有进程,就可以使用下面的命令,这样就会列出所有运行的进程,就像任务管理器里显示的那样。

    PS C:WINDOWSsystem32> Get-ProcessGet-Process

    上面这个命令会显示所有进程。如果需要,我们可以按照某个属性对进程进行排序显示,这需要使用另外一个命令Sort-Object。另外,如果只需要显示前几个进程,可以使用命令Select-Object来选择显示多少数据。比方说,如果我们要查看当前占用CPU前5的chrome进程,就可以使用下面的命令。

    Get-Process chrome|Sort-Object cpu -Descending|Select-Object -First 5

    利用这几个命令,我们可以按照任何想要的方式来查询进程。

    管理进程

    先来看看MSDN上的一个官方例子。首先先打开三个记事本进程,然后使用名称获取这些进程,然后调用进程的Kill()函数即可把这些进程全杀掉。中间调用了Count属性测试了一下总共获取到了几个进程。

    PS C:WINDOWSsystem32> notepad;notepad;notepad;
    PS C:WINDOWSsystem32> $notepads=Get-Process -Name notepad
    PS C:WINDOWSsystem32> $notepads.Count
    3
    PS C:WINDOWSsystem32> $notepads.Kill()

    再学习Powershell编程的时候,我们常常会同时开几个Powershell窗口。不再使用的时候一个一个关闭它们也是一件麻烦事情,所以官方文档还为我们介绍了如何关闭除当前窗口外的所有Powershell进程。

    每个Powershell进程都有一个变量$PID,用于标志当前进程的进程号,利用这一点我们就可以实现这个功能。这里的-WhatIf参数表示不真正关闭进程,仅列出将要关闭的进程。

    PS C:WINDOWSsystem32> Get-Process powershell |Where-Object {$_.Id -ne $PID}|Stop-Process -WhatIf
    WhatIf: 正在目标“powershell (2676)”上执行操作“Stop-Process”。

    如果既想要关闭进程,还想知道关闭了哪些进程,可以使用-PassThru参数。

    PS C:WINDOWSsystem32> Get-Process powershell |Where-Object {$_.Id -ne $PID}|Stop-Process -PassThru
    
    Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
    -------  ------    -----      -----     ------     --  -- -----------
        573      30    56884      68992       0.92   2676   1 powershell

    轮询关闭进程

    如果在死循环中不断查找任务管理器进程,发现它在运行就把它关闭,就可以做一个小小的“病毒”。代码很简单,基本上一下子就能看懂。一开始我没有加Sleep,然后CPU使用率飚的非常高,加了之后基本上对电脑性能没有影响了。

    $process_name = "taskmgr"
    while ($true) {
        $processes = Get-Process
        if ($processes.Name -contains $process_name) {
            Get-Process $process_name|Stop-Process
        }
        else {
            Start-Sleep -Milliseconds 500
        }
    
    }

    如果把上面代码中的taskmgr换成英雄联盟的进程名字,我们就可以做一个简单的“熊孩子防火墙”,防止熊孩子用电脑来玩游戏了。

    注册表操作

    读写注册表

    读取注册表

    首先来介绍一下注册表根的简写,例如HKEY_CURRENT_USER的简写就是HKCUHKEY_LOCAL_MACHINE的简写就是HKLM。知道了简写,我们就可以将Powershell的工作目录切换到注册表内。例如,如果我们想查看HKEY_CURRENT_USERControl PanelDesktopMuiCached下的值,就可以先把工作目录切换到这个位置内部。这里需要将对应的注册表根修改为对应的简写加冒号的形式。

    PS C:WINDOWSsystem32> Set-Location 'HKCU:Control PanelDesktopMuiCached'
    PS HKCU:Control PanelDesktopMuiCached>

    切换到了注册表内部,我们就可以利用Get-Item命令获取注册表的值了。比如说,要获取这个注册表键的值,就可以直接输入Get-Item .了。注意这个点不能省去,它代表当前工作目录。

    PS HKCU:Control PanelDesktopMuiCached> Get-Item .
    
    
        Hive: HKEY_CURRENT_USERControl PanelDesktop
    
    
    Name                           Property
    ----                           --------
    MuiCached                      MachinePreferredUILanguages : {zh-CN}

    如果要获取当前注册表项的属性值,可以利用Get-ItemProperty命令。

    PS HKCU:Control PanelDesktopMuiCached> Get-ItemProperty .  MachinePreferredUILanguages
    
    
    MachinePreferredUILanguages : {zh-CN}
    PSPath                      : Microsoft.PowerShell.CoreRegistry::HKEY_CURRENT_USERControl PanelDesktopMuiCached
    PSParentPath                : Microsoft.PowerShell.CoreRegistry::HKEY_CURRENT_USERControl PanelDesktop
    PSChildName                 : MuiCached
    PSDrive                     : HKCU
    PSProvider                  : Microsoft.PowerShell.CoreRegistry

    当然,切换工作目录这件事情也可以不做。直接利用Get-ItemProperty命令通过路径参数来获取属性。

    Get-ItemProperty -Path 'HKCU:Control PanelDesktopMuiCached' -Name MachinePreferredUILanguages

    编辑注册表项

    下面这个路径是一个安全的注册表路径,在这里修改注册表不会造成严重的系统问题。所以我们把它保存为一个变量。

     $path = "HKCU:Control PanelDesktop"

    如果要新建注册表项,可以使用New-Item命令。我们可以使用注册表编辑器regedit来验证项是否创建成功。

     New-Item –Path $path –Name HelloKey

    如果要修改项的属性,使用Set-ItemProperty命令。

    Set-ItemProperty -path $pathhellokey -name Fake -Value fuck

    最后,如果要删除项的属性,使用Remove-ItemProperty命令。

    Remove-ItemProperty -path $pathhellokey -name Fake

    如果要删除整个注册表项,使用Remove-Item命令。

    Remove-Item -path $pathhellokey -Recurse

    获取当前.NET版本

    下面的参考资料中列出了一个MSDN上的文档,告诉我们如何读取注册表的值来判断当前安装了.NET Framework的版本,并给出了相应的C#代码。下面的代码做的就是将C#代码改写成Powershell脚本。

    # 判断系统当前安装.NET框架版本的脚本
    
    $path = 'HKLM:SOFTWAREMicrosoftNET Framework SetupNDPv4Full'
    $not_found_msg = ".net framework 4.5 or later not installed on your system"
    
    function CheckFor45PlusVersion([int] $releaseKey) {
        if ($releaseKey -ge 460798) {
            return "4.7 or later";
        }
        if ($releaseKey -ge 394802) {
            return "4.6.2";
        }   
        if ($releaseKey -ge 394254) {
            return "4.6.1";
        }
        if ($releaseKey -ge 393295) {
            return "4.6";
        }
        if (($releaseKey -ge 379893)) {
            return "4.5.2";
        }
        if (($releaseKey -ge 378675)) {
            return "4.5.1";
        }
        if (($releaseKey -ge 378389)) {
            return "4.5";
        }
        return $not_found_msg;
    }
    
    
    try {
        $key = get-item $path
        $releaseKey = Get-ItemPropertyValue $path 'release'
        if ($releaseKey -is [int]) {
            $releaseKey = [int]$releaseKey
            $version = CheckFor45PlusVersion($releaseKey)
            Write-Host ".NET framework ${version}"
        }
        else {
            Write-Host $not_found_msg
        }
    }catch {
        Write-Host $not_found_msg
    }

    Office互操作

    操作Excel

    虽然Powershell可以通过COM接口和Office程序交互,不过最常用的还是操作Excel,所以我这里只介绍如何控制Excel表。下面最后一个参考资料就是我参考的操作Excel的文章,可能需要梯子才能访问。需要注意一点,既然是操作Excel,当然首先电脑上需要先安装Excel才能正常使用。

    打开和关闭

    首先,我们来创建一个Excel对象,这样实际上会创建一个Excel应用程序。

    $excel = New-Object -ComObject Excel.Application

    执行了上面的命令,什么事情都没有发生。这是因为默认启动的实例是隐藏的,要显示Excel的窗口的话,将它设置为可见即可。

    $excel.Visible=$true

    如果要打开一个现成的工作簿,使用Open函数。

    $workbook = $excel.Workbooks.Open("XXX.xlsx")

    如果要创建一个新的工作簿,使用Add函数。

    $workbook = $excel.Workbooks.Add()

    一个工作簿可以有多个工作表,要选择某一个工作表,使用Worksheets.Item属性,需要注意这里的下标从一开始。

    $worksheet = $workbook.Worksheets.Item(1)

    对数据完成操作之后,需要保存的话,使用SaveAs函数。

    $workbook.SaveAs("D:Desktophello.xlsx")

    操作数据

    前面只说了打开和关闭操作,下面来看看如何具体读取和写入数据。首先回到上面那步工作表,因为如果要操作数据,需要在工作表对象上进行操作。

    $worksheet = $workbook.Worksheets.Item(1)

    要操作数据,调用工作表对象的Cells属性即可。比方说我要打印九九乘法表,那么就可以用类似下面的代码来迭代写入数据。

    for ($i = 1; $i -le 9; ++$i) {
        # 第一行
        $worksheet.Cells(1, $i + 1) = $i
        # 第一列
        $worksheet.Cells($i + 1, 1) = $i
        # 它们的乘积
        for ($j = 1; $j -le 9; ++$j) {
            $worksheet.Cells($i + 1, $j + 1) = $i * $j
        }
    }

    操作之后,Excel表中应该存在如图所示的数据。

    写入数据

    类似的,读取数据也很简单,只要读取Cells属性即可。

    for ($i = 1; $i -le 10; ++$i) {
        for ($j = 1; $j -le 10; ++$j) {
            Write-Host -NoNewline $worksheet.Cells($i, $j).Text "`t"
        }
        Write-Host
    }

    上面的代码获取了我们刚才写入Excel的数据,然后将其转换为文本并输出,每个数据之间使用制表符 分隔,注意Powershell中的转义字符使用的这个特殊字符。结果应该类似如图所示。

    读取数据

    绘制图表

    Excel很常用的一种操作就是绘制图表,这里也简单说说。不过由于这种资料在网上面实在太少,我就算用谷歌搜索英文网页也搜不出来多少资料,大部分都属于一点小脚本。所以这里只能随便说说了。

    首先准备一下数据,我准备了如图所示的数据。

    准备数据

    然后来创建一个图表对象。如果使用交互式环境Powershell ISE的话,智能提示会显示这里有AddChartAddChart2两个方法,不过我看了下文档,前面那个过时了,所以这里使用带2的那个版本。

    $chart=$worksheet.Shapes.AddChart2().Chart

    创建了图表对象之后,我们为它指定数据源。

    $chart.SetSourceData($worksheet.Range('a1', 'd5'))

    这时候如果观察Excel的话,会发现已经出现了一个初步的图形。如果希望改变图形样式的话,设置图标的类型即可。这里将图表类型保存为一个变量,之后就可以省略长长的类名了。这里推荐使用Powershell ISE,因为自动补全可以显示所有类型的图标,只需要修改一下图表类型并观察Excel中图标类型的变化就可以明白类型和图标的对应关系了。

    $chartTypes = [Microsoft.Office.Interop.Excel.XLChartType]
    $chart.ChartType = $chartTypes::xlColumnClustered

    最后效果如图所示,我看到人家可以使用方法显示图例。但是我使用这个方法却不知道为什么显示不了。所以这里只能将就一下了。

    最终效果图

    最后再来画个饼状图,数据还是上面的数据,不过这次只使用语文那一列的数据。基本上和上面的一样,只有类型那里改成xlPie

    $chartTypes = [Microsoft.Office.Interop.Excel.XLChartType]
    $chart = $worksheet.Shapes.AddChart2().Chart
    $chart.SetSourceData($worksheet.Range('a1', 'b5'))
    $chart.ChartType = $chartTypes::xlPie
    $chart.ApplyDataLabels(5)

    最终效果图如下。

    饼状图

    ImportExcel

    上面的方法好像只能在安装Excel的环境下运行,如果没有安装Office,但是也想使用编程功能,可以使用第三方的模块。这就是这里要介绍的ImportExcel。使用它,我们可以在没有安装Excel的情况下编辑Excel文件。

    首先需要安装它,可以利用Powershell的包管理器方便的安装。

    Install-Module ImportExcel -scope CurrentUser

    如果想让所有用户都可以使用这个模块,需要安装到全局位置,不过这需要管理员权限,所以需要在管理员模式的Powershell窗口中运行。

    Install-Module ImportExcel

    这个模块如何使用我就不作介绍了,这个项目的README文件上基本列出了所有功能和对应的GIF图,需要什么功能只要看一看应该就可以使用了。

    参考资料

    https://4sysops.com/archives/interacting-with-the-registry-in-powershell/

    https://msdn.microsoft.com/en-us/library/hh925568(v=vs.110).aspx

    https://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.aspx

    http://www.lazywinadmin.com/2014/03/powershell-read-excel-file-using-com.html

  • 相关阅读:
    北漂开始
    iOS沙盒简单介绍
    iOS多线程技术
    使用Redis实现分布式锁
    Spring Cloud构建微服务架构(六)高可用服务注册中心
    springboot学习之maven多环境打包的几种方式
    数据库中in和exists关键字的区别
    Java 中的悲观锁和乐观锁的实现
    springboot学习笔记-5 springboot整合shiro
    spring 整合 redis,以及spring的RedisTemplate如何使用
  • 原文地址:https://www.cnblogs.com/lsgxeva/p/9309576.html
Copyright © 2011-2022 走看看