在PowerShell中操作Word - 使用格式化样式

在这个系列的上一步中,我们演示了用Windows PowerShell创建Microsoft Word文档的基本步骤。如果您试用了我的示例脚本,您会注意到文档格式化方面略有不足。幸运的是,我们有一些简洁的办法来改进您文档的质量,我将会在这篇文章中向您演示这个过程。我们将用第一部分的脚本作为起点。

关键之处在于 Selection 对象。

PS C:\>$word=new-object -ComObject "Word.Application"
PS C:\>$doc=$word.documents.Add()
PS C:\> $selection=$word.Selection

您可以更改 Selection 对象的一个重要元素是 Font。您可以轻松地修改字体大小和颜色,以及使用哪种字体。我将把日期和时间的字体改为绿色。

PS C:\> $selection.Font.Color="wdColorGreen"
PS C:\> $selection.TypeText((Get-Date))

在VBScript的年代中,我们需要定义 wdColorGreen 的值并将它赋给一个常量。但是在PowerShell中我们可以轻松地以字符串的形式插入这个常量。您一定很好奇有哪些颜色可以使用?问问PowerShell吧:

PS C:\> [enum]::GetNames([microsoft.office.interop.word.wdcolor])

您需要把字体颜色改回来,除非您需要把整个文档设为这个颜色。

PS C:\ >$selection.font.Color="wdColorAutomatic"
PS C:\> $selection.TypeParagraph()

在我原先的脚本中我插入了一个标题。现在我们把它变成大一点的字体。我将用我上次使用的WMI代码。

$selection.Font.Size=12
$selection.TypeText("Operating System Information for $($os.CSName)")

回顾一下前面一篇文章,有一个问题是PowerShell输出到Word早期是用等宽字体而后来用的是非等宽字体。解决方法是从PowerShell中插入结果之前指定一个合适的字体。

PS C:\> $selection.Font.Size=10
PS C:\> $selection.Font.Name="Consolas"
PS C:\> $selection.TypeText(($os | Select -Property $props | Out-String))

还要做的最后一件事是添加一段格式化的文本,说明报告的创建者。我希望采用Word的斜体格式来呈现。

PS C:\> $selection.Font.size=8
PS C:\> $selection.Font.Name="Calibri"
PS C:\> $selection.Font.Italic=$True
PS C:\> $by="Report created by $env:userdomain\$env:username"
PS C:\> $selection.TypeText($by)

我相信您一定也掌握了如何使文本变成粗体。

除了指定字体之外,您还可以采用Word内置的样式。

$selection.Style="Title"
$selection.TypeText("Operating System Report")
$selection.TypeParagraph()

您可以用PowerShell查询 Document 对象,看看有哪些样式可以用。

$doc.Styles | select NameLocal

大多数这些样式只能应用在文本的第一行,不过您也可以自己做实验调整一下。

通过这些步骤您可以简洁地通过您的PowerShell脚本创建一个漂亮的Word文档。请下载版本修订过的脚本,New-WordDoc2,并且自己做一下实验。

用PowerShell操作Office系列文章

Visual Studio的PowerShell扩展工具

Visual Studio的PowerShell扩展工具为Visual Studio 2012和2013 RC增加了PowerShell语言支持。

本工具目前为BETA版。

下载地址:Visual Studio工具库
开源项目:GitHub

必须条件:

编辑器扩展

语法高亮、智能感知和代码折叠

Syntax highlighting, IntelliSense and code folding

方法导航

Function navigation

调试器扩展

脚本输出

Script Output

断点支持

Breakpoint Support

本地变量支持

Locals Support

调用堆栈支持

Stack Frame Support

工程系统支持

Project System Support

在PowerShell中操作Word - 生成文档

我假设许多读者用PowerShell生成服务器、事件以及Windows网络上各种数据的报表。您也许创建过纯文本文件,甚至漂亮的HTML报表。但是您也可以用上Microsoft Word,当然,前提是您已经安装了Word。在这个系列的第二部分,我将会向您演示如何用PowerShell为Word文档套用样式

创建Word应用程序对象

PowerShell可以通过COM接口控制Word应用程序。有趣的地方是,虽然您可以交互式地做所有的操作,但我希望您最终能够用脚本操作一切。我们从创建一个Word程序对象开始。

PS C:\> $word=new-object -ComObject "Word.Application"

如果您好奇的话,可以将这个对象输出到 Get-Member 命令。我们将创建一系列对象,您可以将每一个对象通过管道输出到 Get-Member 来探索它们。

下一步,我们创建一个文档对象。

PS C:\> $doc=$word.documents.Add()

现在,Word程序已经启动,并且创建了一个新文档,但是您在屏幕上看不到任何东西。通常这是正常的,因为我们需要它在后台运行。但是如果您想查看所创建的文档,您需要将应用程序的 Visible 属性设置为 True

PS C:\> $word.Visible=$True

在我们插入文本之前,我们需要获取焦点。创建一个 Selection 对象可以帮我们做一些诸如设置字体大小和颜色等操作,我们将在第二部分介绍这些操作。

PS C:\> $selection=$word.Selection

