我如何在远程Powershell会话中使用共享函数?

我有一些PowerShell脚本用于设置IIS Web应用程序,消息队列等

他们使用我们创build的一组共享函数库 – 因此每个脚本都以行开始

. .\common.ps1

引用共享库。 共享库包含一组函数,如Create-IisApplicationPoolCreate-MessageQueue等,然后从实际的脚本中调用它们。 这些脚本的问题是,您需要通过远程桌面login并在本地运行它们,因此我正在编写一些新的脚本,用于将代码部署到Amazon EC2实例,并使用Powershell远程处理在本地调用它们。

我无法解决的是如何使这个共享库在远程Powershell会话中可用。

这是一个简单的例子:

functions.ps1

 function Add-Title([string] $name) { "Mr. $name" } function Say-HelloWorld([string] $name = "World") { $computerName = $env:COMPUTERNAME $greeting = Add-Title($name) Write-Host "Hello, $greeting ($computerName)" } 

example.ps1

 . ./functions.ps1 $remoteUsername = "username" $remotePassword = "password" $remoteHostname = "172.16.0.100" $securePassword = ConvertTo-SecureString -AsPlainText -Force $remotePassword $cred = New-Object System.Management.Automation.PSCredential $remoteUsername, $securePassword Say-HelloWorld("Spolsky") 

在当地运行,这个工作很好 – 并且按照预期说:“您好,Spolsky先生(DYLAN_PC)”。

现在,如果我用这个远程脚本调用replaceSay-HelloWorld调用:

 Invoke-Command -computerName $remoteHostname -Credential $cred -ScriptBlock { Say-HelloWorld("Spolsky") } 

我得到的Powershell错误:

The term 'Say-HelloWorld' 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 co rrect and try again. + CategoryInfo : ObjectNotFound: (Say-HelloWorld:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException

显然,远程会话不能看到本地导入的function。

对于简单的函数,这个语法工作:

 Invoke-Command -computerName $remoteHostname -Credential $cred -ScriptBlock ${function:Add-Title } -argumentlist "Spolsky" 

但是这对于依赖于其他function的任何function都是失败的。

我已经使用PS- -Session尝试了各种各样的事情,并尝试将-Sessionparameter passing给Invoke-Command,但无法find任何方法来捕获可导入到远程会话的模块中的本地函数及其依赖关系。 任何帮助感激地收到!

这是一个老话题,但是所有的答案都比这个更全面。

 Import-Module .\Common.ps1 -Force # Now you can call common functions locally $commonFunctions = (Get-Command .\Common.ps1).ScriptContents Invoke-Command -Session $session -ArgumentList $commonFunctions -ScriptBlock { param($commonFunctions) Invoke-Expression $commonFunctions # Now you can call common functions on the remote computer } 

你说每个脚本都以. .\common.ps1 . .\common.ps1 ,但我没有看到它在您的示例脚本。 无论如何,如果你需要使用common.ps1中的函数,那么你必须把它放在远程机器可以访问的地方。

您可以像使用RDP会话一样使用Powershell中的redirect驱动器:

 New-PSSession SERVER1 -Cred $creds | Enter-PSSession . \\tsclient\c\common.ps1 

或者你可以把common.ps1放在networking共享上:

 . \\Server1\share\common.ps1 

或者,您可以将common.ps1上的内容粘贴到每个脚本中。

或者你可以把common.ps1放在远程机器的本地文件系统上。

当远程机器上的Powershellparsing器看到“。\ common.ps1”时,它试图从当前工作目录加载common.ps1,这可能是任何用户build立远程PS会话的主目录。

我会期望你需要复制functions.ps1在点源之前。 事实上,我可能会将两个脚本复制到相同的目录(例如通过C $ admin共享到\\server\C$\foo ),然后使用Invoke-Command远程调用C:\foo\example.ps1

我有完全一样的问题。 我假设它是在远程调用者的上下文中运行远程调用。 我设法通过为目标库提供一个完整的本地path作为variables,然后通过variables点源库来解决问题。

 function Get-ScriptDirectory { return Split-Path $script:MyInvocation.MyCommand.Path } function GetLocalFileName { param([string]$filename) return [system.io.path]::Combine((Get-ScriptDirectory),$filename) } # dot-source the library using full local name to get round problem with remote invocation $MYLIBRARY = GetLocalFileName "mylibrary.ps1" . $MYLIBRARY