【问题标题】:Adobe flash player powershell remote install problemAdobe flash player powershell远程安装问题
【发布时间】:2020-07-21 08:44:53
【问题描述】:

我正在尝试使用 PowerShell 开发一个脚本来远程安装/更新多台机器的 Flash 播放器。无论我做什么,我都无法让安装正常工作。我的工具非常有限,所以我必须使用 PowerShell 和 Flashplayer 的 MSI 安装。我将在下面发布我的脚本,任何帮助将不胜感激。

$Computers = Get-Content C:\Users\name\Desktop\flash.txt

(tried these 3 methods to install none work)
$install = @("/a","/i", "\\$Computer\c$\temp\flash\install_flash_player_32_plugin.msi", "/qn","/norestart")



Invoke-Command -ComputerName $Computer -ScriptBlock {Start-Process "Msiexec" -arg "$using:install" -Wait -PassThru} -Filepath msiexec.exe

    #This returns with "invoke-command: parameter set cannot be resolved using the specified named parameters"

Invoke-Command -ComputerName $computer -ScriptBlock {Start-Process -Filepath msiexec.exe "$using:install" -Wait -PassThru} -Filepath msiexec.exe

    #this returns the same error.

Invoke-Command -ComputerName $Computer -ScriptBlock {start-process msiexec -argumentlist @('/a','/i','"\\$Computer\c$\temp\flash\install_flash_player_32_plugin.msi"','/qn')}

    #this seemingly skips the install entirely. 

我为其他程序使用过类似的脚本,安装它们没有问题,但我使用或研究过的方法都没有正常工作。

【问题讨论】:

  • 更新:遇到此问题的任何其他人的最终脚本应如下所示。 $Computers = 获取内容 C:\Users\name\Desktop\flash.txt $params = '/i C:\temp\flash\install_flash_player_32_plugin.msi LANG_LIST=en_US /qb' $Computers | % { Invoke-Command -ScriptBlock { Param( [Parameter(Mandatory=$true,Position=0)] [String]$arguments ) return Start-Process msiexec.exe -ArgumentList $arguments -Wait -PassThru } -ComputerName $_ -参数列表 $params }
  • 您好 Tyler,如果您想添加进度更新,请编辑问题并将其添加到此处。

标签: powershell flash windows-installer powershell-remoting invoke-command


【解决方案1】:

这应该可以解决问题,我将在下面解释为什么它不起作用:

$Computers = Get-Content C:\Users\name\Desktop\flash.txt

$params = '/i <path to AcroPro.msi> LANG_LIST=en_US TRANSFORMS="1033.mst" /qb'

$Computers | % { 
    Invoke-Command -ScriptBlock {
        Param(
            [Parameter(Mandatory=$true,Position=0)]
            [String]$arguments
        )
        return Start-Process msiexec.exe -ArgumentList $arguments -Wait -PassThru
    }  -ComputerName $_ -ArgumentList $params 
}

因此,它不起作用,因为 Invoke-Command 上的 ScriptBlock 无法看到您在 powershell 会话中声明的变量,将其想象为您正在走向远程计算机并手动输入该代码,您不会有价值(比喻)。

