Windows PowerShell2-知识深入

文章目录

  • 介绍
  • Windows管理规范
    • 简单介绍
    • 选择你的武器:WMI或CIM
    • 使用Get-WmiObject
    • 使用Get-CimInstance
  • 多任务后台作业
    • 介绍
    • 创建本地作业
    • WMI作业和远程处理作业
    • 获取作业执行结果
    • 调度作业
  • 同时处理多个对象
    • 首先方法:“批处理” Cmdlet
    • CIMWMI方式:调用方法
    • 后备计划:枚举对象
  • 安全警报
    • 执行策略设置
    • 数字代码签名
    • 其他安全措施
  • 扩展命令
    • 扩展:找到并添加插件
    • 扩展:找到并添加模块
    • PowerShell模块的构成
    • 从Internet获取模块
  • 总结

介绍

PowerShell作为Windows系统中的默认脚本,其实在开发中,我们用的很少。接下来的几篇文章都将PowerShell的相关知识,在上一章中我们介绍了PowerShell基本的知识,本章我们将深入了解其相关知识。

Windows管理规范

简单介绍

在最顶层,Windows管理规范(Windows Management Instrumentation,WMI)被组织成命名空间(nampespace)。可以把命名空间想象为关联到特定产品或技术的一个文件夹。比如,“rootCIMv2”,该命名空间包含了所有Windows操作系统和计算机硬件信息。而“rootMicrosoftDNS”命名空间包含了所有关于DNS服务器的信息。在客户端计算机上,“rootSecurityCenter2”包含了关于防火墙、杀毒软件和反流氓软件等工具的信息。

在命名空间中,WMI被分成一系列的类,每个类都是可用于WMI查询的管理单元。下面看一个从“rootSecurityCenter2”中查询“AntiSpywareProduct”的例子。

Get-CimInstance -Namespace rootSecurityCenter2 -ClassName AntiSpywareProduct

要想很好的了解WMI,可以通过一个叫WMI explorer的工具来查看,下载地址为https://powershell.org/2013/03/wmi-explorer/。通过此工具可以方便的查看各个命名空间下的类,具体的属性等等。

在这里插入图片描述

选择你的武器:WMI或CIM

而在PowerShell v3及以后的版本中,有两种与WMI交互的方式。

  • 所谓的“WMI Cmdlets”,例如“Get-WmiObject”与“Invoke-WmiMethod”——这些都是遗留命令,意味着它们依旧能工作,但是微软不会对它们进行后续的开发投入。
  • 新版的“WMI Cmdlets”,例如“Get-CimInstance”与“Invoke-CimMethod”——它们或多或少等价于旧版本的“WMI Cmdlets”,但是它们通过WS-MAN(由Windows远程管理服务实现)交互,替代原有的RPCs。执行“Get-Command -noun CIM*”可显示很多微软提供的这些命令

使用Get-WmiObject

通过“Get-WmiObject”命令(别名是Gwmi),你可以指定一个命名空间、一个类名称甚至远程计算机的名称以及备用凭据名。如果需要,还可以从指定计算机中查询该类的所有实例。下面的语法获取一个命名空间的类列表。

Get-WmiObject -namespace rootcimv2 -list

注意:命名空间名称中使用的是反斜杠,不是斜杠

也可以通过指定命名空间和类型查询一个类。

Get-WmiObject -namespace rootcimv2 -list -class win32_desktop
Get-WmiObject win32_desktop

注意:“rootcimv2”命名空间是默认命名空间,“-class”是位置参数,所以上面两个命令结果一样

另外,“-filter”参数允许你通过指定的规则查询特定的实例。

Get-WmiObject win32_operatingsystem | gm
gwmi -class win32_desktop -filter "name='NT AUTHORITY\SYSTEM'"

在这里插入图片描述

对于该命令和输出结果,需要注意下面事项。

筛选条件通常被引号包住
筛选操作符并不使用PowerShell的常规操作符“-eq”和“-like”,而使用更加传统、更加编程化的操作符,比如=><<=>=<>。可以使用关键字“LIKE”作为操作符,但在匹配值时必须使用“%”作为字符通配符,如“NAME LIKE '%administrator%'”。注意,这里不能像PowerShell的其他地方一样使用“*”作为通配符
字符串匹配是以单引号包住,这也是筛选表达式的最外面的引号是双引号的原因
避免在WMI中使用反斜杠。如必须使用则使用两个反斜杠代替
Gwmi的输出结果总会包含大量系统属性,PowerShell的默认显示配置通常因此这些属性,系统属性名称以双下划线开始

