Назад | Перейти на главную страницу

Удаленная установка msi на серверах Citrix с помощью WMI

Хорошо, я программист на C #, который пытается упростить развертывание унаследованного мною приложения формы Windows и построил установщик для WiX (это приложение нужно будет регулярно переустанавливать, поскольку я вношу в него изменения). На самом деле я не привык к админскому типу вещей (или vbs, или WMI, или терминальные серверы, или Citrix, и даже WiX и MSI - это не то, с чем я обычно имею дело), ​​но пока я собрал несколько vbs и поставил конечную цель в уме. MSI действительно работает, и я установил его с подключенного диска O: на моем компьютере разработчика, а RDP - на компьютер Citrix.

Конечная цель: Разверните код, написанный на моей машине разработчика и скомпилированный в MSI (который я могу улучшить в рамках WiX и того, что позволяет Windows Installer Engine) в кластере машин Citrix, к которым у моих пользователей есть доступ.

Что мне не хватает в моем сценарии для выполнения MSI на удаленных машинах?

Макет:

Сценарий:

'Set WMI Constants
Const wbemImpersonationLevelImpersonate = 3
Const wbemAuthenticationLevelPktPrivacy = 6

'Set whether this is installing to the debug Citrix Servers
Const isDebug = true

'Set MSI location
'Network location yields error 1619 (This installation package could not be opened.)
msiLocation = "\\255.255.255.255\odrive\Citrix Deployment\Setup.msi"
'Directory on machine A yields error 3 (file not found)
'msiLocation = "C:\Temp\Deploy\Setup.msi"
'Mapped network drive (on both machines) yield error 3 (file not found)
'msiLocation = "O:\Citrix Deployment\Setup.msi"

'Set login information
strDomain = "MyDomain" 
Wscript.StdOut.Write "user name:"
strUser = Wscript.StdIn.ReadLine 
Set objPassword = CreateObject("ScriptPW.Password")
Wscript.StdOut.Write "password:"
strPassword = objPassword.GetPassword()

'Names of Citrix Servers
Dim citrixServerArray
If isDebug Then
    citrixServerArray = array("C4")
Else
    'citrixServerArray = array("C1","C2","C3","C5","C6")
End If

'Loop through each Citrix Server
For Each citrixServer in citrixServerArray

    'Login to remote computer
    Set objLocator = CreateObject("WbemScripting.SWbemLocator")
    Set objWMIService = objLocator.ConnectServer(citrixServer, _
        "root\cimv2", _
         strUser, _
         strPassword, _
         "MS_409", _
         "ntlmdomain:" + strDomain)

    'Set Remote Impersonation level
    objWMIService.Security_.ImpersonationLevel = wbemImpersonationLevelImpersonate
    objWMIService.Security_.AuthenticationLevel = wbemAuthenticationLevelPktPrivacy

    'Reference to a process on the machine
    Dim objProcess : Set objProcess = objWMIService.Get("Win32_Process")

    'Change user to install for terminal services
    errReturn = objProcess.Create _
        ("cmd.exe /c change user /install", Null, Null, intProcessID)   
    WScript.Echo errReturn

    'Install MSI here
    'Reference to a product on the machine
    Set objSoftware = objWMIService.Get("Win32_Product")
    'All users set in option parameter, I'm led to believe that the third parameter is actually ignored
    'http://www.webmasterkb.com/Uwe/Forum.aspx/vbscript/2433/Installing-programs-with-VbScript
    errReturn = objSoftware.Install(msiLocation,"ALLUSERS=2 REBOOT=ReallySuppress",True)
    Wscript.Echo errReturn

    'Change user back to execute
    errReturn = objProcess.Create _
        ("cmd.exe /c change user /execute", Null, Null, intProcessID)
    WScript.Echo errReturn

Next

Я также пробовал использовать это для установки, он не возвращает код ошибки, но и не устанавливает msi, и это заставляет меня задаться вопросом, действительно ли работает команда change user / install.

errReturn = objProcess.Create _
    ("cmd.exe /c msiexec /i ""O:\Citrix Deployment\Setup.msi"" /quiet")
Wscript.Echo errReturn

@tony Файл копируется нормально, но потом я получаю следующее:

ERROR:
Code = 0x80070005
Description = Access is denied.
Facility = Win32

Мне нужно использовать другую учетную запись пользователя (хотя и тот же домен) для компьютеров Citrix, поэтому я использовал:

Set objLocator = CreateObject("WbemScripting.SWbemLocator")
Set objWMIService = objLocator.ConnectServer( .....

Наконец, я использовал для этого сценарий PowerShell, основанный на вводе и предложении Тони, и он выглядит и действует намного чище.

Хотя получение метода установки класса Win32_Product по-прежнему выглядит немного запутанным (по сравнению с командой WMIC), но это то, что предлагает Technet:

http://blogs.msdn.com/b/wmi/archive/2010/01/06/wmic-vs-wmi-powershell-cmdlets.aspx http://technet.microsoft.com/en-us/library/dd347651.aspx

#$servers = 'C1' , 'C2', 'C3' , 'C5', 'C6'
$servers = , 'C4'
$MyCredential = Get-Credential MyDomain\otherusername

foreach($server in $servers)
{
    Copy-Item -LiteralPath C:\Temp\Deploy\Setup.msi -Destination \\$server\c$\Temp\Setup.msi -Force
    (Get-WmiObject -ComputerName $server -Credential $MyCredential -List | `
    Where-Object -FilterScript {$_.Name -eq "Win32_Product"}).Install("C:\TEMP\Setup.msi")
}

во-первых, у Citrix есть собственная технология развертывания, во-вторых, вы говорите, что ваш метод развертывания каким-то образом не работает? Если так, я полагаю, что это проблема выдачи себя за другое лицо. Но я не могу точно сказать из вашего объяснения.

Ниже приведен ярлык для всего кода, который у вас есть
1-й
скопировать file.msi \ citrixservername \ c $ \ pathtoyourfile

wmic / node: citrixservername product call install true, "", "c: \ PathToYour \ File.msi"

обратите внимание, что установочный файл копируется локально на сервер 1st, если вы этого не сделаете, у вас возникнет проблема с олицетворением!