2009-04-18 74 views
15

假设您是一位系统管理员,他使用PowerShell来管理他/她系统上的很多事情。从某个目录将所有函数加载到PowerShell中

您可能已经编写了很多功能,可以执行您经常需要检查的功能。但是,如果你需要大量移动,大量使用不同的机器等,则必须一次又一次地重新输入所有功能才能使用它们。我甚至必须这样做,每次我退出并重新启动PowerShell出于某种原因,因为它不会记住这些函数...

我已经写了一个函数来为我做这件事。我在这里发布,因为我想确保它是万无一失的。函数本身存储在allFunctions.ps1中,这就是为什么我将它排除在代码中的原因。

其基本思想是你有一个文件夹,你可以在其中存储你所有的ps1文件,每个文件夹都包含一个函数。在PowerShell中,你去到该目录,然后输入:

. .\allFunctions.ps1 

该脚本的内容是这样的:

[string]$items = Get-ChildItem -Path . -Exclude allFunctions.ps1 
$itemlist = $items.split(" ") 
foreach($item in $itemlist) 
{ 
    . $item 
} 

该脚本将首先收集在你的目录所有文件,这意味着所有非ps1文件,你也可能在那里。 allFunctions.ps1将被排除。

然后我根据空间分割长字符串,这是常见的分隔符。然后我用Foreach循环遍历它,每次将函数初始化为PowerShell。

假设你有超过100个功能,你永远不知道你需要哪些,哪些不需要?为什么不把他们全部输入而不是挑剔?

所以我想知道,这里可能会出现什么问题?我希望这是非常安全的,因为我可能会使用它很多。

回答

15

将它们包含在PowerShell配置文件中,以便每次启动PS时它们都会自动加载。

查看Windows PowerShell Profiles了解更多关于在哪里可以找到您的个人资料脚本的信息。

PS默认您的配置文件到您的“我的文档”文件夹。 Mine位于网络驱动器上,因此在我登录的任何位置,PowerShell指向相同的配置文件文件夹。

6

功能明智我认为有几种方法可以改善您的脚本。

首先,您的脚本依赖于脚本的名称不变。虽然我不认为你可能会改变这个剧本的名字,但你永远不会知道几年后你会有什么样的心情。相反,为什么不动态地计算脚本的名称。

$scriptName = split-path -leaf $MyInvocation.MyCommand.Definition 

下一个问题是,我相信你是分裂功能将失败,如果你曾经将目录放在一个包含空格的路径。它会导致像“c:\ foo bar \ baz.ps1”这样的路径显示为“c:\ foo”,“bar \ baz.ps1”。更好地移除分割,并使用get-childitem命令的枚举。

此外,您正在对当前包含脚本的路径进行依赖。你应该做一个明确的参数或使用包含allFunctions.ps1文件的路径(我更喜欢后者)

这是我将使用的更新版本。

$scriptName = split-path -leaf $MyInvocation.MyCommand.Definition 
$rootPath = split-path -parent $MyInvocation.MyCommand.Definition 
$scripts = gci -re $rootPath -in *.ps1 | ?{ $_.Name -ne $scriptName } 
foreach ($item in $scripts) { 
    . $item.FullName 
} 

从安全角度来看,您必须考虑恶意用户向目标目录中添加坏脚本的可能性。如果他们这样做,它会与您的allFunctions.ps1文件一起执行,并可能损坏计算机。但是在恶意用户可以访问文件系统的时候,他们可能会在没有脚本的帮助下做到这一点,所以这可能是一个小问题。

+0

他似乎喜欢在PS中使用字符串进行翻译:) – Joey 2009-04-18 17:38:55

+0

感谢您的帮助,您提到了一些好的一点。实际上,入侵的黑客可能会造成更多的伤害。 另外,约翰,这不是我喜欢PS中的字符串,我更喜欢设置变量类型,当用户输入一个字符串应该是的数字时,会抛出一个错误,而不是脚本仍然尝试做某事用它。 – KdgDev 2009-04-18 17:41:59

+1

Get-ChildItem将返回FileInfo/DirectoryInfo对象的集合。没办法,你可以尝试在那里使用数字。 – Joey 2009-04-18 17:43:46

10

你可以用更简单的方法来做到这一点。我在我的个人资料中有:

##------------------------------------------- 
## Load Script Libraries 
##------------------------------------------- 
Get-ChildItem ($lib_home + "*.ps1") | ForEach-Object {& (Join-Path $lib_home $_.Name)} | Out-Null 

其中$ lib_home是存储我想要自动包含的脚本的文件夹。在这种情况下,它执行它们。所以我有脚本定义全局函数。您也可以点出它们的源代码(将“&”替换为“。”)。

0

简单的解决方案:

$Path - file location 
$Name - exluded file 

Get-ChildItem -Path $Path | Where {$_.psIsContainer -eq $false}|Where { $_.Name -like "*.ps1" }|Where { $_.Name -ne $Name }|foreach-object -process {.$_.FullName}|out-null 

read all object|file only| powershell file only|exclude file $Name| run ...|out-null 
0

另一个解决方案是功能组合成一个模块(PSM1)文件并导入与所述导入模块命令。如上所述,您可以将Import-Module命令添加到您的配置文件中,但语法更为简单。

一个简单的启动方法是在WindowsPowerShell目录中创建一个名为Modules的文件夹。在该文件夹中用您的模块名称创建另一个文件夹。你的psm1文件保存在这里。然后将Import-Module ModuleName.psm1添加到WindowsPowerShell目录中的配置文件。如果您想使用其他配置文件或将您的模块保存在其他位置,则需要相应地操作路径。

另一个提示是对模块文件中的每个函数使用Export-ModuleMember FunctionName。这会掩盖您可能分发给此用户的最终用户的支持功能。

相关问题