在 PowerShell 中,如何在文件中定义函数并从 PowerShell 命令行调用它?
我有一个 .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
I have a .ps1 file in which I want to define custom functions.
Imagine the file is called MyFunctions.ps1, and the content is as follows:
Write-Host "Installing functions"
function A1
{
Write-Host "A1 is running!"
}
Write-Host "Done"
To run this script and theoretically register the A1 function, I navigate to the folder in which the .ps1 file resides and run the file:
.\MyFunctions.ps1
This outputs:
Installing functions
Done
Yet, when I try to call A1, I simply get the error stating that there is no command/function by that name:
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
I must misunderstand some PowerShell concepts. Can I not define functions in script files?
Note that I have already set my execution policy to 'RemoteSigned'. And I know to run .ps1 files using a dot in front of the file name: .\myFile.ps1
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
在 PowerShell 命令行上尝试一下:
点运算符用于脚本包含,又名“点源”(或 "点源表示法")
Try this on the PowerShell command line:
The dot operator is used for script include, aka "dot-sourcing" (or "dot source notation")
你所说的叫做点源。这是邪恶的。但不用担心,有一种更好、更简单的方法来完成您想要的事情模块(听起来比实际更可怕)。使用模块的主要好处是,如果需要,您可以从 shell 中卸载它们,并且它可以防止函数中的变量爬入 shell(一旦您点了函数文件的源代码,请尝试从shell 中的函数,你就会明白我的意思)。
首先,将包含所有函数的 .ps1 文件重命名为 MyFunctions.psm1 (您刚刚创建了一个模块!)。现在,为了正确加载模块,您必须对该文件执行一些特定的操作。首先,要让 Import-Module 查看模块(您使用此 cmdlet 将模块加载到 shell 中),它必须位于特定位置。模块文件夹的默认路径是 $home\Documents\WindowsPowerShell\Modules。
在该文件夹中,创建一个名为 MyFunctions 的文件夹,并将 MyFunctions.psm1 文件放入其中(模块文件必须驻留在与 PSM1 文件名称完全相同的文件夹中)。
完成后,打开 PowerShell,然后运行以下命令:
如果您看到一个名为 MyFunctions 的命令,则说明您做得对,并且您的模块已准备好加载(这只是为了确保设置正确,您只需执行此操作一次)。
要使用该模块,请在 shell 中键入以下内容(或将此行放入您的 $profile 中,或将其作为脚本中的第一行):
您现在可以运行您的函数。最酷的一点是,一旦你有 10-15 个函数,你就会忘记其中几个函数的名字。如果您将它们放在模块中,则可以运行以下命令来获取模块中所有函数的列表:
这非常好,在前端进行设置所需的一点点努力是值得的。
What you are talking about is called dot sourcing. And it's evil. But no worries, there is a better and easier way to do what you are wanting with modules (it sounds way scarier than it is). The major benefit of using modules is that you can unload them from the shell if you need to, and it keeps the variables in the functions from creeping into the shell (once you dot source a function file, try calling one of the variables from a function in the shell, and you'll see what I mean).
So first, rename the .ps1 file that has all your functions in it to MyFunctions.psm1 (you've just created a module!). Now for a module to load properly, you have to do some specific things with the file. First for Import-Module to see the module (you use this cmdlet to load the module into the shell), it has to be in a specific location. The default path to the modules folder is $home\Documents\WindowsPowerShell\Modules.
In that folder, create a folder named MyFunctions, and place the MyFunctions.psm1 file into it (the module file must reside in a folder with exactly the same name as the PSM1 file).
Once that is done, open PowerShell, and run this command:
If you see one called MyFunctions, you did it right, and your module is ready to be loaded (this is just to ensure that this is set up right, you only have to do this once).
To use the module, type the following in the shell (or put this line in your $profile, or put this as the first line in a script):
You can now run your functions. The cool thing about this is that once you have 10-15 functions in there, you're going to forget the name of a couple. If you have them in a module, you can run the following command to get a list of all the functions in your module:
It's pretty sweet, and the tiny bit of effort that it takes to set up on the front side is WAY worth it.
<代码>。 “$PSScriptRoot\MyFunctions.ps1”
MyA1Func
从 v3 开始可用,在此之前请参阅 如何获取 PowerShell 脚本的文件系统位置?。这很常见。
PS 我不同意“一切都是模块”的规则。我的脚本由 GIT 之外的其他开发人员使用,因此我不喜欢在脚本运行之前将内容放在特定位置或修改系统环境变量。这只是一个脚本(或两个或三个)。
. "$PSScriptRoot\MyFunctions.ps1"
MyA1Func
Availalbe starting in v3, before that see How can I get the file system location of a PowerShell script?. It is VERY common.
P.S. I don't subscribe to the 'everything is a module' rule. My scripts are used by other developers out of GIT, so I don't like to put stuff in specific a place or modify system environment variables before my script will run. It's just a script (or two, or three).
您可以将功能添加到:
该功能将可用。
配置文件的实际位置由 $PROFILE 变量确定,只需在 powershell 终端中输入该位置就会告诉您要编辑的文件。
You can add function to:
An the function will be available.
The actual location of the profile file is determined by the $PROFILE variable and typing just that into a powershell terminal will tell you the file to edit.
如果您的文件只有一个要调用/公开的主函数,那么您也可以使用以下命令启动该文件:
然后您可以按如下方式调用它:
如果您只想轻松调用该函数,这会更加方便无需导入该函数。
If your file has only one main function that you want to call/expose, then you can also just start the file with:
You can then call it e.g. as follows:
This makes it much more convenient if you want to easily call just that function without having to import the function.
您当然可以在脚本文件中定义函数(然后我倾向于在加载时通过我的 Powershell 配置文件加载它们)。
首先,您需要通过运行以下命令来检查以确保该函数已加载:
并检查它是否出现在列表中(应该是 1 的列表!),然后让我们知道您得到的输出!
You certainly can define functions in script files (I then tend to load them through my Powershell profile on load).
First you need to check to make sure the function is loaded by running:
And check that it appears in the list (should be a list of 1!), then let us know what output you get!
假设我在路径
C:\Temp\TestScript.sp1
这些脚本中的脚本和函数遵循
范围
的规则。另外,当您在 powershell 编辑器中使用
调用运算符 (&)
执行脚本文件时,它也不会添加到 powershell 编辑器的当前作用域中,如下所示Let's say I created a script at path
C:\Temp\TestScript.sp1
Scripts and functions within those scripts follow the rules of
scope
.Also When you use the
call operator (&)
to execute a script file in powershell editor, it is also not added to the current scope of powershell editor as shown below假设您有一个名为 Dummy-Name.psm1 的模块文件,其中有一个名为 Function-Dumb() 的方法
Assuming you have a module file called Dummy-Name.psm1 which has a method called Function-Dumb()
最简单的更改是在
global
作用域中设置A1
函数MyFunctions.ps1
然后它就可以工作:
The simplest change is to set the
A1
function in theglobal
scopeMyFunctions.ps1
Then it works: