使用powershell管理进程和服务(翻译自官方文档7.1 Managing Processes and Services)

01.使用process cmdlet管理进程

001.获取进程信息(Get-Process)

使用这个命令可以获得进程信息,你也可以指定名字或者进程id来指定获取信息的进程。

PS> Get-Process -id 0

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
      0       0        0         16     0               0 Idle

指定属性的时候,如果找不到会报错。

如果指定名字,可以指定多个,并且支持通配符

PS> Get-Process -Name ex*

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    234       7     5572      12484   134     2.98   1684 EXCEL
    555      15    34500      12384   134   105.25    728 explorer

更复杂一些的命令是加上机器名,并且用规范的格式输出

PS> Get-Process powershell -ComputerName localhost, Server01, Server02 |
    Format-Table -Property Handles,
        @{Label="NPM(K)";Expression={[int]($_.NPM/1024)}},
        @{Label="PM(K)";Expression={[int]($_.PM/1024)}},
        @{Label="WS(K)";Expression={[int]($_.WS/1024)}},
        @{Label="VM(M)";Expression={[int]($_.VM/1MB)}},
        @{Label="CPU(s)";Expression={if ($_.CPU -ne $()){$_.CPU.ToString("N")}}},
        Id, ProcessName, MachineName -auto

Handles  NPM(K)  PM(K) WS(K) VM(M) CPU(s)  Id ProcessName  MachineName
-------  ------  ----- ----- ----- ------  -- -----------  -----------
    258       8  29772 38636   130         3700 powershell Server01
    398      24  75988 76800   572         5816 powershell localhost
    605       9  30668 29800   155 7.11    3052 powershell Server02

002.终结进程 (Stop-Process)

可以使用名字来终结进程。

PS> Stop-Process -Name Idle
Stop-Process : Process 'Idle (0)' cannot be stopped due to the following error:
 Access is denied
At line:1 char:13
+ Stop-Process  <<<< -Name Idle

终结进程的能力取决于你的权限,有些进程无法被终结。

你也可以选择强制弹出确认提示,这个在你使用通配符匹配的时候会很有用。

PS> Stop-Process -Name t*,e* -Confirm
Confirm
Are you sure you want to perform this action?
Performing operation "Stop-Process" on Target "explorer (408)".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help
(default is "Y"):n
Confirm
Are you sure you want to perform this action?
Performing operation "Stop-Process" on Target "taskmgr (4072)".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help
(default is "Y"):n

复杂一点的进程操作,可以使用where来筛选执行对象,一个进程如果可以进行响应会返回true,可以利用这个性质,终结所有没有响应的应用

Get-Process | Where-Object -FilterScript {$_.Responding -eq $false} | Stop-Process

由于Stop-Process没有主机名选项ComputerName,所以远程停止其他电脑的进程,需要通过Invoke-Command来实现

Invoke-Command -ComputerName Server01 {Stop-Process Powershell}

003.终结所有其他powershell会话

PS> Get-Process -Name powershell | Where-Object -FilterScript {$_.Id -ne $PID} | Stop-Process -PassThru

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    334       9    23348      29136   143     1.03    388 powershell
    304       9    23152      29040   143     1.03    632 powershell
    302       9    20916      26804   143     1.03   1116 powershell
    335       9    25656      31412   143     1.09   3452 powershell
    303       9    23156      29044   143     1.05   3608 powershell
    287       9    21044      26928   143     1.02   3672 powershell

02.管理服务

001.获取服务信息

Get-Service -Name se*

Status   Name               DisplayName
------   ----               -----------
Running  seclogon           Secondary Logon
Running  SENS               System Event Notification
Stopped  ServiceLayer       ServiceLayer

远程获取其他电脑的服务信息

Get-Service -ComputerName Server01

002.获取依赖进程和被依赖服务

Get-Service有两个在服务管理上比较使用的参数

