在PowerShell中,如何在文件中定义函数并从PowerShell命令行调用它?

在PowerShell中,如何在文件中定义函数并从PowerShell命令行调用它?,powershell,Powershell,我有一个.ps1文件,我想在其中定义自定义函数 假设文件名为MyFunctions.ps1,内容如下: Write-Host "Installing functions" function A1 { Write-Host "A1 is running!" } Write-Host "Done" .\MyFunctions.ps1 -Param1 'value1' 要运行此脚本并从理论上注册A1函数,请导航到.ps1文件所在的文件夹并运行该文件: .\MyFunctions.ps1

我有一个.ps1文件,我想在其中定义自定义函数

假设文件名为MyFunctions.ps1,内容如下:

Write-Host "Installing functions"
function A1
{
    Write-Host "A1 is running!"
}
Write-Host "Done"
.\MyFunctions.ps1 -Param1 'value1'
要运行此脚本并从理论上注册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
术语“A1”不能识别为cmdlet、函数、脚本文件或可操作程序的名称。检查拼写
如果包含名称或路径,请验证路径是否正确,然后重试。
第1行字符数:3

+A1在PowerShell命令行上尝试以下操作:

. .\MyFunctions.ps1
A1

点运算符用于脚本include,也称为“点源”(or)

您当然可以在脚本文件中定义函数(然后我倾向于在加载时通过我的Powershell配置文件加载它们)

首先,您需要检查以确保通过运行以下命令加载函数:

ls function:\ | where { $_.Name -eq "A1"  }

并检查它是否出现在列表中(应该是1的列表!),然后让我们知道您得到了什么输出

你所说的叫做。这是邪恶的。但是不用担心,有一种更好更简单的方法来做你想做的事情(听起来比实际情况更可怕)。使用模块的主要好处是,如果需要的话,可以从shell中卸载它们,这样可以防止函数中的变量潜入shell(一旦你点源函数文件,试着从shell中的函数调用其中一个变量,你就会明白我的意思)

因此,首先,将包含所有函数的.ps1文件重命名为MyFunctions.psm1(您刚刚创建了一个模块!)。现在,为了正确加载模块,您必须对文件执行一些特定的操作。首先,导入模块要查看模块(使用此cmdlet将模块加载到shell中),它必须位于特定位置。模块文件夹的默认路径为$home\Documents\WindowsPowerShell\modules

在该文件夹中,创建一个名为MyFunctions的文件夹,并将MyFunctions.psm1文件放入其中(模块文件必须位于与psm1文件同名的文件夹中)

完成后,打开PowerShell并运行以下命令:

Get-Module -listavailable
如果您看到一个名为MyFunctions的函数,您就做对了,并且您的模块已经准备好加载(这只是为了确保设置正确,您只需执行一次)

要使用该模块,请在shell中键入以下内容(或将此行放在$profile中,或将其作为脚本中的第一行):

现在可以运行函数了。最酷的是,一旦你有了10-15个函数,你就会忘记一对夫妇的名字。如果模块中有这些函数,可以运行以下命令以获取模块中所有函数的列表:

Get-Command -module MyFunctions
它非常可爱,在前端设置所需的一点点努力都是值得的。

。“$PSScriptRoot\MyFunctions.ps1”
MyA1Func

在v3中开始可用,在此之前请参见。这是很常见的


另外,我不同意“一切都是模块”的规则。我的脚本被GIT以外的其他开发人员使用,所以我不喜欢在脚本运行之前将内容放在特定的位置或修改系统环境变量。它只是一个脚本(或两个或三个)。

您可以将函数添加到:

c:\Users\David\Documents\WindowsPowerShell\profile.ps1

该函数将可用。

如果您的文件只有一个要调用/公开的主函数,那么您也可以使用以下命令启动该文件:

Param($Param1)
然后,您可以将其称为,例如,如下所示:

Write-Host "Installing functions"
function A1
{
    Write-Host "A1 is running!"
}
Write-Host "Done"
.\MyFunctions.ps1 -Param1 'value1'

如果您只想轻松调用该函数而不必导入该函数,这将使调用更加方便。

假设您有一个名为Dummy-Name.psm1的模块文件,该文件有一个名为function-Dumb()的方法


它的意思是“在当前上下文而不是子上下文中运行它”。它的意思是源文件的内容。与bash中相同。除非您先运行。\MyFunctions.ps1使其可用,否则它似乎不能很好地工作(至少在ISE中是这样)。我不确定是否严格从powershell.exe运行。我认为dot sourcing使用相对于pwd的路径而不是脚本是违反直觉的,因此我建议人们参考JoeG的答案并使用模块。@Spork
。“$PSScriptRoot\MyFunctions.ps1”
。在v3中开始可用,在此之前请参见。这很常见。如果您的函数仅与给定的PowerShell应用程序相关,该怎么办?我的意思是,如果你在某处安装了一个PS1软件包来完成一项工作,你可能不需要配置文件中的所有功能,对吗?在这种情况下,我会为特定的应用程序创建一个模块,在运行脚本之前加载它(如果以交互方式工作),或者在脚本中加载它。但一般来说,如果您有只针对给定任务的代码,那么您希望脚本中包含这些函数。就我个人而言,我只编写一般只做一件事的函数。如果一段代码是超专用的,那么将其包装在函数或模块中就没有意义(除非有多个脚本使用相同的代码,否则可能有意义)。模块文件不必位于与PSM1文件名称完全相同的文件夹中。它可以像导入模块一样完成。\buildsystem\PSUtils.psm1
@MichaelFreidgeim,只要用导入模块更改
并重命名扩展名即可,并且不需要将模块放在特定文件夹中,也就是说,我可以将其放在我想要的任何目录中,就像dot sourcing一样,考虑到范围界定带来的好处,是否有任何理由在模块上进行网络采购?(当然,除非那些范围“问题”是你想要的)@Abdul,dot采购更简单,模块更强大。见第页