一旦你查询到一个WMI实例的集合后,就可以把它们通过管道连接到任何以“-ObjectCmdlet、“FormatCmdlet或“Out-”、“Export-”、“ConvertTo-”开头的Cmdlet中。

gwmi -Class win32_bios -ComputerName DESKTOP-GT96S5L,localhost | 
Format-Table @{ label='ComputerName'; expression={$_.__SERVER}},
@{ label='BIOSSerial'; expression={$_.SerialNumber}},
@{ label='OSBuild'; expression={
    gwmi -Class win32_operatingsystem -ComputerName $_.__SERVER |
    Select-Object -ExpandProperty BuildNumber}
 } -AutoSize

使用Get-CimInstance

Get-CimInstancePowerShell v3引入的新命令,与“Get-WmiObject”有很多相似的地方,但是也由几个语法上的差异。

你需要使用“-ClassName”代替“-Class
没有用于列出命名空间中所有类的“-List”参数。而是使用“Get-CimClass”并搭配“-Namespace”参数获取类列表
没有“-Credential”参数;如果你需要从远程计算机查询并被要求提供代替凭据,需要通过“Invoke-Command”发送“Get-CimInstance

Get-CimInstance -ClassName Win32_LogicalDisk
Invoke-Command -ScriptBlock { Get-CimInstance -ClassName Win32_Proccess } -ComputerName win8 -Credential DOMAINAdministrator

多任务后台作业

介绍

PowerShell的后台作业功能可以将一个命令移至另一个独立的后台线程(一个独立的,Powerhell后台进程)。该功能使得命令以后台模式运行,这样你就可以使用PowerShell处理其他任务。

同步和异步执行命令的区别。

  • 当在同步模式下运行命令时,可以相应输入请求;当使用后台模式运行命令时,根本就没有机会看到输入请求——实际上,当遇到输入请求时,会停止执行该命令
  • 在同步模式下,如果遇到错误,命令会立即返回错误信息;后台模式执行的命令也会产生错误信息,但是你无法立即查看这些信息。如果需要,你必须通过一些机制来获取这些信息
  • 在同步模式下,如果忽略了某个的必要参数,PowerShell会提示对应的缺失信息;如果是后台执行的命令,无法提示缺失信息,所有命令会执行失败
  • 在同步模式下,当命令开始产生执行结果时,就会立即返回;但是当命令处于后台模式时,你必须等待命令执行结束,才能获取缓存的执行结果

创建本地作业

为了创建这种类型的作业,你需要使用Start-Job命令。参数-ScriptBlock使得你可以指定需要执行的命令(一个或多个)。PowerShell会自动使用默认的作业名称(Job1Job2等)。你可以使用-Name参数指定特定的作业名称,可以使用-Crendential参数接收一个域名用户名(DOMAINUserName)的凭证,同时该参数也会使得提示输入密码。如果没有指定脚本块,可以使用-FilePath参数来使得作业执行包含多个命令的完整脚本文件。

Start-Job -ScriptBlock { Dir }
Start-Job -ScriptBlock { Get-EventLog Security -ComputerName Server-R2 }

注意:尽管本地作业是在本地运行的,但是它们也需要使用PowerShell的远程处理系统架构,所以如果你没有启用远程处理,那么将无法创建本地作业

WMI作业和远程处理作业

创建作业的另一种方法是使用Get-WMIObject命令。为了将命令置为后台运行模式,像往常一样执行Get-WMIObject命令,但是需要加上-AsJob参数。此时,你不能指定一个自定义的作业名称,只能使用PowerShell指定的默认作业名称。

Get-WMIObject Win32_OperatingSystem -ComputerName( Get-Content allservers.txt) -AsJob

同样的,使用-AsJob参数添加到Invoke-Command命令中也可实现作业的创建,但是通过此命令的-JobName参数可以指定一个特定的作业名称。

Invoke-Command -Command { Get-Process } -ComputerName ( Get-Content .allservers.txt ) -AsJob -JobName myRemoteJob

获取作业执行结果