DependentServices 参数获取依赖服务的其他服务

RequiredServices获取一个服务所依赖的服务。

下面的例子是获取LanmanWorkstation这个服务所依赖的服务。

PS> Get-Service -Name LanmanWorkstation -RequiredServices

Status   Name               DisplayName
------   ----               -----------
Running  MRxSmb20           SMB 2.0 MiniRedirector
Running  bowser             Bowser
Running  MRxSmb10           SMB 1.x MiniRedirector
Running  NSI                Network Store Interface Service

下面的命令获取依赖LanmanWorkstation的服务

PS> Get-Service -Name LanmanWorkstation -DependentServices

Status   Name               DisplayName
------   ----               -----------
Running  SessionEnv         Terminal Services Configuration
Running  Netlogon           Netlogon
Stopped  Browser            Computer Browser
Running  BITS               Background Intelligent Transfer Ser...

你甚至可以获取所有有依赖的服务。

Get-Service -Name * | Where-Object {$_.RequiredServices -or $_.DependentServices} |
  Format-Table -Property Status, Name, RequiredServices, DependentServices -auto

003.停止,开始,挂起,和重启服务

Stop-Service -Name spooler
Start-Service -Name spooler
Suspend-Service -Name spooler
Restart-Service -Name spooler

03.管理Windows PowerShell Drives

Windows PowerShell Drives是一种数据存储位置,可以像访问磁盘驱动器一样进行访问。

里面为你创建了一些驱动器,比如c盘,d盘,还有注册表驱动器,证书驱动器等。

你也可以创建你自己的驱动器,但是这些驱动器只能在powershell中进行访问。资源管理器或者cmd中无法访问。

专有名词是PSDrive

PS> Get-PSDrive

Name       Provider      Root                                   CurrentLocation
----       --------      ----                                   ---------------
A          FileSystem    A:\
Alias      Alias
C          FileSystem    C:\                                 ...And Settings\me
cert       Certificate   \
D          FileSystem    D:\
Env        Environment
Function   Function
HKCU       Registry      HKEY_CURRENT_USER
HKLM       Registry      HKEY_LOCAL_MACHINE
Variable   Variable

使用Get-Command命令查看语法

PS> Get-Command -Name Get-PSDrive -Syntax

Get-PSDrive [[-Name] ] [-Scope ] [-PSProvider ] [-V
erbose] [-Debug] [-ErrorAction ] [-ErrorVariable ] [-
OutVariable ] [-OutBuffer ]

PSProvider 参数允许你选择特定的provider类型。

PS> Get-PSDrive -PSProvider FileSystem

Name       Provider      Root                                   CurrentLocation
----       --------      ----                                   ---------------
A          FileSystem    A:\
C          FileSystem    C:\                           ...nd Settings\PowerUser
D          FileSystem    D:\

你也可以使用常用的路径操作命令

PS> Set-Location HKLM:\SOFTWARE
PS> Push-Location .\Microsoft
PS> Get-Location

Path
----
HKLM:\SOFTWARE\Microsoft

001.添加新的Windows PowerShell Drives (New-PSDrive)

创建一个新的 Windows PowerShell drive,需要提供三个参数

  • 驱动器的名字
  • PSProvider,比如文件系统类型或者注册表类型
  • 根路径的位置

比如创建一个名叫Office的新驱动器,映射一个文件夹,里面用于存放Office应用,

PS> New-PSDrive -Name Office -PSProvider FileSystem -Root "C:\Program Files\Microsoft Office\OFFICE11"

Name       Provider      Root                                   CurrentLocation
----       --------      ----                                   ---------------
Office     FileSystem    C:\Program Files\Microsoft Offic...

注意:路径是大小写不敏感的。

Windows PowerShell drive可以简化一些任务,举个例子,一些注册表的键值可能有很长的路径。

创建powershell驱动器可以简化这些路径

比如

