欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

PowerShell 入门3

程序员文章站 2022-03-09 12:21:43
...

更多请看(www.omob.cc PowerShell 入门3
本文参考自Powershell快速入门(三) Shell编程
这一篇文章,我将记录下PowerShell的几个简单的实践例子,给读者参考。结合前面两篇PowerShell的文章,我们开始从理论实践,用PowerShell操作我们Windows电脑上的文件,进程,软件等资源,为日后的Windows Server管理打开一个良好的开端

这一节,我们开始创建简单的PowerShell脚本文件,在写脚本的过程中,我们可以使用VS Code编辑器并在VS Code里打开Shell总断,一边在Shell终端临时输入代码验证,一边把验证过的代码记录在编辑器里面,这样可以事半功倍,免去频繁的验证和切换窗口。PowerShell脚本的后缀名为.ps1,名如其人,微软少有的把这么嚣张的名字给了PowerShell,貌似不符合微微一软的微软低调的取名风格。其实我个人认为PowerShell对的起这个名字,学习的曲线很平,功能完全不输甚至超过了Linux的bash。至于为什么后缀不是.ps,我猜第一是photoshop这个软件出名,不能引起误解,第二是微软的文件后缀名一版都是三个字比如.exe

操作文件

我们先新建一个HelloWorld.ps1

PS D:\workspace\langs\powershell> ls


    目录: D:\workspace\langs\powershell


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        2018/7/19     23:01            158 HelloWorld.ps1

在窗口先测试代码:

执行后会把计算结果写到a.txt中

PS C:\Users\think\Desktop> $i = 2
PS C:\Users\think\Desktop> $j = 3
PS C:\Users\think\Desktop>
# 输入到文件
PS C:\Users\think\Desktop> $i*$j>./a.txt
# 同时输入到控制台
PS C:\Users\think\Desktop> Get-Content ./a.txt | Write-Output
6

再把上面测试通过的代码记录到VS code里面,保存到HelloWorld.ps1即可

我们执行脚本运行成功

PS D:\workspace\langs\powershell> .\HelloWorld.ps1
6


    目录: D:\workspace\langs\powershell


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        2018/7/19     23:25              8 a.txt

文件管理

常用命令

先来看看常用的文件管理命令。
- Set-Location命令用于切换工作目录,它的别名是cd。
- Get-Location命令用于获取当前工作目录,它的别名是pwd。
- Get-ChildItem命令用于获取当前目录下的所有文件。
- Get-Item命令用于获取给定文件的信息。

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

获取文件信息

获取文件信息可以利用命令Get-Item

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

PS D:\workspace\langs\powershell> Get-Item .\HelloWorld.ps1


    目录: D:\workspace\langs\powershell


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        2018/7/19     23:01            158 HelloWorld.ps1

过滤文件

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

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

PS D:\workspace\langs\powershell> ls


    目录: D:\workspace\langs\powershell


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        2018/7/19     23:25              8 a.txt
-a----        2018/7/19     23:01            158 HelloWorld.ps1


PS D:\workspace\langs\powershell> Get-ChildItem *.txt


    目录: D:\workspace\langs\powershell


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        2018/7/19     23:25              8 a.txt

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

下面同样是查找所有.txt格式的文件,不过这次使用了Where-Object和正则表达式,其中Where-Object里面的$_是形式变量,代表每次迭代的文件。

PS D:\workspace\langs\powershell> Get-ChildItem|Where-Object {$_ -match '\w*.txt$'}


    目录: D:\workspace\langs\powershell


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        2018/7/19     23:25              8 a.txt

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

# a.txt没有5kb被过滤
PS D:\workspace\langs\powershell> Get-ChildItem|Where-Object {$_ -match '\w*.txt$' -and $_.Length/1kb -gt 5}
# 再试一次 有结果了
PS D:\workspace\langs\powershell> Get-ChildItem|Where-Object {$_ -match '\w*.txt$' -and $_.Length/1kb -gt 0}


    目录: D:\workspace\langs\powershell


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        2018/7/19     23:25              8 a.txt

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

例如:

PS C:\Program Files> cd 'C:\Program Files\internet explorer\'
PS C:\Program Files\internet explorer> Get-ChildItem -Recurse -Depth 2 *.exe


    目录: C:\Program Files\internet explorer


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        2018/4/12      7:33          52736 ExtExport.exe
-a----        2018/4/12      7:33         513536 iediagcmd.exe
-a----        2018/4/12      7:33         498176 ieinstal.exe
-a----        2018/4/12      7:33         223232 ielowutil.exe

进程管理

查看进程

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

PS D:\workspace\langs\powershell> 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 D:\workspace\langs\powershell> Get-Process

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    242      15     4160      21960       0.28   7040   4 ApplicationFrameHost
    157       8     1744       4316              2212   0 AppVShNotify
    149       9     1360       4080              3724   0 armsvc
    254      13    11428      18212       1.00   7728   0 audiodg

    ......

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

PS D:\workspace\langs\powershell> Get-Process firefox|Sort-Object cpu -Descending|Select-Object -First 3

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    632     106   526492     496964     277.56   1396   4 firefox
   1424     111   217820     263360     118.73   4432   4 firefox
    433      20    34364      58360      58.64  12004   4 firefox

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

管理进程

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

PS D:\workspace\langs\powershell> notepad;notepad;notepad;
PS D:\workspace\langs\powershell> $notepads=Get-Process -Name notepad
PS D:\workspace\langs\powershell> $notepads.Count
3
PS D:\workspace\langs\powershell> $notepads.Kill()

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

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

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

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

PS D:\workspace\langs\powershell> Get-Process powershell |Where-Object {$_.Id -ne $PID}|Stop-Process -PassThru

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    751      30    64972      75436       8.95   8184   4 powershell

与其他软件互操作

操作Excel

虽然Powershell可以通过COM接口和Office程序交互,不过最常用的还是操作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:\Desktop\hello.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的数据,然后将其转换为文本并输出,每个数据之间使用制表符\t分隔,注意Powershell中的转义字符使用的这个特殊字符。结果应该类似如下。

PS C:\Users\think\Desktop> 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
>> }
        1       2       3       4       5       6       7       8       9
1       1       2       3       4       5       6       7       8       9
2       2       4       6       8       10      12      14      16      18
3       3       6       9       12      15      18      21      24      27
4       4       8       12      16      20      24      28      32      36
5       5       10      15      20      25      30      35      40      45
6       6       12      18      24      30      36      42      48      54
7       7       14      21      28      35      42      49      56      63
8       8       16      24      32      40      48      56      64      72
9       9       18      27      36      45      54      63      72      81

附上代码:

excel.ps1

$excel = New-Object -ComObject Excel.Application
$excel.Visible=$true
$workbook = $excel.Workbooks.Add()
$worksheet = $workbook.Worksheets.Item(1)
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
    }
}


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
}
相关标签: PowerShell