我真的很快建立了og体育和函数的模块。我喜欢它允许我组织我的功能并在其他og体育中使用它们。我也看到许多PowerShellog体育人员慢慢地拍摄构建模块的步骤。我们经常学习如何构建一个模块,而无需真正了解它们为什么以这种方式构建。

在此帖子中,我们会一次将常用og体育方案转换为完整的模块。我们将采用几个MicroSteps来显示为什么常用模块构建的所有细微细节。让奥秘摆脱构建一个模块,看看它们有多简单。

指数

从函数开始

与PowerShell合作时存在自然进展。你从小og体育开始,并做出更大的工作。当您的og体育变大时,即可开始使用更多功能。这些函数可能来自您自己写的其他人或功能。这些函数在og体育顶部开始收集。

    function Get-Info
    {
        param($ComputerName)
        Get-WmiObject -ComputerName $ComputerName -Class Win32_BIOS
    }

    Get-Info -ComputerName localhost

您的og体育仍然是长期的,因为所有这些功能仍然占用og体育中的空间。这是我们将建立的常见情景。我在这里有一个功能,但有几个是常见的。

DOT Sourcing.

From here, we would move the functions out into their own .ps1 file. So if you saved that function into a file called GetInfo.ps1, then you could dot source it and call it like this.

. .\GetInfo.ps1
GetInfo -ComputerName localhost

DOT Sourcing是将og体育加载到当前运行空间中的方法。此功能现在可供您或调用og体育使用。遗漏该时期将运行og体育而不留下og体育中可用的定义功能。

您可以在该文件中放置多个函数并将其视为函数库。这是模块的基本思想。

导入模块

All it takes to turn your function script into a module is the use of 导入模块 to import it. Here is how that works.

 导入模块  .\GetInfo.ps1
GetInfo -ComputerName localhost

我喜欢这么多的东西。我真的希望这是一个原因下的标准方法。首先,理解和向Powershell新的人们更容易理解和解释。其次,它将og体育转移到更快的方式制作模块的路径。

.psm1

We can call 导入模块 on a .ps1, but the convention is to use .psm1 as a module designation. Rename that script to GetInfo.psm1.

 导入模块  .\GetInfo.psm1
GetInfo -ComputerName localhost

现在我们可以说我们有一个模块。

出口 - 模署

Sometimes you may have utility functions in your module that should stay internal to the module and not be made available to other scripts. If you want to have public and internal functions, you will need to use 出口 - 模署 in the *.psm1 file to define the exported public functions.

function GetInfo{
    param($ComputerName)
    Get-WmiObject -ComputerName $ComputerName -Class Win32_BIOS
}   
Export-ModuleMember -Function 'GetInfo'

If you don’t call 出口 - 模署 to specify exactly what you want exported, then everything is exported from this .psm1 file.

当我们谈论模块清单时,我将显示另一种方法来执行此操作。

文件夹名称

Then next thing I want to do is place our module into its own folder. The convention here is that the name of the folder matches the name of the .psm1 file. Our file structure should look something like this now.

Scripts
│   myscript.ps1
│
└───GetInfo
        GetInfo.psm1

Then we update our myscript.ps1 file to import that folder.

 导入模块  .\GetInfo
GetInfo -ComputerName localhost

导入模块 will automatically find our .psm1 file inside that folder. From here on out, that whole folder and all of it’s contents will be our module.

$ env:psmodulepath

There is an environment variable called $ env:psmodulepath . If we look at it, we will see all the locations where we can import a module (by module name instead of by path).

PS:> $env:PSModulePath -split ';'

C:\Users\username\Documents\WindowsPowerShell\Modules
C:\Program Files\WindowsPowerShell\Modules

这通常是一个字符串,但我拆分它,以便我们可以阅读它。有时您将安装一些将添加该列表的路径的东西。如果我们将文件夹放在两个位置之一内,我们可以按名称导入我们的模块。

所以我们需要将模块移动到 C:\Users\$env:username\Documents\WindowsPowerShell\Modules

Move-Item .\GetInfo "C:\Users\$env:username\Documents\WindowsPowerShell\Modules\"

然后我们的模块应在列出可用模块时显示。

Get-Module -ListAvailable

我们可以通过我们的og体育中的名称导入它。

 导入模块  GetInfo
GetInfo -ComputerName localhost

模块清单