我又做了一些改动:

  1. 我将所有参数都移到了 1 个字符串中,无需将它们放在数组中。
  2. 添加了$Computers | 以遍历计算机名称。
  3. 删除了 FilePath,因为它的使用方式不同,documentation(示例 #1)。
  4. $MinutesToWait 设置为您想要的任何分钟数。
  5. 不需要尝试传msiexec,因为windows自带默认路径是“C:\WINDOWS\system32\msiexec.exe”
  6. 添加了一个 return,尽管它从来没有必要,但为了使其更具可读性并表明您打算返回 msiexec 进程的输出。
  7. \\$Computer\c$ 替换为C:\,因为如果您指向正在运行命令的主机,则无需使用网络连接/

希望对你有帮助,祝你好运。

编辑:

所以,正如您提到的管道执行卡住了,我过去在为我的部门创建计算机准备脚本时遇到了这个问题,我所做的是使用作业来创建安装的并行执行,所以如果有一台计算机由于某种原因速度较慢或完全卡住并且永无止境,您可以识别它,请按原样尝试以下操作,看看它是如何工作的,然后进行替换:

#region ######## SetUp #######
$bannerInProgress = @"


#######################
#Jobs are still running
#######################
"@
$bannerDone = @"


##################################################
#DONE see results of finished installations bellow
##################################################
"@
#VARS TO SET
$MinutesToWait = 1
$computers = 1..10 | % {"qwerty"*$_} #REPLACE THIS WITH YOUR COMPUTER VALUES (Get-Content C:\Users\name\Desktop\flash.txt)
#endregion

#region ######## Main #######

#Start Jobs (REPLACE SCRIPTBLOCK OF JOB WITH YOUR INVOKE-COMMAND)
$jobs = [System.Collections.ArrayList]::new()
foreach($computer in $computers){
    $jobs.Add(
        (Start-Job -Name $computer -ScriptBlock {
            Param(
                [Parameter(Mandatory=$true, Position=0)]
                [String]$computer
            )
            Sleep -s (Get-Random -Minimum 5 -Maximum 200)
            $computer
        } -ArgumentList $computer)
    ) | Out-Null
}

$timer = [System.Diagnostics.Stopwatch]::new()
$timer.Start()
$acceptedWait = $MinutesToWait * 60 * 1000 # mins -> sec -> millis
$running = $true
do {
    cls
    $jobsRunning = $jobs | Where-Object State -EQ 'Running'
    if ($jobsRunning) {
        Write-Host $bannerInProgress
        foreach ($job in $jobsRunning) {
            Write-Host "The job `"$($job.Name)`" is still running. It started at $($job.PSBeginTime)"
        }
        Sleep -s 3
    } else {
        $running = $false
    }

    if($timer.ElapsedMilliseconds -ge $acceptedWait){
        $timer.Stop()
        Write-Host "Accepted time was reached, stopping all jobs still pending." -BackgroundColor Red
        $failed = @()
        foreach($job in $jobsRunning){
            $output = $job | Receive-Job
            $failed += [PsCustomObject]@{
                            "ComputerName" = $job.Name;
                            "Output" = $output;
                        }
            $job | Remove-Job -Force
            $jobs.Remove($job)
        }
        $failed | Export-Csv .\pendingInstallations.csv -NoTypeInformation -Force
        $running = $false
    }

}while($running)

Write-host $bannerDone
$results = @()
foreach($job in $jobs){
    $output = $job | Receive-Job
    $results += [PsCustomObject]@{
                    "ComputerName" = $job.Name;
                    "Output" = $output;
                }
}
$results | Export-Csv .\install.csv -NoTypeInformation -Force
#endregion

此脚本将触发 10 个只等待并返回其名称的作业,然后在您设置的时间内完成的作业被认为是正确的,而那些没有被认为是待处理的,两个组都被导出到CSV 供审查。您需要替换以下内容才能按预期工作:

  1. 在设置区域添加$params = '/i &lt;path to AcroPro.msi&gt; LANG_LIST=en_US TRANSFORMS="1033.mst" /qb'
  2. $computers 的声明替换为$computers = Get-Content C:\Users\name\Desktop\flash.txt
  3. Start-Job 脚本块的主体替换为 Invoke-command 来自此答案中代码的第一个 sn-p。

你应该最终得到类似的东西:

.
.code
.
$params = '/i <path to AcroPro.msi> LANG_LIST=en_US TRANSFORMS="1033.mst" /qb'
#VARS TO SET
$MinutesToWait = 1
$computers = Get-Content C:\Users\name\Desktop\flash.txt
#endregion

#region ######## Main #######

#Start Jobs
$jobs = [System.Collections.ArrayList]::new()
foreach($computer in $computers){
    $jobs.Add(
        (Start-Job -Name $computer -ScriptBlock {
            Param(
                [Parameter(Mandatory=$true, Position=0)]
                [String]$computer
            )
            Invoke-Command -ScriptBlock {
                Param(
                    [Parameter(Mandatory=$true,Position=0)]
                    [String]$arguments
                )
                return Start-Process msiexec.exe -ArgumentList $arguments -Wait -PassThru
            }  -ComputerName $computer -ArgumentList $params 
        } -ArgumentList $computer)
    ) | Out-Null
}
.
. code
.

我知道它看起来一团糟,但它确实有效。 希望对您有所帮助。

【讨论】:

  • 这绝对比我尝试过的任何其他方法都走得更远。它启动 msiexec 进程,但它似乎并没有实际安装。我猜它与参数有关。您认为添加日志记录会为我指明正确的方向吗?
  • 我发现参数需要看起来像这样 /i LANG_LIST=en_US TRANSFORMS="1033.mst" /qb
  • 进行了更改,但作为来自某人的经验的建议,这对于 IT 部门来说正是如此,测试您计算机中的参数,它很少会因为对您有用的相同参数而失败。
  • 尝试一下,如果有效,请不要忘记将其添加为答案,谢谢。
  • 它正在与从文本文件中提取的一台机器一起工作,但它不能与多个机器一起工作,它似乎被挂断了。知道为什么会这样吗?
猜你喜欢
  • 1970-01-01
  • 2016-02-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多