Get-Job这个Cmdlet可以获取在系统中定义的所有作业,并返回其状态。而使用Receive-Job命令可以获取一个作业的执行结果。

  • 你必须指定希望获取返回结果的对应作业。可以通过作业ID、作业名称,或者通过Get-Job命令获取作业列表后,通过管道传递给Receive-Job命令
  • 如果你获取了父作业的返回结果,那么该结果会包含所有子作业的输出结果。当然,你也可以获取一个或多个子作业执行结果
  • 正常情况下,获取一个作业的返回结果后,会自动在作业的输出缓存中清除对应的数据,这样你不能再次获取它们。可以通过-Keep参数在内存中保留输出结果的一份拷贝。或者如果你希望保存一份拷贝以作它用,也可以将结果输出到CliXML
  • 作业的返回结果可以是反序列化的对象,即返回的结果是它们产生时的一个快照,它们可能不会包含可以执行的任何方法。但是如果需要,你可以直接将作业的返回结果通过管道传递给一些Cmdlet,比如Sort-ObjectFormat-ListExprot-CSVConvertTo-HTMLOut-File
Get-Job
# 格式化输出结果
Get-Job -id 1 | Format-List *
Receive-Job -ID 1
# 将结果缓存
Receive-Job -ID 3 -Keep
Receive-Job -Name MyRemoteJob | Sort-Object PSComputerName | Format-Table -GroupBy PSComputerName

在这里插入图片描述

注意:当某个作业的输出结果没有被缓存时,对应的HasMoreData列为False

以下演示了如何获取子作业。

在这里插入图片描述

对应包含多个子作业的情况,可以使用以下命令获取其子命令。

Get-Job -ID 3 | Select-Object -Expand ChildJobs

针对作业,还有另外3个命令。

  • Remove-Job——该命令会移除一个作业,包括从内存中移除该作业缓存的所有输出结果
  • Stop-Job——如果某个作业看起来卡住了,你可以通执行该命令停止它。但是仍然可以获取截至到该时刻产生的结果
  • Wait-Job——该命令在下面场景中比较有用:当使用一段脚本开启一个作业,同时希望该脚本在作业运行完毕之后继续执行。该命令会使得PowerShell停止并等待作业执行,在作业执行结束后,运行PowerShell继续执行

调度作业

术语调度作业(scheduled jobs)和调度任务(scheduled tasks)并不同——前一种是与PowerShell相关的,后一种是你经常使用的传统作业。

你通过创建一个触发器(New-JobTrigger)开启一个调度作业,该触发器主要用于定义任务的运行时间。同时,你也可以使用New-ScheduledTaskOption命令设置作业的选项。之后你使用Register-ScheduledJob命令将该作业注册到计划任务程序中。该命令采用集合任务程序中的XML格式来创建任务的定义,之后在磁盘上新建一个层级结构的文件夹存放每次作业运行的结果。

# 每天凌晨2点值Get-Process命令,如果必须则唤醒计算机,同时要求作业运行在高级权限下
Register-ScheduledJob -Name DailyProcList -ScriptBlock { Get-Process } -Trigger ( New-JobTrigger -Daly -At 2am ) -ScheduledJobOption ( New-ScheduledJobOption -WaketoRun -RunElevated)

当移除这些作业,对应的结果也会从磁盘上移除。可以通过Register-ScheduledJob命令的-MaxResultCount参数控制存放结果数量。

同时处理多个对象

首先方法:“批处理” Cmdlet

很多PowerShell Cmdlet可以接收批量对象,或者称之为对象集合。下面是一个使用批处理管理的示例。

Get-Service | Stop-Service

在本例中,Stop-Service专门被设计用于从管道接收一个或多个服务对象,并停止服务。这就是所谓的“batch Cmdlets”(这是我们对它的命名,不是官方术语),也是我们批量管理的首先方式。

Get-Service -Name BITS -ComputerName Serv1,Serv2,Serv3 | Start-Service -PassThru | Out-File NewServiceStatus.txt

该命令从三台计算机列表中获取指定服务,然后通过管道将这些服务传递给Start-Service。该命令不仅会启动服务,而且会将涉及的服务对象打印在屏幕上。然后这些服务对象将会通过管道传递给Out-File存储到文本文件中。

-PassThru参数用于打印出该命令所接收的对象

CIMWMI方式:调用方法

不幸的是,总有一些任务无法通过调用Cmdlet完成。而且有一些我们可以通过Windows管理规范WMI)可以操控的条目。

