我有一个 .ps1 文件,我想在其中定义自定义函数。
想象一下这个文件叫MyFunctions.ps1,内容如下:
Write-Host "Installing functions"
function A1
{
Write-Host "A1 is running!"
}
Write-Host "Done"
要运行此脚本并在理论上注册 A1 函数,我导航到 .ps1 文件所在的文件夹并运行该文件:
.\MyFunctions.ps1
这输出:
Installing functions
Done
然而,当我尝试调用 A1 时,我只是收到错误消息,指出没有该名称的命令/函数:
The term 'A1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling
of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:3
+ A1 <<<<
+ CategoryInfo : ObjectNotFound: (A1:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
我必须误解一些 PowerShell 概念。我不能在脚本文件中定义函数吗?
请注意,我已经将执行策略设置为“RemoteSigned”。而且我知道在文件名前使用一个点来运行 .ps1 文件:.\myFile.ps1
您所说的称为dot sourcing。这是邪恶的。不过不用担心,使用 modules 有一种更好、更简单的方法来做你想做的事(听起来比实际更可怕)。使用模块的主要好处是,如果需要,您可以从外壳中卸载它们,并且它可以防止函数中的变量潜入外壳(一旦您点源函数文件,请尝试从在 shell 中运行,你会明白我的意思)。
因此,首先,将包含所有函数的 .ps1 文件重命名为 MyFunctions.psm1(您刚刚创建了一个模块!)。现在要正确加载模块,您必须对文件执行一些特定操作。首先要让 Import-Module 查看模块(您使用此 cmdlet 将模块加载到 shell 中),它必须位于特定位置。模块文件夹的默认路径是 $home\Documents\WindowsPowerShell\Modules。
在该文件夹中,创建一个名为 MyFunctions 的文件夹,并将 MyFunctions.psm1 文件放入其中(模块文件必须位于与 PSM1 文件同名的文件夹中)。
完成后,打开 PowerShell,然后运行以下命令:
Get-Module -listavailable
如果您看到一个名为 MyFunctions 的功能,那么您做对了,并且您的模块已准备好加载(这只是为了确保设置正确,您只需执行一次)。
要使用该模块,请在 shell 中键入以下内容(或将此行放在 $profile 中,或将其作为脚本的第一行):
Import-Module MyFunctions
您现在可以运行您的函数。很酷的一点是,一旦你有 10-15 个函数,你就会忘记一对夫妇的名字。如果您将它们放在模块中,则可以运行以下命令来获取模块中所有函数的列表:
Get-Command -module MyFunctions
它非常可爱,而且在前端设置所需的一点点努力是值得的。
Import-Module .\buildsystem\PSUtils.psm1
一样完成
Import-Module
更改 .
并重命名扩展名一样简单,并且不需要将模块放置在特定文件夹中,即我可以将它放在我想要的任何目录中,只需与点源一样,考虑到范围界定的好处,是否有任何理由甚至对模块进行点源? (当然,除非那些范围“问题”是你想要的)
. "$PSScriptRoot\MyFunctions.ps1" MyA1Func
从 v3 开始可用,在此之前请参阅 How can I get the file system location of a PowerShell script?。这是很常见的。
PS 我不订阅“一切都是模块”规则。我的脚本被 GIT 之外的其他开发人员使用,所以我不喜欢在我的脚本运行之前将东西放在特定的地方或修改系统环境变量。它只是一个脚本(或两个,或三个)。
Get-Command -Module FluentMigrator.PowerShell
的能力非常好?
您当然可以在脚本文件中定义函数(然后我倾向于在加载时通过我的 Powershell 配置文件加载它们)。
首先,您需要检查以确保通过运行加载该函数:
ls function:\ | where { $_.Name -eq "A1" }
并检查它是否出现在列表中(应该是 1 的列表!),然后让我们知道你得到了什么输出!
您可以将功能添加到:
c:\Users\David\Documents\WindowsPowerShell\profile.ps1
该功能将可用。
如果您的文件只有一个您想要调用/公开的主要功能,那么您也可以使用以下方式启动文件:
Param($Param1)
然后你可以调用它,例如如下:
.\MyFunctions.ps1 -Param1 'value1'
如果您想轻松调用该函数而无需导入该函数,这将更加方便。
[CmdletBinding()]
属性并将其免费升级为高级功能。 :-)
假设您有一个名为 Dummy-Name.psm1 的模块文件,其中有一个名为 Function-Dumb() 的方法
Import-Module "Dummy-Name.psm1";
Get-Command -Module "Function-Dumb";
#
#
Function-Dumb;
. "$PSScriptRoot\MyFunctions.ps1"
。从 v3 开始可用,在此之前请参阅 stackoverflow.com/questions/3667238/…。这是很常见的。