在添加模块清单之前,我们真的不应该打电话给我们的模块。这为模块添加了元数据。它包括作者信息和版本控制。如果我们正确创建,它也将使PowerShell自动加载我们的模块。

The module manifest is just a hashtable saved as a *.psd1 file. The name of the file should match the name of the folder. By creating this file, it will get loaded when you call 导入模块 .

新ModuleManifest.

The good news is that we have a 新ModuleManifest. cmdlet that will create the manifest for us.

$manifest = @{
    Path              = '.\GetInfo\GetInfo.psd1'
    RootModule        = 'GetInfo.psm1' 
    Author            = 'Kevin Marquette'
}
New-ModuleManifest @manifest

Because our manifest is loaded instead of the *.psm1, we need to use the RootModule parameter to indicate what PowerShell module file should be ran. This is the structure that we have now.

 模块 
│
└───GetInfo
        GetInfo.psd1
        GetInfo.psm1

这是我们刚刚生成的清单的剪辑。

# Module manifest for module 'GetInfo'
# Generated by: Kevin Marquette
# Generated on: 5/21/2017

@{

# Script module or binary module file associated with this manifest.
RootModule = 'GetInfo.psm1'

# Version number of this module.
ModuleVersion = '1.0'

# ID used to uniquely identify this module
GUID = 'dadea276-ae04-4c01-b901-06838167ec7c'

# Author of this module
Author = 'Kevin Marquette'

# Company or vendor of this module
CompanyName = 'Unknown'

# Copyright statement for this module
Copyright = '(c) 2017 Kevin Marquette. All rights reserved.'

# Description of the functionality provided by this module
# Description = ''

# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = '*'

...

}

The 新ModuleManifest. created all those keys and comments for us.

functionstoExport.

One of the properties in the module manifest is the functionstoExport. property with a default value of *. By default, it will export all functions. We want to update that value to have all our public functions in it.

 functionstoExport.  = "GetInfo"

如果需要列出多个函数,请使用数组。

Using this property in the manifest is just like using 出口 - 模署 . I do need to mention that you don’t need to use both 出口 - 模署 and functionstoExport. . You only need to use one of those to export your functions. If you have a manifest, then you should be using functionstoExport. .

In Powershell 6.0, the functionstoExport. default is changing to an empty array @(). This is more in-line with best practices. You should either specify the functions to export or set the value to an empty array.

模块自动加载

One nice feature of having a module manifest with functionstoExport. defined, is that Powershell can auto import your module if you call one of the exported functions. Your module still has to be in the $ env:psmodulepath variable for this to work.

This is why it is important to populate the functionstoExport. . The default value for this is * to designate that it is exporting all functions defined in the module. This does work, but the auto import functionality depends on this value. This is often overlooked by a lot of module builders.

$ psmoduleautoloadingpreference.

Module auto-loading was introduced in PowerShell 3.0. We were also given $ psmoduleautoloadingpreference. to control that behavior. If you want to disable module auto-loading for all modules, then set this value to none.

$ psmoduleautoloadingpreference. = 'none'

除非您的模块开发,否则您通常会单独留下此变量。

#requires -modules.

当您有一个需要模块的og体育时,可以添加一个 需要声明 到og体育的顶部。这将要求在og体育运行之前加载指定的模块。如果安装了模块,并且如果允许自动加载,则需要语句将继续并导入模块。

 #requires -modules.  GetInfo
GetInfo -ComputerName localhost

如果我们在正确的位置有一个正确制作的模块,这就像我们的og体育最终应该结束。

把它整合在一起

现在我们知道如何按层构建模块层,我通常会以这种方式构建一个模块。

  • 创建名为的文件夹 MyModule
  • Create a file called MyModule.psm1 in that folder to hold your functions
  • Use 新ModuleManifest. to create a MyModule.psd1 in that folder for the metadata
  • Update the ModuleRoot and functionstoExport. properties in the MyModule.psd1

从库或实用程序模块开始,以实现常用功能。随着您的函数收集增长,您可以稍后将它们分解为自己的模块。

下一步是什么?

我们都从这样的简单模块开始,我想为我的下一篇文章奠定基础。我将为您在该帖子中的大量社区项目中看到的模块提供特定的设计模式。我在我的帖子中迅速覆盖 构建CI / CD管道.

如果您正在寻找向团队中的其他人分发模块的方法,请考虑创建一个 内部og体育存储库。它比你预期的更容易。