【问题标题】:Running a uninstaller as administrator remotely over Powershell通过 Powershell 以管理员身份远程运行卸载程序
【发布时间】:2015-11-27 13:20:21
【问题描述】:

我正在开发一个小型软件部署脚本,该脚本使用 powershell 远程卸载和安装 Check_MK 的新版本。

一切都很好——我能够本地化旧服务,停止它并确定它的安装路径。问题是运行服务的“uninstall.exe”。

这可以通过在使用凭据参数的服务器上使用 Powershell 会话记录来轻松完成。

$passwd = convertto-securestring -AsPlainText -Force -String "password"
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist "domain\user",$passwd
$session = new-pssession -computername "192.xxx.xxx.xxx" -credential $cred
Enter-PSSession $session

问题是您不能在脚本中使用 PSSession - 它是供个人使用而不是自动化的。

所以我尝试使用 Powershells Invoke-Command cmdlet。

Invoke-Command -Computername "192.xxx.xxx.xxx" -credential $cred -argumentlist $cred -ScriptBlock {
    # Lots of stuff and enter uninstall directory

    uninstall.exe /S
}

调用 exe 文件以查询管理员凭据结束。

我还尝试远程启动提升的 Powershell 会话并将其用于卸载..

Start-Process powershell -Credential $cred

使用提升的 Powershell 会话执行位于服务器上以启动 uninstall.exe 的脚本以 UAC 查询结束(不是查询凭据,而是要求执行)。

还有其他解决方案可以解决这个问题吗?我尝试了更多,但没有任何效果。

【问题讨论】:

  • $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist "domain\user",$passwd 你在“argumentlist”中有错字。也许这是错误...
  • 看不到任何错字? $cred 对象也可以工作,因为我可以通过 PSSession 成功登录计算机。
  • 现在我明白了。粘贴在这里只是失败 - 脚本中的代码是可以的。
  • invoke-commandpssession 作为参数,因此无需重新输入计算机名、凭据等
  • 问题是我必须为 40 到 50 台机器这样做,我不想为每台机器启动 PSSession。

标签: powershell credentials runas invoke-command start-process


【解决方案1】:

这是另一种方法,使用计划任务。

使用登录的用户凭据在本地创建任务,当然您必须在远程计算机上具有管理员权限。

Function Run-RemoteCommand
{

Param(

[Parameter(Mandatory = $true)]
[String]
$Computer,

[Parameter(Mandatory = $true)]
[String]
$Task,

[Switch]
$Background

)

$TaskName = "TempTask"
$Explorer=gwmi win32_process -ComputerName $Computer | ? {$_.ProcessName -eq "explorer.exe" }
$OWner = $Explorer.GetOwner().Domain + "\" + $Explorer.GetOwner().User
if ($Background)
{
$Create = "SCHTASKS /Create /TN ""$TaskName"" /RU System /TR ""$Task"" /SC Once /ST 22:30"
}
Else
{
$Create = "SCHTASKS /Create /TN ""$TaskName"" /RU $Owner /TR ""$Task"" /SC Once /ST 22:30"
}
$Runit = "SCHTASKS /Run /TN ""$TaskName"""
$Delete = "SCHTASKS /Delete /TN ""$TaskName"" /F"
$WMI = Get-WmiObject -List Win32_Process -ComputerName $Computer 
$WMI.Create($Create)
$WMI.Create($Runit)
Sleep 2
$WMI.Create($Delete)
}

运行它:

Run-RemoteCommand -Computer "192.xxx.xxx.xxx" -Task 'c:\path\uninstall.exe /S'

如果你想以 'NT AUTHORITY\SYSTEM' 运行它,请添加 -Background 开关

【讨论】:

  • 我尝试了你的代码,我得到了 3 大块输出,包括进程 ID 等等。但看起来uninstall.exe 没有执行。检查 $OWner 给了我我的凭据 - 一切都很好:/
【解决方案2】:

最好的方法是始终让本地 shell 以提升的用户身份运行。这使您无需在脚本中提供凭据即可启动调用命令。

一旦您以管理用户身份运行 Powershell,您就可以使用 invoke-command 运行您的脚本。我一直这样做。

如果您要安排此任务,则必须让该任务以提升的用户身份运行。这又使您不必在脚本中以纯文本形式输入密码。

【讨论】:

    【解决方案3】:

    你没有提到这是否在域上下文中。

    如果它在域上下文中,您可以使用组策略对象中的启动脚本来实现您的目标。它将在工作站下次重新启动时执行。

    您也可以在没有组策略的情况下执行此操作,但这意味着单独访问每台计算机并更改本地组策略对象 - 此时,您不妨只运行 powershell 脚本。

    另一种解决方案:您可以创建一个 .zap 文件并使用组策略的软件部署功能进行部署。这有点滥用系统。 .zap 文件旨在安装未打包在 MSI 文件中的软件,但您也可以使用它来启动卸载您的软件的脚本。通常,.zap 文件无法卸载。

    第三种选择:从http://www.chocolatey.org 下载 Chocolatey。这是一个 PowerShell 脚本,可以为您管理许多标准软件的安装。在每个工作站上将其配置为自动运行(使用调度程序左右)。为您的软件创建一个 NuGet 包(NuGet 是 Chocolatey 在后台运行的),并根据需要使用 Chocolatey 部署或取消部署您的软件。

    顺便说一句,您可能需要考虑将其转换为 MSI 文件,而不是滚动您自己的安装程序 - 这些文件可以轻松安装和卸载,甚至可以远程安装,无需过多的 UAC 麻烦。您也可以使用 NullSoft 安装程序,但这些安装程序更难远程自动化。 MSI 是微软官方的安装方式。

    有些人也围绕标准 .exe 类型的安装程序创建 MSI 包装器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-29
      • 2023-01-24
      • 2011-02-18
      • 1970-01-01
      • 1970-01-01
      • 2021-11-10
      • 2017-08-23
      • 1970-01-01
      相关资源
      最近更新 更多