用PowerShell在文档中插入文本

现在光标在文档的顶部,现在可以开始插入文本了。我们将用 Selection 对象的 TypeText() 方法插入当前的日期和时间。

PS C:\> $selection.TypeText((Get-Date))

如果我们继续插入文本,那么文本将会紧挨在日期的后面。现在我们用 TypeParagraph() 方法插入一个回车符。

PS C:\> $selection.TypeParagraph()

让我们继续插入一些文本。我将用WMI获取本地计算机的操作系统信息。

PS C:\> $os=Get-WmiObject -class win32_OperatingSystem
PS C:\> $selection.TypeText("Operating System Information for $($os.CSName)")

由于我希望写入所有的非系统属性,所以我将快速递创建一个数组用来保存所有的属性名。

PS C:\> $os.properties | select Name | foreach -begin {$props=@()} -proc {$props+="$($_.name)"}

现在我可以从 $os 获取所有的属性并插入Word文档。很重要的一点是 TypeText() 的值是字符串型的,所以我需要将内联的PowerShell表达式通过管道输出到 Out-String

PS C:\> $selection.TypeText(($os | Select -Property $props | Out-String))

如果需要的话,还可以继续插入文字和图片。当完成操作以后,我将保存并关闭文档。

PS C:\> $doc.SaveAs([ref]"c:\work\osreport.docx")
PS C:\> $doc.Close()

请确认使用 [ref] 为文件路径转换数据类型。假设我不再创建新的文档,那么剩下的就是关闭Word应用程序。

PS C:\> $word.quit()

这些就是要做的所有事情。最终生成的Word文档是可用的,虽然可能不太漂亮。在我的例子中发现一个问题:Word用的事非等宽字体,而PowerShell的输出格式假设用的是等宽字体。(译者注:可能会造成输出的结果对不整齐)。在第二部分,我将向您演示如何解决这些问题。同时,欢迎下载示例脚本 New-WordDoc.ps1

用PowerShell操作Office系列文章

PowerShell 技能连载 - 设置显示器亮度

如果您的显示驱动程序支持WMI,那么您可以用PowerShell改变显示器的亮度——甚至是远程的计算机!

以下是实现改变显示器亮度的函数:

function Set-MonitorBrightness
{
    param
    (
        [Parameter(Mandatory=$true)]
        [Int][ValidateRange(0,100)]
        $Value,

        $ComputerName,
        $Credential
    )

    $null = $PSBoundParameters.Remove('Value')

    $helper = Get-WmiObject -Namespace root/WMI -Class WmiMonitorBrightnessMethods @PSBoundParameters
    $helper.WmiSetBrightness(1, $Value)
}

只需要指定一个0-100之间的值,您就可以看到显示器亮度发生改变。为 -ComputerName 参数指定远程计算机名或IP地址(均支持多个),然后您远程的同事们会惊讶地发现去吃午餐的时候显示器都变暗了!当然,远程操作WMI需要本地管理员权限,并且为防火墙设置了允许远程管理的规则。

如果提示“不支持”的错误提示信息,那么说明您的显示驱动程序不支持WMI。

这是“有趣”的部分:模拟一个古怪的显示效果:

for($x=0; $x -lt 20; $x++)
{
    Set-MonitorBrightness -Value (Get-Random -Minimum 20 -Maximum 101)
    Start-Sleep -Seconds 1
}

PowerShell 技能连载 - 检测显示器亮度

如果您想检查您当前的显示器亮度(当然,尤其是针对笔记本电脑),以下是一个快捷的函数:

function Get-MonitorBrightness
{
    param($ComputerName, $Credential)

    Get-WmiObject -Namespace root/WMI -Class WmiMonitorBrightness @PSBoundParameters |
        Select-Object -Property PSComputerName, CurrentBrightness, Levels
}

它甚至支持 -ComputerName-Credential,所以您也可以查询远程的主机。

如果您为 -ComputerName 参数传入一个用逗号分隔的主机名或IP地址列表,您将获得所有具有local Admin权限的主机的执行结果。

PowerShell 技能连载 - 创建符号链接

符号链接使用起来很像“普通”的链接文件(*.lnk):它们可以虚拟地指向任何文件或者文件夹,甚至UNC路径。和lnk文件不同的是,创建符号链接需要完整管理员权限,并且用户不可以存取符号链接属性。

以下是一个创建符号链接的函数:

function New-SymbolicLink
{
    param
    (
        [Parameter(Mandatory=$true)]
        $OriginalPath,

        [Parameter(Mandatory=$true)]
        $MirroredPath,

        [ValidateSet('File', 'Directory')]
        $Type='File'
    )

    if(!([bool]((whoami /groups) -match "S-1-16-12288") ))
    {
        Write-Warning 'Must be an admin'
        break
    }
    $signature = '
        [DllImport("kernel32.dll")]
        public static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, int dwFlags);
        '
    Add-Type -MemberDefinition $signature -Name Creator -Namespace SymbolicLink

    $Flags = [Int]($Type -eq 'Directory')
    [SymbolicLink.Creator]::CreateSymbolicLink($MirroredPath, $OriginalPath,$Flags)
}