比如WMI中的Win32_NetworkAdapterConfiguration类。该类代表与网卡绑定的配置信息,我们想通过命令启用DHCP,查看下面的示例。

Gwmi Win32_NetworkAdapterConfiguration -Filter "description like '%intel%'" | gm

在这里插入图片描述

Gwmi Win32_NetworkAdapterConfiguration -Filter "description like '%intel%'" | EnabledDHCP()

不幸的是,这是无效的。EnabledDHCP并不是PowerShellCmdlet,而是直接附加在配置对象自身的行为。但是我们可以使用Invoke-WmiMethod这个通用的Cmdlet

Gwmi Win32_NetworkAdapterConfiguration -Filter "description like '%intel%'" | Invoke-WmiMethod -Name EnabledDHCP

你需要记住以下几点。

  • 方法名称后无需加括号
  • 方法名称不区分大小写
  • Invoke-WmiMethod 一次只能接收一种类型的WMI对象。
  • 你可以针对Invoke-WmiMethod方法加上-WhatIf-Confirm参数。但直接由对象调用方法时,无法使用这些参数

当你由一个WMI对象包含可执行的方法时,大多可以使用Invoke-WmiMethod。该命令对远程计算机通用有效。同样的,我们可以使用Invoke-CimMethod进行替代,并且我们更加建议使用Invoke-CimMethod命令。

后备计划:枚举对象

总是会有些情况,我们只能通过枚举的方式一个个的处理。PowerShell提供了两种方法:第一种是使用Cmdlet,另一种是使用脚本结构。

我们使用Win32_Service这个WMI类作为示例。更详细的说是使用Change()方法。具体示例如下。

Gwmi Win32_Service -Filter "name='BITS'" | Foreach-Object -Process { $_.change($null,$null,$null,$null,$null,$null,$null,"P@ssw0rd")}

让我们把示例中的代码分解说明。

  • 首先,你将看到Cmdlet名称,ForEach-Object
  • 接下来,使用-Process参数指定脚本段。其是位置参数,也可以不写,但建议明确写出
  • ForEach-Object将会对每个通过管道传输给ForEach-Object的对象执行脚本段。每次脚本段执行后,下一个通过管道传输进来的对象都会被置于特殊的$_容器
  • 通过在$_后输入一个“.”,告诉Shell我们需要访问当前对象的属性或方法

接下来我们看一下下面的例子,它通过多种方式实现停止某个指定条件下的服务。

# 批处理Cmdlet
Get-Service -Name *B* | Stop-Service
# ForEach-Object
Get-Service -Name *B* | ForEach-Object { $_.Stop() }
# WMI
Get-WmiObject Win32_Service -Filter "name like '%B%'" | Invoke-WmiMethod -Name StopService
# WMI 和 ForEach-Object
Get-WmiObject Win32_Service -Filter "name like '%B%'" | ForEach-Object { $_.Stop() }
# Stop-Service 
Stop-Service -Name *B*

从上面的例子中我们也可以看出CmdletWMI的重要区别。

  • 原生Cmdlet过滤条件通常使用“*”作为通配符,而WMI过滤使用百分比符号(%)——请不要将百分比符号和ForEach-Ojbect别名搞混。这个百分比符号封装在Get-WmiObject-Filter参数内,并不是一个别名
  • 原生对象通常和WMI有相同的功能,但是语法或许会有不同
  • 原生过滤通常使用原生的比较操作符,比如说-eqWMI使用类似编程语言风格的操作符,比如说=或者like

那么,何时该使用WMI方法或者Cmdlet来完成一个任务呢?这个选择十分简单。

  • 如果你通过Get-WmiObject获取对象,你将需要通过使用WMI方法来执行行为。你可以使用Invoke-WmiMethodForEach-Object方式执行方法
  • 如果你通过非Get-WmiObject的方式获取对象,你将需要对获取到对象使用原生Cmdlet。除非你获取到的对象只有方法而没有能够完成任务所需的Cmdlet,你可能会使用ForEach-Object方式执行方法

注意:到这里的最低标准是ForEach-Object:它的语法或许是最难的,但你可以使用它完成几乎所有你需要完成的工作

无论何时都无法将任何对象通过管道传递给一个方法。你只能利用管道将一个Cmdlet产生的对象传递给另一个Cmdlet。如果完成任务所需的Cmdlet不存在,但存在这样的方法,那么你就可以将其通过管道传递给ForEach-Object并执行对象的方法。