PS> New-PSDrive -Name cvkey -PSProvider Registry -Root HKLM\Software\Microsoft\Windows\CurrentVersion

Name       Provider      Root                                   CurrentLocation
----       --------      ----                                   ---------------
cvkey      Registry      HKLM\Software\Microsoft\Windows\...

你可以在其他任何驱动器访问这个新建的驱动器

cd cvkey:

或者

PS> Set-Location cvkey: -PassThru

Path
----
cvkey:\

注意这个新建的驱动器只在当前会话中存在,关闭当前powershell窗口,这个新建的驱动器就会丢失。

如果想要永久保存这个驱动器,可以使用 Export-Console命令导出当前的powershell会话,

然后使用PowerShell.exe PSConsoleFile参数来导入这个会话文件,或者也可以写入powershell'的profile中。

002.删除Windows PowerShell Drivess(Remove-PSDrive)

Remove-PSDrive -Name Office

04.处理网络任务

001.获取电脑的IP地址

如果是获取本机的ip地址,执行以下命令

 Get-CimInstance -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=$true |
  Select-Object -ExpandProperty IPAddress

002.获取IP配置数据

获取每个网络适配器详细的ip配置信息,执行:

Get-CimInstance -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=$true

默认的输出格式比较难以查看,使用Select-Object或者 Format-List来指定显示的属性

现代TCP/IP 网络上,你可能不会对 IPX或者WINS属性感兴趣,可以排除掉这些属性

Get-CimInstance -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=$true |
  Select-Object -ExcludeProperty IPX*,WINS*

003.ping

可以使用Win32_PingStatus实现ping另一台电脑的功能

Get-CimInstance -Class Win32_PingStatus -Filter "Address='127.0.0.1'"

一个比较好的信息总结需要显示地址,响应时间和状态码属性,执行Format-Table命令来格式化输出

Get-CimInstance -Class Win32_PingStatus -Filter "Address='127.0.0.1'" |
  Format-Table -Property Address,ResponseTime,StatusCode -Autosize
Address   ResponseTime StatusCode
-------   ------------ ----------
127.0.0.1            0          0

StatusCode 值为0表示一个成功的ping

你也可以使用数组去ping多台电脑

'127.0.0.1','localhost','research.microsoft.com' |
  ForEach-Object -Process {
    Get-CimInstance -Class Win32_PingStatus -Filter ("Address='$_'") |
      Select-Object -Property Address,ResponseTime,StatusCode
  }

可以用同样形式的命令ping一个网络的所有子网

1..254| ForEach-Object -Process {
  Get-CimInstance -Class Win32_PingStatus -Filter ("Address='192.168.1.$_ '") } |
    Select-Object -Property Address,ResponseTime,StatusCode

004.获取网络适配器信息

Get-CimInstance -Class Win32_NetworkAdapter -ComputerName .

005.给网络适配器更换DNS地址

需要用到Win32_NetworkAdapterConfigurationSetDNSDomain 方法

Get-CimInstance -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=$true |
  ForEach-Object -Process { $_.SetDNSDomain('fabrikam.com') }

IPEnabled属性是必要的,因为即使再一个只使用TCP/IP的网络上也会有一些不是TCP/IP的网络适配器。

也可以使用where进行过滤

Get-CimInstance -Class Win32_NetworkAdapterConfiguration |
  Where-Object {$_.IPEnabled} |
    ForEach-Object -Process {$_.SetDNSDomain('fabrikam.com')}

006.执行DHCP配置任务

寻找开启DHCP的网络适配器

Get-CimInstance -Class Win32_NetworkAdapterConfiguration -Filter "DHCPEnabled=$true"

再配置IP设置有问题的配置器

Get-CimInstance -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled=$true and DHCPEnabled=$true"

获取DHCP属性

因为DHCP相关的属性通常是DHCP开头的,所以

