Powershell 在远程服务器中安装软件时调用命令出现问题

Powershell 在远程服务器中安装软件时调用命令出现问题,powershell,parameters,powershell-3.0,powershell-remoting,Powershell,Parameters,Powershell 3.0,Powershell Remoting,我需要在安静模式下在几个远程服务器上安装一个应用程序。我使用Powershell v3.0创建了一个脚本Installer.ps1,如下所示: param( [String] $ServerNameFilePath = $(throw "Provide the path of text file which contains the server names"), [String] $InstallerFolderPath = $(throw "Provide the Installer Fol

我需要在安静模式下在几个远程服务器上安装一个应用程序。我使用Powershell v3.0创建了一个脚本Installer.ps1,如下所示:

param(
[String] $ServerNameFilePath = $(throw "Provide the path of text file which contains the server names"),
[String] $InstallerFolderPath = $(throw "Provide the Installer Folder Path. This should be a network location"),
[String] $UserName = $(throw "Provide the User Name"),
[String] $Password= $(throw "Provide the Password")
)
Function InstallApp
{
    $secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force
    $mycreds = New-Object System.Management.Automation.PSCredential ($UserName, $secpasswd)

    $ScrBlock = {param($InstallerFolderPath) $ExePath = Join-Path $InstallerFolderPath "ServerReleaseManager.exe";  & $ExePath /q;}
    Invoke-Command -ComputerName (Get-Content Servers.txt) -Credential $mycreds $ScrBlock -ArgumentList $InstallerFolderPath

}

InstallApp -ServerNameFilePath $ServerNameFilePath -InstallerFolderPath $InstallerFolderPath -UserName $UserName -Password $Password
然后我调用下面这样的脚本安装程序文件夹路径可以有空格,可执行文件ServerReleaseManager.exe接受参数:

.\Installer.ps1 -ServerNameFilePath Servers.txt -InstallerFolderPath "\\TestServer01\Public\Stable Applications\Server Release Manager Update 2\2.7" -UserName "Domain\User" -Password "Test123"
我总是在下面命令NotFoundException:

我尝试过其他选项,比如在Invoke命令中使用-FilePath,但出现了相同的错误。我在这里真的被堵住了。你能告诉我为什么会出现这个错误吗?如何解决错误?或者有没有更好的方法来处理这个问题。谢谢你的帮助。

这听起来像是一个双跳身份验证问题。一旦您被远程连接到服务器,您就无法访问第三台服务器上的文件共享,因为您无法将基于kerberos的身份验证传递给它

您可以尝试从共享复制到远程服务器,首先必须在执行脚本的计算机上执行,然后在脚本块中引用现在的本地路径

你可以,这不是一个好主意

基本上,您需要避免连接到一台机器,然后通过该连接连接到另一台机器

实现我所描述的变通方法的代码: param [String]$ServerNameFilePath=$throw提供包含服务器名称的文本文件的路径, [String]$InstallerFolderPath=$throw提供安装程序文件夹路径。这应该是一个网络位置, [String]$UserName=$throw提供用户名, [字符串]$Password=$throw提供密码 函数InstallApp { $secpasswd=converttosecurestring$Password-AsPlainText-Force $mycreds=New Object System.Management.Automation.PSCredential$UserName,$secpasswd $ScrBlock={param$InstallerFolderPath$ExePath=加入路径$InstallerFolderPath ServerReleaseManager.exe;&$ExePath/q;} 获取Content Servers.txt | ForEach项{ $remoteDest=\\$\uc`$\some\temp\folder $localDest=C:\some\temp\folder |连接路径-ChildPath$InstallerFolderPath |分割路径-Leaf 试一试{ 复制项目-路径$InstallerFolderPath-目标$dest-强制 调用命令-ComputerName$\凭证$mycreds$ScrBlock-ArgumentList$localDest 最后{ 删除项目$remoteDest-Force-ErrorAction忽略 } } } InstallApp-ServerNameFilePath$ServerNameFilePath-InstallerFolderPath$InstallerFolderPath-UserName$UserName-Password$Password 笔记 这是未经测试的。 正如Swonkie所提到的,如果您希望实现的目标在我的代码中没有提到,那么您应该将参数设置为强制参数。 您不应传递单独的纯文本用户名和密码参数,然后将其转换为凭据对象。而应传递单个[PSCredential]参数。您可以使用默认值进行提示,如[PSCredential]$Cred=Get credential。我的代码中也没有解决这一问题。
所需的状态配置可用于在目标机器上安装软件。我认为这可以解决双跳问题

顺便说一句-不要因为缺少必需参数而抛出错误。让PowerShell来处理这个问题-它对用户更友好:

param(
    [parameter(Mandatory=$true)] [string] $ServerNameFilePath,
    [parameter(Mandatory=$true)] [string] $InstallerFolderPath,
    [parameter(Mandatory=$true)] [string] $UserName,
    [parameter(Mandatory=$true)] [string] $Password
)

在这里,我为列表中的每台服务器创建了一个新的PSsession,并使用invoke命令以该服务器的会话为目标。我已经在我的环境中对其进行了测试,它成功地在我的远程服务器上安装了带有a/q开关的exe应用程序

但是,此方法不会告诉您命令是否在远程端成功运行,您必须登录到服务器或执行到所安装文件的预期位置的测试路径以进行验证。此外,PSsessions将保持打开状态,直到启动该命令的控制台关闭。如果PSsession在安装完成之前结束s、 安装将失败

Function InstallApp {

    param(
        [parameter(Mandatory=$true)] [String] $ServerNameFilePath,
        [parameter(Mandatory=$true)] [String] $InstallerFilePath,
        [parameter(Mandatory=$true)] [String] $CommandArgument,
        [parameter(Mandatory=$true)] [String] $UserName,
        [parameter(Mandatory=$true)] [String] $Password
    )

    $secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force
    $mycreds = New-Object System.Management.Automation.PSCredential ($UserName, $secpasswd)

    Get-Content $ServerNameFilePath | ForEach-Object {
        $remoteSession = new-PSSession $_ -Credential $mycreds
        Invoke-command -Session $remoteSession -Scriptblock {& ($args[0]) @($args[1])} -ArgumentList $InstallerFilePath,$CommandArgument 
    }
}

InstallApp -ServerNameFilePath $ServerNameFilePath -InstallerFilePath $InstallerFilePath -CommandArgument $CommandArgument -UserName $UserName -Password $Password

我看到的一个问题是,您有-ComputerName Get Content Servers.txt,我想您希望它是-ComputerName Get Content$ServerNameFilePathyes..这是一个错误..但它不能解决问题,您没有显示-ScriptBlock参数…我必须检查,但可能它有位置问题。在的中使用参数名$ScrBlock like-ScriptBlock$ScrBlock会有帮助。在您的参数集中,它是位置0,但它正在位置1中查找它。尝试使用-ScriptBlock谢谢您的建议。但我以前也尝试过。运气不好。您确定路径吗?包括服务器名称。您是否验证文件确实位于该位置?CredSSP为not设置在我们的服务器中。我不允许这样做。这就是为什么我使用-Authentication CredSSP,我得到以下错误:WinRM客户端无法处理请求。计算机策略不允许将用户凭据委派到目标计算机。有没有其他方法解决此问题?没有灵丹妙药。正如我所说,您可以将文件复制到远程服务器
r,然后使用指向服务器路径的本地路径引用它们。如果您没有更改策略或配置的权限,则您的选项是有限的。Edited可能会回答一些详细信息。DSC更容易出现双跳问题,因为它始终使用远程处理,即使在推送模式下也是如此。在这里看到我的答案:据我所知,这是一个在目标机器上运行的服务,它实际上使用提供者对目标机器进行更改,并且不会使用创建配置的用户的凭据。链接答案下的评论也提到了类似的内容。
Function InstallApp {

    param(
        [parameter(Mandatory=$true)] [String] $ServerNameFilePath,
        [parameter(Mandatory=$true)] [String] $InstallerFilePath,
        [parameter(Mandatory=$true)] [String] $CommandArgument,
        [parameter(Mandatory=$true)] [String] $UserName,
        [parameter(Mandatory=$true)] [String] $Password
    )

    $secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force
    $mycreds = New-Object System.Management.Automation.PSCredential ($UserName, $secpasswd)

    Get-Content $ServerNameFilePath | ForEach-Object {
        $remoteSession = new-PSSession $_ -Credential $mycreds
        Invoke-command -Session $remoteSession -Scriptblock {& ($args[0]) @($args[1])} -ArgumentList $InstallerFilePath,$CommandArgument 
    }
}

InstallApp -ServerNameFilePath $ServerNameFilePath -InstallerFilePath $InstallerFilePath -CommandArgument $CommandArgument -UserName $UserName -Password $Password