请记住,通过管道将对象传递给Get-Member,可以查看对象包含的方法。

在这里插入图片描述

如图,请重点关注TypeName,在本例中是Sytem.Service Process.ServcieController。在搜索引擎中搜索完整的类型名称,你通常可以找到完整的官方开发文档,并可以根据文档找出你所需要的特定方法的文档。

最后,我们来分享一下ForEach-Object的一些小技巧。

  • 多使用ForEach-Object的完整名称,而不是使用%ForEach这样的别名。完整名称更易于阅读。如果你使用别人写的示例,请将别名替换为完整名称
  • 花括号内的代码段对于每一个通过管道传入的对象执行一次
  • 在代码段内,$_代表通过管道传入的对象之一
  • 使用$_本身控制所有通过管道传入的对象;使用$_后的加“.”控制单独的方法或属性
  • 即使方法不需要任何参数,方法名称之后也总是跟随圆括号。当需要参数时,通过逗号将参数分割放在括号内

安全警报

Windows PowerShell的安全目标是:

  • PowerShell不会给被处理的对象任何额外的权限
  • PowerShell无法绕过既有的权限
  • PowerShell的安全并不是针对恶意软件的防护

下面我们具体看有哪些安全措施来实现PowerShell的安全。

执行策略设置

默认设置是Restricted,该策略会阻止正常脚本的运行。也就是说,你默认情况下你可以使用PowerShell进行交互式执行命令,但是不能执行脚本。

你可以通过运行Get-ExecutionPolicy命令来查看当前执行策略。如果你想修改当前执行策略,可以采用下面3中方式之一。

  • 运行Set-ExecutionPolicy命令。该命令会修改Windows注册表中的HKEY_LOCAL_MACHINE部分,但是需要在管理员权限下才能执行该命令
  • 使用组策略对象(GPO)。如下图,我们可以在“本地计算机策略”=>用户配置=>管理模板=>Windows组件=>Windows PowerShell中找到相应的设置内容

在这里插入图片描述

  • 通过手动运行PowerShell.exe,并给出-ExecutionPolicy的命令行开关参数。采用这种方式,那么命令中指定的执行策略会覆盖本地任何设置和组策略中的设置值

你可以执行策略设置为5种值(请注意:组策略对象中包含下面列表中的3个选项)。

  • Restricted——默认选项,除微软提供的一部分配置PowerShell的默认选项脚本外,不允许执行其他任何脚本。这些脚本有微软的数字签名,如果修改了数字签名则也无法执行这些脚本了
  • AllSigned——经过受信任的证书颁发机构(CA)设计的数字证书签名之后的任意脚本,PowerShell均可执行
  • RemotedSigned——PowerShell可以运行本地任何脚本,同时也可以执行受信任的CA签发的数字证书前面之后的远程脚本
  • Unrestricted——可以运行所有脚本,此选项并不建议使用
  • Bypass——这个特殊的设定主要是针对应用程序开发任意,他们会将PowerShell嵌入到他们的应用程序中。这个设定值会忽略已经配置的执行策略,应当仅在主机应用程序提供了自身的脚本安全层时才使用该选项

微软强烈建议在执行脚本时使用RemoteSigned执行策略,并且仅在需要执行脚本的机器上采用该策略。

数字代码签名

数字代码签名,简称为代码签名,是指将一个密码签名应用到一个文本文件的过程,签名会显示在文件末端。签名包含了两部分重要信息:一是列出了对脚本签名的公司或组织;二是包含了对脚本的加密副本,并且PowerShell可以解密该副本。在创建一个签名之前,你需要拥有一个代码签名的证书,该证书也被称为第三方证书,一般由商业CA签发。

一旦你拥有了第三方证书并安装后,可以使用PowerShellSet-AuthenticodeSignature Cmdlet将该数字签名应用到一段脚本。签名不仅会提供脚本作者的身份信息,也会确保在作者对脚本签名后,不会被他人更改。原理如下:

  • 脚本作者持有一个数字证书,该密钥包含两个密钥:一个公钥、一个私钥
  • 当对脚本进行签名时,该签名会被私钥加密。私钥仅能被脚本开发者访问,同时仅有公钥能对该脚本进行解密。在签名中会包含脚本的副本
  • PowerShell运行该脚本时,它会使用作者的公钥(包含在签名中)解密该签名。如果解密失败,则说明签名被篡改,那么该脚本就无法被运行。如果签名中的脚本副本与明文文本不吻合,那么该签名就会识别为损坏,该脚本也无法被运行