Get-CimInstance -Class Win32_NetworkAdapterConfiguration -Filter "DHCPEnabled=$true" |
  Format-Table -Property DHCP*

开启每个适配器的DHCP

Get-CimInstance -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=$true |
  ForEach-Object -Process {$_.EnableDHCP()}

可以用Filter 筛选掉那些已经启动DHCP的。

在特定适配器上Releasing 或者 Renewing DHCP协议

Get-CimInstance -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled=$true and DHCPEnabled=$true" |
  Where-Object {$_.DHCPServer -contains '192.168.1.254'} |
    ForEach-Object -Process {$_.ReleaseDHCPLease()}

在所有适配器上Releasing 或者 Renewing DHCP协议

通过列出所有WMI类,然后根据名字选择需要的类,就可以返回一个Win32_NetworkAdapterConfiguration 类而不是实例。

Get-CimInstance -List | Where-Object {$_.Name -eq 'Win32_NetworkAdapterConfiguration'}

你可以把整个命令当作一个class,然后调用ReleaseDHCPAdapterLease 方法,

(Get-CimInstance -List |
  Where-Object {$_.Name -eq 'Win32_NetworkAdapterConfiguration'}).ReleaseDHCPLeaseAll()

同样的形式,可以调用RenewDHCPLeaseAll 方法

007.创建网络共享

(Get-CimInstance -List |
  Where-Object {$_.Name -eq 'Win32_Share'}).Create(
    'C:\temp','TempShare',0,25,'test share of the temp folder'
  )

windows平台也可以使用 net share命令

net share tempshare=c:\temp /users:25 /remark:"test share of the temp folder"

008.移除网络共享

(Get-CimInstance -Class Win32_Share -Filter "Name='TempShare'").Delete()

or(windows only)

net share tempshare /delete

009.连接windows可访问网络驱动器

之前讲了New-PSDrive创建一个powershell驱动器,如果需要通过网络访问驱动器可以使用WScript.Network COM object

执行以下命令把\FPS01\users 映射到b驱动器

(New-Object -ComObject WScript.Network).MapNetworkDrive('B:', '\\FPS01\users')

windows平台下可以使用net use

net use B: \\FPS01\users

05.软件安装

001.列出windows installer应用

Get-CimInstance -Class Win32_Product |
  Where-Object Name -eq "Microsoft .NET Core Runtime - 2.1.5 (x64)"

这条命令执行还是比较慢的。

Get-CimInstance -Class Win32_Product |
  Where-Object Name -eq "Microsoft .NET Core Runtime - 2.1.5 (x64)" |
    Format-List -Property *

002.列出所有能卸载的应用

因为大多数标准应用都注册了卸载程序,可以从下面这个注册表里面找到

New-PSDrive -Name Uninstall -PSProvider Registry -Root HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

查看卸载程序的数目

(Get-ChildItem -Path Uninstall:).Count

列表用变量保存

$UninstallableApplications = Get-ChildItem -Path Uninstall:

显示名称

$UninstallableApplications | ForEach-Object -Process { $_.GetValue('DisplayName') }

查询特定

$UninstallableApplications | Where-Object -FilterScript {
  $_.GetValue("DisplayName") -eq "Microsoft Silverlight"
}

003.安装应用

可以使用Win32_Product类安装应用,当然需要管理员权限。

Invoke-CimMethod -ClassName Win32_Product -MethodName Install -Arguments @{PackageLocation='\\AppSrv\dsp\NewPackage.msi'}

004.删除应用

Get-CimInstance -Class Win32_Product -Filter "Name='ILMerge'" | Invoke-CimMethod -MethodName Uninstall

可以通过删除字符串找到可以删除的程序

Get-ChildItem -Path Uninstall: | ForEach-Object -Process { $_.GetValue('UninstallString') }
Get-ChildItem -Path Uninstall: |
    Where-Object -FilterScript { $_.GetValue('DisplayName') -like 'Win*'} |
        ForEach-Object -Process { $_.GetValue('UninstallString') }