$downloads = "$env:userprofile\Downloads"
$desktop = "$env:userprofile\Desktop\MyDownloads"

New-SymbolicLink -OriginalPath $downloads -MirroredPath $desktop -Type Directory

当您(以管理员身份)运行这段代码时,它将使您能在桌面上访问下载文件夹。请右击符号链接并选择属性,并和“普通”的*.link文件做对比。

PowerShell 技能连载 - 检查管理员权限

以下通过一个非常规的办法实现检查一段脚本是否以管理员权限运行(通过提升UAC),这体现了PowerShell强大的灵活性:

function Test-Admin { [bool]((whoami /groups) -match "S-1-16-12288") }

它的基本原理是检查当前用户是否是高完整性级别用户组的成员。该用户组是专门针对提升权限的管理员设置的。

如果您不想使用本地命令(whoami.exe)的话,还可以使用更贴近PowerShell(或.NET)的方法,如以下代码所示:

function Test-Admin {

    $id = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())

    $id.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)

}

Clover 3 为您的 Windows Explorer 插上翅膀!

Clover 3为您的Windows Explorer插上翅膀!

Clover 是 Windows Explorer 资源管理器的一个扩展,为其增加类似谷歌 Chrome 浏览器的多标签页功能。

Clover 3

官方网站:易捷科技

Version:
3.0.386

Requirements:
Windows XP / Windows 7 / Windows 8

Language:
English / 简体中文 / 繁體中文 / 日本語 / Français / Español / Deutsch / Nederlands / Português

PowerShell 技能连载 - 创建硬连接

硬连接是NTFS文件系统中文件的“镜像”。它们使得一个文件能在多个文件系统位置(必须在一个卷中)中出现。

所以文件仅仅占用它的原始位置空间,但是在其它地方也可用。当您需要让大文件在多个地方可用的时候,这是一个十分有用的功能。

以下是 New-HardLink 函数的介绍。它演示了PowerShell如何调用底层的API函数:

function New-HardLink
{
    param
    (
        [Parameter(Mandatory=$true)]
        $OriginalFilePath,

        [Parameter(Mandatory=$true)]
        $MirroredFilePath
    )

    $signature = '
            [DllImport("Kernel32.dll")]
            public static extern bool CreateHardLink(string lpFileName,string lpExistingFileName,IntPtr lpSecurityAttributes);
    '
    Add-Type -MemberDefinition $signature -Name Creator -Namespace Link

    [Link.Creator]::CreateHardLink($MirroredFilePath,$OriginalFilePath,[IntPtr]::Zero)

}

以下是它的使用方法:

$Original = "$env:temp\testfile.txt"
$Copy1 = "$env:userprofile\Desktop\mirrorfile1.txt"
$Copy2 = "$env:userprofile\Desktop\mirrorfile2.txt"

# create original file:
Set-Content -Path $Original -Value 'Hello'

# create hard link #1:
New-HardLink -OriginalFilePath $Original -MirroredFilePath $Copy1

# create hard link #2:
New-HardLink -OriginalFilePath $Original -MirroredFilePath $Copy2

这段代码首先在临时文件夹中创建一个物理文件。然后在您的桌面上创建两个硬连接。它们看上去分别是mirrorfile1.txtmirrorfile2.txt。虽然它们看上去像是独立的文件,而实际上他们都指向刚创建的临时文件。

您可以打开桌面上两个文件中的某一个,做一些修改,然后保存并关闭。当打开另一个文件时,您可以看到一模一样的修改后的内容。您还可以简单地删掉一个镜像文件来移除硬连接。

用 PowerShell 处理纯文本 - 1

原始文本:”data1”:111,”data2”:22,”data3”:3,”data4”:4444444,”data5”:589
要求:转换成对象

方法一,采用字符串运算及 ConvertFrom-StringData 命令:

$rawTxt='"data1":111,"data2":22,"data3":3,"data4":4444444'
$rawTxt -split ',' | ForEach-Object {
   $temp= $_ -split ':'
   "{0}={1}" -f $temp[0].Substring(1,$temp[0].Length-2),$temp[1]
} | ConvertFrom-StringData

方法二,采用正则表达式,使用.NET的方法:

$rawTxt = '"data1":111,"data2":22,"data3":3,"data4":4444444,"data5":589'
$regex = [regex] '"(?<name>\w*)":(?<value>\d*),?'
$match = $regex.Match($rawTxt)
while ($match.Success) {
    [PSCustomObject]@{
        Name = $match.Groups['name'].Value
        Value = $match.Groups['value'].Value
    }
    $match = $match.NextMatch()
}

方法三,采用正则表达式,使用 Select-String Cmdlet:

Select-String -InputObject $rawTxt -Pattern $regex -AllMatches | % {
    $_.Matches
} | % {
   [PSCustomObject]@{
        Name = $_.Groups['name'].Value
        Value = $_.Groups['value'].Value
    }
}

三者的执行结果都是这样:

Name          Value
----          -----
data1         111
data2         22
data3         3
data4         4444444
data5         589

原命题参见:[PowerShell 文本处理实例(三)] 1