Windows PowerShell:打包并分发自定义 Windows PowerShell 工具

您可以利用 Dot-source 功能实现一些有趣的功能,但如果您不够谨慎,它也可能会带来一些问题。

Don Jones

Dot-source 是一种巧妙的技巧,但如果您不再需要某些命令,或者如果您后来发现某些命令与其他内容冲突,却很难删除这些命令。当我们在上个月将一个命令变为独立的、参数化的可重用工具之后,我发现我们需要解决两个问题。

我们将该工具构建为 Windows PowerShell 高级函数,有时也称为“脚本 Cmdlet”。第一个问题是,脚本本身难以使用。该脚本包含一个函数,因此如果只运行该脚本,不会发生任何事。您要么修改该脚本并添加用来运行该函数的命令,要么通过 Dot-source 将该脚本转移到 Shell 中,才能使该函数成为一个全局命令。

另一问题是,该脚本包含两个函数。第一个函数是 Get-OSInfo,是我希望用户使用的函数。第二个函数是 OSInfoWorker,它完成了所有实际的工作。但是,我不希望用户直接执行这个函数。如果使用 Dot-source 方式,则没有办法隐藏 OSInfoWorker(或者按照程序员的说法,将它变为私有)。将脚本转变成脚本模块可解决这两个问题。

了解模块

Windows PowerShell 支持三种基本的模块类型:二进制、脚本和清单模块。二进制模块包含一个在 Visual Studio 中生成的 DLL,用于向 Shell 添加 Cmdlet、提供程序或其他元素。脚本模块仅仅是指:单一的脚本,可向 Shell 添加一个或多个函数。清单模块可真正包含多个组件,例如二进制扩展程序、脚本等等。脚本模块最容易创建,因此我们选择使用脚本模块。

脚本模块有三项要求:

  1. 它必须是有效的 Windows PowerShell 脚本,主要由要添加到 Shell 中的函数组成。
  2. 它必须具有 .psm1 文件扩展名,而不是 .ps1 文件扩展名。
  3. 它必须位于计算机上的特定文件夹中

最后一条要求实际上不过是为方便起见而提供的一项建议。在安装时,Windows PowerShell 会定义一个新的系统级环境变量,名为 PSModulePath。此环境变量的工作方式与系统的 Path 环境变量非常相似。它包含 Shell 在按名称查找模块时自动搜索的文件夹。

默认情况下,会定义两个模块路径。其中一个位于 System32 文件夹层次结构下。此路径供 Microsoft 提供的模块使用。另一个位于您的 Documents 文件夹中,供您自己的模块使用。我们将使用这一个路径。当然,您可以在 PSModulePath 中修改或添加路径,例如,定义您的团队用来集中存储共享模块的路径。

我们使用的路径是 \[My ]Documents\WindowsPowerShell\Modules。在 Windows XP,此路径为“My Documents”。而在 Windows Vista 及更高版本中,此路径仅为“Documents”。默认情况下,WindowsPowerShell 文件夹不存在。您必须自行创建。默认情况下,Modules 子文件夹也不存在,因此您也需要自行创建。

如果不将您的模块放到某个 PSModulePath 位置中,则只需在加载模块时,指定完整的路径和文件名。这种方式对于常用模块不是很方便,因此我倾向于将其放到 PSModulePath 中定义的路径下。

构建模块

我将在上个月的脚本末尾加上三个命令(您可以在此下载修订后的脚本):

New-Alias goi Get-OSInfo
Export-ModuleMember -function Get-OSInfo
Export-ModuleMember -alias goi

第一个命令定义一个别名“goi”。它用于我的 Get-OSInfo 函数。其他两个命令仅当您在脚本模块中使用它们时才会生效。

默认情况下,当您将一个模块导入 Shell 中时,将公开提供该模块中的每个函数。但是当您使用 Export-ModuleMember 时,则只会公开提供那些明确命名的函数和别名。

我的“goi”别名以及 Get-OSInfo 函数就能由任何使用此模块的用户使用。而我未指定的函数 OSInfoWorker 将被隐藏。您仍然可以在模块本身内部使用任何函数来调用 OSInfoWorker,但它不能直接在模块外使用,因为它是私有函数。

添加了这些命令后,我需要为该脚本指定适当的名称并将其放到适当的位置。我选择将此模块命名为“MyModule”。因此,该脚本文件的路径应当为 \[My ]Documents\WindowsPowerShell\Modules\MyModule\MyModule.psm1。

该脚本必须放到 Modules 的子文件夹中。子文件夹和脚本文件本身的名称都必须与模块名相同。做完此操作后,我就可以运行 Import-Module MyModule 来加载我的模块。

这是向其他用户分发脚本的一种简单而又有效的方法。我可以根据需要,在这一个文件中包含任意数量的函数和别名。只要将其放到正确的位置(或者有人愿意指定完整路径),其他用户就能轻松加载该模块,并使用这些函数。

Don Jones

Don Jones是 Concentrated Technology 的创始人,他会在 ConcentratedTech.com 上解答有关 Windows PowerShell 和其他技术的问题。他也是 Nexus.Realtimepublishers.com 的撰稿人,他的许多著作还在他的网站上以电子版的形式提供。

获取更多内容

下载本月文章随附的示例代码

注册即将截止,请赶快注册参加 Jones 亲自主持的独家动手体验工作室,该工作室为期三天,与 TechMentor Spring 2011 在同一地点举行。有关详情,请访问 TechMentorEvents.com

相关内容