PowerShell 技能连载 - 在 PowerShell 中提升命令权限

有些时候,一个脚本需要运行一个需提升(管理员)权限的命令。

一种方法是将用管理员权限运行整个脚本,另一种方法是将独立的命令送到提升权限的 shell 中执行。

这段代码将重启 Spooler 服务(需要提升权限),并将命令发送到另一个 PowerShell 进程中。如果当前进程没有管理员权限,它将自动提升权限。

$command = 'Restart-Service -Name spooler'
Start-Process -FilePath powershell.exe -ArgumentList "-noprofile -command $Command" `
-Verb runas

PowerShell 技能连载 - 获取无线网卡

在上一个技巧中,我们演示了如何使用注册表信息来查找无线网卡。以下是一个可以返回您系统中所有无线网卡的 Get-WirelessAdapter 函数:

function Get-WirelessAdapter
{
  Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Network\*\*\Connection' -ErrorAction SilentlyContinue |
    Select-Object -Property MediaSubType, PNPInstanceID |
    Where-Object { $_.MediaSubType -eq 2 -and $_.PnpInstanceID } |
    Select-Object -ExpandProperty PnpInstanceID |
    ForEach-Object {
      $wmipnpID = $_.Replace('\', '\\')
      Get-WmiObject -Class Win32_NetworkAdapter -Filter "PNPDeviceID='$wmipnpID'"
    }
}

只需要运行该函数:

由于该函数返回一个 WMI 对象,所以您可以获知该网卡当前是否是活动的,或者启用禁用它。

以下代码将取出网卡对象,然后禁用它,再启用它:

$adapter = Get-WirelessAdapter
$adapter.Disable().ReturnValue
$adapter.Enable().ReturnValue

请注意返回值 5 意味着您没有足够的权限。请以管理员身份运行该脚本。

PowerShell 技能连载 - 查找无线网卡

有很多方法可以查找网卡,但似乎没有办法识别活动的无线网卡。

您网卡的所有信息都可以在注册表中找到,以下是一个单行的代码,可以提供您想要的信息:

有趣的部分是 MediaSubType 值。无线网卡的 MediaSubType 值总是 2。

所以这行代码只返回无线网卡:

PowerShell 技能连载 - 以 GB 和百分比的形式显示驱动器容量

当一个 cmdlet 返回原始数据时,您可能希望将数据转换为一个更好的格式。例如,WMI 可以汇报驱动器的剩余空间,但是是以字节为单位的。

您可以使用 Select-Object 并且传入一个哈希表来将原始数据转换为您希望的格式。这个例子演示了如何将剩余空间转换为以 GB 为单位,并且计算剩余空间的百分比:

$Freespace =
@{
  Expression = {[int]($_.Freespace/1GB)}
  Name = 'Free Space (GB)'
}

$PercentFree =
@{
  Expression = {[int]($_.Freespace*100/$_.Size)}
  Name = 'Free (%)'
}

Get-WmiObject -Class Win32_LogicalDisk |
  Select-Object -Property DeviceID, VolumeName, $Freespace, $PercentFree

以下是不使用哈希表的结果:

这是使用了哈希表的结果:

PowerShell 技能连载 - 查找空闲容量低的硬盘驱动器

可以通过 WMI 轻松地获取驱动器信息。以下代码可以从您的本地计算机中获取驱动器信息(用 -ComputerName 可以存取远程系统的信息)。

要限制结果只包含硬盘驱动器,并且只包含空闲容量低于指定值的硬盘驱动器,请试试以下代码:

$limit = 80GB
Get-WmiObject -Class Win32_LogicalDisk -Filter "DriveType=3 and Freespace<$limit" |
  Select-Object -Property VolumeName, Freespace, DeviceID

PowerShell 技能连载 - 查找昨天以来的错误

要获取一个时间段内的数据,相对日期的作用十分重要,它能避免硬编码日期和时间值。

这段代码将会从系统日志中获取昨天起(24 小时以内)的所有错误和警告事件:

$today = Get-Date
$1day = New-TimeSpan -Days 1

$yesterday = $today - $1day

Get-EventLog -LogName system -EntryType Error, Warning -After $yesterday

PowerShell 技能连载 - 导出数据到 Excel

您可以轻松地在 PowerShell 中将对象数据转化为 CSV 文件。以下代码生成当前进程的 CSV 报告:

要在 Microsoft Excel 中打开 CSV 文件,您可以使用 Invoke-Item 来打开文件,但是这仅当您的 CSV 文件扩展名确实关联到 Excel 应用程序的时候才有效。

以下代码将确保在 Microsoft Excel 中打开 CSV 文件。它展示了一种超出您 Excel 应用(假设它已经安装了,并且无须检测它是否存在)的方法:

$report = "$env:temp\report.csv"
$ExcelPath = 'C:\Program Files*\Microsoft Office\OFFICE*\EXCEL.EXE'
$RealExcelPath = Resolve-Path -Path $ExcelPath | Select-Object -First 1 -ExpandProperty Path
& $RealExcelPath $report

PowerShell 技能连载 - 查找一个时间点附近的日志

经常地,您会需要浏览某个指定日期附近的所有系统事件。我们假设某台机器在 08:47 崩溃了,您需要查看该时间前后 2 分钟之内的事件。

以下是一个完成以上任务的脚本:

$deltaminutes = 2
$delta = New-TimeSpan -Minutes $deltaminutes

$time = Read-Host -Prompt 'Enter time of event (yyyy-MM-dd HH:mm:ss or HH:mm)'

$datetime = Get-Date -Date $time
$start = $datetime - $delta
$end = $datetime + $delta

$result = @(Get-EventLog -LogName System -Before $end -After $start)
$result += Get-EventLog -LogName Application -Before $end -After $start

$result | Sort-Object -Property TimeGenerated -Descending |
  Out-GridView -Title "Events +/− $deltaminutes minutes around $datetime"

当您运行它时,它需要用户输入一个时间或日期 + 时间值。然后,您可以获得该时间点前后 2 分钟之内系统和应用程序日志中的所有事件。

如果您没有获取到任何数据,那么说明在这段时间段中没有任何事件。

这段代码示范了您可以获取一个时间段之内的事件,并且示范了如何查询多个事件日志。

PowerShell 技能连载 - 自动连接到公共热点

许多手机服务提供商在机场和公共场所提供公共热点。要连接热点,您往往需要浏览一个登录页面,然后手动输入您的凭据。

以下是一个自动做以上事情的脚本。它在 t-mobile.de 运营商环境下调是通过。但是您可以调整脚本以适应其它的运营商。

function Start-Hotspot
{
  param
  (
    [System.String]
    $Username = 'XYZ@t-mobile.de',

    [System.String]
    $Password = 'topsecret'
  )

  # change this to match your provider logon page URL
  $url = 'https://hotspot.t-mobile.net/wlan/start.do'

  $r = Invoke-WebRequest -Uri $url -SessionVariable fb

  $form = $r.Forms[0]

  # change this to match the website form field names:
  $form.Fields['username'] = $Username
  $form.Fields['password'] = $Password

  # change this to match the form target URL
  $r = Invoke-WebRequest -Uri ('https://hotspot.t-mobile.net' + $form.Action) -WebSession $fb -Method POST -Body $form.Fields
  Write-Host 'Connected' -ForegroundColor Green
  Start-Process 'http://www.google.de'
}

简而言之,Invoke-WebRequest 可以到导航到一个页面,填充表单数据,然后提交表单。要能提交正确的数据,您需要查看登录网页的的源代码(导航到该页面,在浏览器中右键单击选择显示 HTML 源代码)。

然后,识别出您希望填充的表单,然后将脚本代码中的表单名称和动作改为您从 HTML 代码中识别出来的值。

PowerShell 技能连载 - 字符串左右对齐

如果您需要确保给定的字符串有一致的宽度,那么您可以使用 .NET 方法来适当地对齐字符串:

$mytext = 'Test'

$paddedText = $mytext.PadLeft(15)
"Here is the text: '$paddedText'"

$paddedText = $mytext.PadRight(15)
"Here is the text: '$paddedText'"

以下是结果:

您甚至可以自己指定补充的字符(如果您不想使用空格来补的话):