65.9K
CodeProject 正在变化。 阅读更多。
Home

跨会话保存 PowerShell 命令

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.86/5 (3投票s)

2008年5月21日

CPOL

6分钟阅读

viewsIcon

45160

downloadIcon

141

一组函数,提供保存命令以便将来在 PowerShell 会话中使用的能力。

引言

PowerShell 对于开发人员和系统管理员来说都是一个有用的工具。它的许多用途来自于能够构建一个复杂的多部分命令来获取一些有用的信息。问题是,一旦我关闭窗口,该命令就消失了。如果我真的想保存该命令,我可以创建一个脚本,但这涉及到几个步骤:打开文本编辑器,输入命令,然后保存脚本文件。此外,以后当我想要运行它时,我必须输入脚本的完整路径。另外,当我编写脚本时,我觉得需要包含描述性的注释,比如脚本的目的和参数。而我真正想要的只是一个快速简便的方法来保存命令并在以后执行它们。

背景

在网上进行了一些搜索,我发现了 `Get-History` cmdlet,它允许你查看迄今为止已保存的整个命令历史记录。还有一个 `Add-History` cmdlet,但我尝试使用它来加载已保存的命令时并不成功。`Get-History` 会显示这些命令,但通过向上或向下箭头键(这是循环浏览历史记录的常规方式)却无法访问它们。

即使它奏效了,我还是想要一种方法来保存任意数量的命令,并能够轻松执行它们,而不必通过历史记录来循环。这种方法的另一个缺点是,加载的命令最终会被历史记录挤出,需要某种方法将命令重新加载到历史记录中。考虑到这些限制,我着手编写自己的函数。

为什么是函数而不是脚本文件?使用函数而不是脚本文件的主要原因是,我可以从任何位置调用它们,而无需输入我保存脚本的目录路径。一旦函数被添加到 `$profile` 文件中,每次 PowerShell 启动时都会加载这些函数,并且无需我进一步干预即可使用。由于我太懒得每次都输入完整的函数名,所以我还在 `$profile` 文件中为每个函数设置了一个简短的别名。对于不熟悉 PowerShell 的人来说,这很简单,如下所示:

Set-Alias nsc NewSaveCommand

使这一切正常工作的关键在于 PowerShell 有一个类似 `eval` 的函数。`Invoke-Expression` cmdlet 将通过管道或作为参数接收一个字符串,并将其作为 PowerShell 命令执行。这使您能够将命令保存到小的文本文件中,并在以后加载和执行该命令。

Using the Code

为了实现全部功能,需要四个函数。它们是:

  • NewSavedCommand
  • RemoveSavedCommand
  • GetSavedCommand
  • ExecuteSavedCommand

每个函数的作用从名称上应该很清楚,但它们的工作方式值得解释。

`NewSavedCommand` 将最后输入的命令(当然是在输入保存最后一个命令的命令之前)保存到与您的 PowerShell profile 文件相同的目录下的一个文本文件中。文件名形式为 `<number>.psc`,其中选择的数字是第一个未被占用的最小数字。这意味着,如果您有几个命令并开始删除它们,您添加的下一个命令将填充空白数字,而不是添加到末尾并留下间隙。

`RemoveSavedCommand` 将删除您不再想保留的已保存命令。这将释放命令编号,以便下一个您保存的命令可以再次使用。如果您向该函数传递一个负数,**所有**您已保存的命令都将被删除。您已被充分警告。

`GetSavedCommand` 可以打印所有已保存命令的列表,也可以打印特定已保存命令的完整文本。在截图[18]中,您可以看到传递给该函数(不带参数或带负参数)的结果。我的一个命令很长,超出了屏幕。要查看整个命令,我只需再次调用该函数并提供我想要查看的命令编号。这个命令是我在接下来的几周内可能会想调用的,您可以看到不必记住并重新输入整个命令有多么有用。

`ExecuteSavedCommand` 将要执行的命令编号作为参数,并读取 `<number>.psc` 的内容,然后将其传递给 `Invoke-Expression`。结果将是执行您复杂、精心制作的命令,而无需再次键入整个文本。

关注点

在我编写这些函数时,我遇到的一件有趣的事情是,无需预定义类和属性即可将输出格式化为表格。截图[20]中对 `GetSavedCommand` 的第一次调用显示了结果。下面是相应的代码:

Get-ChildItem (Split-Path $profile -parent) *.psc | 
    Format-Table @{Label='Number'; 
         Expression={[int]([System.IO.Path]::GetFileNameWithoutExtension($_.FullName))}},
         @{Label='Command'; Expression={Get-Content $_.FullName}} -auto

如果您不熟悉 PowerShell,以下是关于语法的一些说明。`@{}` 创建一个可以填充键值对的哈希表。分号用作分隔符,因为逗号已用于创建数组(创建数组不需要大括号或括号,只需用逗号分隔的值列表)。对于习惯于使用 C 风格语言进行编码的人来说,您可能会猜测 `Expression` 值是一个代码块,您猜对了。

`Format-Table` 是一个内置的 cmdlet,它允许您通过管道传递要格式化的对象,并指定属性作为参数。但是,如果您想显示不是属性的内容,则需要使用上面所示的哈希表语法。`Label` 是将显示在列顶部的名称,而 `Expression` 是一个计算该列值的代码块。`-auto` 参数只是告诉 cmdlet 自动调整列大小以避免大量空白。

有改进空间

创建函数后,我想到了几个潜在的改进,但我决定不为我自己的使用而实现它们。它们应该不难添加,如果多人觉得它们有用,我很乐意添加它们。

  • 能够保存的内容不仅仅是最后输入的命令。这可能通过将 `Get-History` cmdlet 返回的 ID 传递给 `NewSavedCommand` 函数来实现。
  • 能够将参数传递给已保存的命令。

历史

  • 2008 年 5 月 21 日
    • 初始版本。
© . All rights reserved.