在这里插入图片描述

其他安全措施

首先,Windows不会将PS1文件扩展名是为可执行文件类型。双击PS1文件,默认使用记事本打开进行编辑,不会被执行。其次,在Shell中不能通过键入脚本名称执行该脚本,Shell不会在当前目录中搜索脚本。只有通过绝对路径或者相对路径来运行脚本文件,这样做的目的是为了防止称为“命令劫持”的攻击类型。在攻击中,它会将一个脚本文件放入到文件夹中,然后将它命名为某些内置的命令名,如:dir

扩展命令

扩展:找到并添加插件

PowerShell存在两种类型的扩展:模块和管理单元。首先讲述管理单元。

一个合适管理单元PowerShell的名称是PSSnapin,用于区别这些来自管理单元的图形MMS。一个PSSnapin通常包含一个或多个DLL文件,同时包含配置XML文件和帮助文档。PSSnapin必须先安装并注册,然后PowerShell才能识别它的存在。

了解:通常PSSnapin的相关命令有——Get-PSSnapinAdd-PSSnapin

PSSnapin的概念逐渐被微软移除了,将来可能会越来越少。在内部,微软的重点是提供扩展模块。

扩展:找到并添加模块

PowerShell v2之后提供了模块。模块被设计的更加独立,因此更容易分发,但是它的工作原理类似与PSSnapin。模块不需要复制的注册。PowerShell会自动在一个特定的目录下查找模块。PSModulePath这个关键变量定义了PowerShell期望存放模块的路径。对于新的模块路径,可以考虑添加到此变量中。当然也可以考虑使用Import-Module命令并指定完整的模块路径进行添加。

Get-Content env:PSModulePath

可以通过Get-Module命令查看当前计算机上已经存在的模块

PowerShell会在磁盘中几个默认位置搜索模块,不同种类的模块位于不同的位置。

  • 系统模块PowerShell默认安装的模块大部分位于C:WindowsSystem32WindowsPowerShellv1.0Modules文件夹中。这个路径通常是PowerShell内部模块装用的。虽然可以将自己些的模块放到这个里面,但是不建议。

  • 所有用户模块:此部分的文件夹位置是C:Program FilesWindowsPowerShellModules。这个路径中的模块针对所有用户,如果想让计算机上的所有用户使用,可以将模块放在此文件夹中。

  • 当前用户模块:此部分文件夹位置是C:Users<loggedInUsers>DocumentsWindowsPowerShellModules。不管是自己些的还是下载的,放在此文件夹就只有当前登录的用户可用,对于多个计算机用户来说,有一定的隔离作用。

PowerShell模块的构成

  • .psm1格式文件:此扩展名的文件都可以是PowerShell模块。当然,文件中需要定义函数。通常,一个文件中的函数都是围绕一个主题了。

  • 模块清单文件(module manifest):扩展名称为.psd1,此文件不是必须的,但是建议提供。这是使用PowerShell哈希表格式编写的文本文件,哈希表中的元素用于描述模块的元数据。

此文件可以手动创建,也可以使用New-ModuleManifest命令生成模板

New-ModuleManifest 'e:so.psd1' -Author 'Adam Bertram' -RootModule so.psm1 -Description 'This module helps in deploying software.'

生成内容如下。

#
# 模块“so”的模块清单
#
# 生成者: Adam Bertram
#
# 生成时间: 2024/1/4
#