005.升级Windows Installer应用

Get-CimInstance -Class Win32_Product -Filter "Name='OldAppName'" |
  Invoke-CimMethod -MethodName Upgrade -Arguments @{PackageLocation='\\AppSrv\dsp\OldAppUpgrade.msi'}

06.解码正在运行的powershell脚本

有时,我们会运行一些占用大量资源的powershell程序。当由多个powershell程序运行的时候,很难判断哪个程序出了问题。下面我们就展示如何从一个运行的powershell进程中解码代码块

001.创建一个运行时长比较长的进程

下面这个程序会每分钟输出一个数字,持续10分钟

powershell.exe -Command {
    $i = 1
    while ( $i -le 10 )
    {
        Write-Output -InputObject $i
        Start-Sleep -Seconds 60
        $i++
    }
}

002.查看进程

执行的命令体会被存储在Win32_Process类的属性上,并且命令被编码了。依据这一信息我们可以用下面的步骤反混淆

以管理员模式打开powershell,执行下面的命令

获取到编码过的命令

$powerShellProcesses = Get-CimInstance -ClassName Win32_Process -Filter 'CommandLine LIKE "%EncodedCommand%"'

下面的步骤创建一个传统的powershell对象包括进程id和编码的命令

$commandDetails = $powerShellProcesses | Select-Object -Property ProcessId,
@{
    name       = 'EncodedCommand'
    expression = {
        if ( $_.CommandLine -match 'encodedCommand (.*) -inputFormat' )
        {
            return $matches[1]
        }
    }
}

然后编码的命令就能被解码了。

下面的代码片段,遍历命令对象,解码被编码的命令,将解码后的命令加回该对象,供进一步研究

$commandDetails | ForEach-Object -Process {
    # Get the current process
    $currentProcess = $_

    # Convert the Base 64 string to a Byte Array
    $commandBytes = [System.Convert]::FromBase64String($currentProcess.EncodedCommand)

    # Convert the Byte Array to a string
    $decodedCommand = [System.Text.Encoding]::Unicode.GetString($commandBytes)

    # Add the decoded command back to the object
    $commandDetails |
        Where-Object -FilterScript { $_.ProcessId -eq $_.ProcessId } |
        Add-Member -MemberType NoteProperty -Name DecodedCommand -Value $decodedCommand
}
$commandDetails[0]

查看会是下面的样子。

ProcessId      : 8752
EncodedCommand : IAAKAAoACgAgAAoAIAAgACAAIAAkAGkAIAA9ACAAMQAgAAoACgAKACAACgAgACAAIAAgAHcAaABpAGwAZQAgACgAIAAkAGkAIAAtAG
                 wAZQAgADEAMAAgACkAIAAKAAoACgAgAAoAIAAgACAAIAB7ACAACgAKAAoAIAAKACAAIAAgACAAIAAgACAAIABXAHIAaQB0AGUALQBP
                 AHUAdABwAHUAdAAgAC0ASQBuAHAAdQB0AE8AYgBqAGUAYwB0ACAAJABpACAACgAKAAoAIAAKACAAIAAgACAAIAAgACAAIABTAHQAYQ
                 ByAHQALQBTAGwAZQBlAHAAIAAtAFMAZQBjAG8AbgBkAHMAIAA2ADAAIAAKAAoACgAgAAoAIAAgACAAIAAgACAAIAAgACQAaQArACsA
                 IAAKAAoACgAgAAoAIAAgACAAIAB9ACAACgAKAAoAIAAKAA==
DecodedCommand :
                     $i = 1

                     while ( $i -le 10 )

                     {

                         Write-Output -InputObject $i

                         Start-Sleep -Seconds 60

                         $i++

                     }

你可能感兴趣的:(使用powershell管理进程和服务(翻译自官方文档7.1 Managing Processes and Services))