@{

# 与此清单关联的脚本模块或二进制模块文件。
RootModule = 'so.psm1'

# 此模块的版本号。
ModuleVersion = '1.0'

# 支持的 PSEditions
# CompatiblePSEditions = @()

# 用于唯一标识此模块的 ID
GUID = '6adb5eb0-68e5-47a4-a8cc-6ba81131933c'

# 此模块的作者
Author = 'Adam Bertram'

# 此模块所属的公司或供应商
CompanyName = '未知'

# 此模块的版权声明
Copyright = '(c) 2024 Adam Bertram。保留所有权利。'

# 此模块所提供功能的说明
Description = 'This module helps in deploying software.'

# 此模块要求的 Windows PowerShell 引擎的最低版本
# PowerShellVersion = ''

# 此模块要求的 Windows PowerShell 主机的名称
# PowerShellHostName = ''

# 此模块要求的 Windows PowerShell 主机的最低版本
# PowerShellHostVersion = ''

# 此模块要求使用的最低 Microsoft .NET Framework 版本。此先决条件仅对 PowerShell Desktop 版本有效。
# DotNetFrameworkVersion = ''

# 此模块要求使用的最低公共语言运行时(CLR)版本。此先决条件仅对 PowerShell Desktop 版本有效。
# CLRVersion = ''

# 此模块要求的处理器体系结构(无、X86、Amd64)
# ProcessorArchitecture = ''

# 必须在导入此模块之前先导入全局环境中的模块
# RequiredModules = @()

# 导入此模块之前必须加载的程序集
# RequiredAssemblies = @()

# 导入此模块之前运行在调用方环境中的脚本文件(.ps1)。
# ScriptsToProcess = @()

# 导入此模块时要加载的类型文件(.ps1xml)
# TypesToProcess = @()

# 导入此模块时要加载的格式文件(.ps1xml)
# FormatsToProcess = @()

# 将作为 RootModule/ModuleToProcess 中所指定模块的嵌套模块导入的模块
# NestedModules = @()

# 要从此模块中导出的函数。为了获得最佳性能,请不要使用通配符,不要删除该条目。如果没有要导出的函数,请使用空数组。
FunctionsToExport = '*'

# 要从此模块中导出的 cmdlet。为了获得最佳性能,请不要使用通配符,不要删除该条目。如果没有要导出的 cmdlet,请使用空数组。
CmdletsToExport = '*'

# 要从此模块中导出的变量
VariablesToExport = '*'

# 要从此模块中导出的别名。为了获得最佳性能,请不要使用通配符,不要删除该条目。如果没有要导出的别名,请使用空数组。
AliasesToExport = '*'

# 要从此模块导出的 DSC 资源
# DscResourcesToExport = @()

# 与此模块一起打包的所有模块的列表
# ModuleList = @()

# 与此模块一起打包的所有文件的列表
# FileList = @()

# 要传递到 RootModule/ModuleToProcess 中指定的模块的专用数据。这还可能包含 PSData 哈希表以及 PowerShell 使用的其他模块元数据。
PrivateData = @{

    PSData = @{

        # 应用于此模块的标记。这些标记有助于在联机库中执行模块发现。
        # Tags = @()

        # 指向此模块的许可证的 URL。
        # LicenseUri = ''

        # 指向此项目的主网站的 URL。
        # ProjectUri = ''

        # 指向表示此模块的图标的 URL。
        # IconUri = ''

        # 此模块的 ReleaseNotes
        # ReleaseNotes = ''

    } # PSData 哈希表末尾

} # PrivateData 哈希表末尾

# 此模块的 HelpInfo URI
# HelpInfoURI = ''

# 从此模块中导出的命令的默认前缀。可以使用 Import-Module -Prefix 覆盖默认前缀。
# DefaultCommandPrefix = ''

}

从Internet获取模块

微软引入了一个名称为PowerShellGet的模块,这使得从在线仓库中搜索、下载、安装、升级模块变的容易。微软甚至还维护了一个在线源,称为PowerShell Gallery(http://powershellgallery.com)。

使用步骤:

  • 运行Register-PSReporsitory添加要给源的URL。默认如上

  • 使用Find-Module在源中查找模块。你可以在名称、特定标签等列中使用通配符缩写搜索范围

  • 找到所需模块后,使用Install-Module下载与安装

  • 使用Update-Module确保你的模块的副本是最新的,如不是则下载更新并安装

  • 使用Remove-Module删除模块,使用Uninstall-Module命令从磁盘中卸载/删除模块

# 查看
Get-Command -Module PowerShellGet
# 查找
Find-Module -Name *VMware*
# 安装
Find-Module -Name VMware.PowerCLI | Install-Module

最后,如果要创建我们自己的模块。记住,PowerShell模块通常由文件夹(模块容器)、 .psm1文件(模块)和.psd1文件(模块清单文件)构成。其中,模块文件夹的名称必须和模块本身的名称相同。放在上面介绍的三个位置的任意一个地方,使用Get-Module命令即可查看到自定义的模块及相应的命令。

总结

以上是对PowerShell基本知识的深入介绍,在接下来的章节中我们将介绍PowerShell的远程部分。