среда, 30 июня 2010 г.

Удаленная установка UltraVNC с драйвером

Не стану говорить о том, почему мне понадобилось это сделать. Факт в том, что понадобилось. Попросту говоря, понадобилось ПО с этим функционалом, но бесплатное. После длительных размышлений выбор пал именно на UltraVNC. Попробую пояснить почему. Хотелось решение, в котором есть возможность использовать видеодрайвер, так называемый mirror driver, благодаря которому работа с решением с точки зрения клиентской машины значительно ускоряется. Проще говоря производительность сервера с драйвером раз в 5-7 выше, нежели без драйвера. А учитывая порой плачевное состояние парка машин, это условие было, пожалуй, очень важным. Драйвер такой есть у нескольких производителей. Однако RealVNC не дает его с бесплатной версией а TightVNC находится в какой-то странной бете, а я бетам не доверяю. Может быть незаслуженно, но это все таки бета.

Итак, решение принято, приступаем к установке. После долгих мучений я решил забросить попытки проинсталлировать программу на удаленных машинах при помощи стандартного инсталлятора. Причиной тому являются две вещи. Первая – как я не пытался это отключить, инсталлятор  пытается скачать видеодрайвер и затыкается на этом. И вторая – сразу после инсталляции запускается программа для администрирования и задания пароля на подключение к VNC. С правами пользователя происходит вообще странная штука. При запуске толи службы, толи приложения в трее окно настроек не появляется, зато появляется ошибка, говорящая о том что пароль не задан. Потом значок в трее пропадает и спустя секунду появляется снова, и снова всплывает окно с ошибкой.

В общем, наиболее удачных подхода, на мой взгляд два. Либо создать msi пакет, либо, согласно этой документации, проделать все вручную. Краткая информация по поводу создания MSI есть тут. С моей точки зрения этот способ все же наиболее удачный, несмотря на сложности с его реализацией.

Прежде все займемся созданием MSI при помощи, например UltraVNC MSI Creator. По сути дела это пакет WiX с готовым набором конфигурационных файлов для создания пакета. Тут все достаточно просто. После распаковки вы увидите несколько bat файлов, при помощи которых и создается пакет. Однако не все гладко. Сценарий, в моем случае, завершает свое выполнение с ошибкой:

== Entering GetACL
== Error 183: RegOpenKeyEx

Так я и не понял в чем проблема. Error 183 – по идее это “file already exists”. Но что конкретно “already exists” я так и не понял. В прринципе это не очень важно. Судя по всему эту ошибку выдает вторая строка скрипта, а именно утилита MSLogonACL. Все это как-то связано с доменной аутентификацией. Однако по моему мнению она тут не очень нужна. Мало ли какие проблемы могут быть у клиента. Вдруг в этот момент она не работает. В общем и целом на этом шаге создается конфигурационный ini файл для VNC сервера и в принципе второй шаг, а соответственно и ошибку можно вполне опустить.

Следующим этапом будет собственно генерация MSI пакета при помощи второго скрипта.

Итак, пакет сгенерирован, что же дальше? Самым главным в нашей сегодняшней работе будет не только установка VNC сервера, но и установка mirror driver, который ускорит работу сервера. Для этого нам понадобятся собственно сами файлы драйвера, утилита devcon и утилита CertMgr.exe, которую можно взять в windows sdk. Тут два момента. Если мы будем просто устанавливать драйвер, то на клиентской машине появится окно с предупреждением о то что драйвер подписан неизвестным ключем и просьбой нажать на кнопку. Поэтому в нашу задачу входит достать этот ключ и импортировать его прежде, чем устанавливать драйвер. Делаем это так:

 

 

Теперь у нас есть все что нам надо. Алгоритм дальнейших действий прост. Нужно установить на клиентскую машину сертификат, затем драйвер и потом собственно UltraVNC. Для упрощения процесса пишем скрипт:

$ErrorActionPreference = "SilentlyContinue"

#путь к папке с инсталляционными файлами
$fileserver = '\\server\!uvnc'

$uvncMSI =             "$fileserver\UltraVNC.msi" #MSI пакет
$uvnccert =         "$fileserver\cert.cer" #сертификат
$certmgr =             "$fileserver\CertMgr.Exe" #утилита управления сертификатами
$devcon =             "$fileserver\devcon.exe" #управление драйверами
#собственно драйверы
$drivers =            "$fileserver\mv2.sys","$fileserver\mv2.inf","$fileserver\mv2.dll","$fileserver\mv2.cat"

#пользователь и пароль.
#необходимо для установки
#если в этих строках есть пробелы, строку необходимо заключить в
#двойные кавычки
$username = 'domain\administrator'
$password = '"xxx xxx"'

#собственно установка UVNC
function installUVNC () {
PROCESS{
$name = $_.name
Write-Host "УСТАНОВКА $uvncMSI" -ForegroundColor Blue
psexec  -u $username -p $password -i  "\\$name" msiexec /i $uvncMSI /quiet
Write-Output $_
}
}

#проверка связи
function Ping-Address {
PROCESS {
$ping = $false
$name = $_.name
Write-Host "PINGING $name" -NoNewline
if (Test-Connection -ComputerName $name -Count 1 -ErrorAction SilentlyContinue) {
Write-Host " PING OK" -ForegroundColor Green
return $_} 
else 
{Write-Host " PING FAILED" -ForegroundColor Red}
}
}

#получение системного каталога
function getWindowsDirectory ($computername){
gwmi win32_operatingsystem -Property windowsdirectory, systemdrive -ComputerName $computername | Select-Object windowsdirectory, systemdrive}

#установка сертификата    
function installCertificate {
PROCESS {
#копируем сертификат
Write-Host 'КОПИРУЮТСЯ СЕРТИФИКАТ И УТИЛИТА CERTMGR' -ForegroundColor Blue
$name = $_.name
Copy-Item $uvnccert,$certmgr "\\$name\admin$"
Write-Host '    СЕРТИФИКАТ СКОПИРОВАН' -ForegroundColor Green
$win = getWindowsDirectory $name
$windowsDir = $win.windowsdirectory
$systemDrive = $win.systemdrive
Write-Host '    УСТАНОВКА СЕРТИФИКАТА' -ForegroundColor Blue
psexec  -i  "\\$name" certmgr.exe -add "$windowsDir\cert.cer" -c -s -r localMachine TrustedPublisher
Write-Output $_

}
}

#установка драйвера
function installDriver {
PROCESS {
Write-Host ' КОПИРУЮТСЯ ДРАЙВЕРЫ И УТИЛИТА DEVCON' -ForegroundColor Blue
$name = $_.name
Copy-Item $devcon "\\$name\admin$"
Write-Host '    $devcon УСПЕШНО СКОПИРОВАН' -ForegroundColor Green
Copy-Item $drivers "\\$name\admin$"
Write-Host '    $drivers УСПЕШНО СКОПИРОВАНЫ' -ForegroundColor Green
$win = getWindowsDirectory $name
$windowsDir = $win.windowsdirectory
$systemDrive = $win.systemdrive
Write-Host '    УСТАНОВКА ДРАЙВЕРОВ' -ForegroundColor Blue
psexec  -i  "\\$name" devcon.exe install "$windowsDir\mv2.inf" mv_hook_display_driver2
Write-Output $_
}
}

cls
#список компьютеров
# можно использовать Get-QADcomputer от quest software
# примерно так Get-QADcomputer -Name "*" | Select-Object name

$computers  = @{name='testVM'} 
$computers | Ping-Address | installCertificate | installDriver | installUVNC

Теперь о том, как этим скриптом пользоваться. Все настройки заданы в переменных вначале скрипта. В первую очередь это $fileserver, указывающий путь к папке с файлами, затем $uvncMSI, $uvnccert, $certmgr, $devcon, $drivers. Соответствующие файлы необходимо положить по указанным путям. Параметры с именем пользователя и паролем прокомментированы.

PS.

Это, скажем так, измененная версия скрипта. Как оказалось, предыдущая версия, в том виде, в котором она была опубликована, не принимала список компьютеров на входе. По сути дела она была заточена на использование Get-QADcomputer. Я немного изменил этот момент, теперь, в примере ниже, можно использовать просто список:

$ErrorActionPreference = "SilentlyContinue"

#путь к папке с инсталляционными файлами
$fileserver = '\\server\!uvnc'

$uvncMSI =             "$fileserver\UltraVNC.msi" #MSI пакет
$uvnccert =         "$fileserver\cert.cer" #сертификат
$certmgr =             "$fileserver\CertMgr.Exe" #утилита управления сертификатами
$devcon =             "$fileserver\devcon.exe" #управление драйверами
#собственно драйверы
$drivers =            "$fileserver\mv2.sys","$fileserver\mv2.inf","$fileserver\mv2.dll","$fileserver\mv2.cat"

#пользователь и пароль.
#необходимо для установки
#если в этих строках есть пробелы, строку необходимо заключить в
#двойные кавычки
$username = 'domain\administrator'
$password = '"xxx xxx"'

#собственно установка UVNC
function installUVNC () {
PROCESS{
$name = $_.name
Write-Host "УСТАНОВКА $uvncMSI" -ForegroundColor Blue
psexec  -u $username -p $password -i  "\\$name" msiexec /i $uvncMSI /quiet
Write-Output $_
}
}

#проверка связи
function Ping-Address {
PROCESS {
$ping = $false
$name = $_.name
Write-Host "PINGING $name" -NoNewline
if (Test-Connection -ComputerName $name -Count 1 -ErrorAction SilentlyContinue) {
Write-Host " PING OK" -ForegroundColor Green
return $_} 
else 
{Write-Host " PING FAILED" -ForegroundColor Red}
}
}

#получение системного каталога
function getWindowsDirectory ($computername){
gwmi win32_operatingsystem -Property windowsdirectory, systemdrive -ComputerName $computername | Select-Object windowsdirectory, systemdrive}

#установка сертификата    
function installCertificate {
PROCESS {
#копируем сертификат
Write-Host 'КОПИРУЮТСЯ СЕРТИФИКАТ И УТИЛИТА CERTMGR' -ForegroundColor Blue
$name = $_.name
Copy-Item $uvnccert,$certmgr "\\$name\admin$"
Write-Host '    СЕРТИФИКАТ СКОПИРОВАН' -ForegroundColor Green
$win = getWindowsDirectory $name
$windowsDir = $win.windowsdirectory
$systemDrive = $win.systemdrive
Write-Host '    УСТАНОВКА СЕРТИФИКАТА' -ForegroundColor Blue
psexec  -i  "\\$name" certmgr.exe -add "$windowsDir\cert.cer" -c -s -r localMachine TrustedPublisher
Write-Output $_

}
}

#установка драйвера
function installDriver {
PROCESS {
Write-Host ' КОПИРУЮТСЯ ДРАЙВЕРЫ И УТИЛИТА DEVCON' -ForegroundColor Blue
$name = $_.name
Copy-Item $devcon "\\$name\admin$"
Write-Host '    $devcon УСПЕШНО СКОПИРОВАН' -ForegroundColor Green
Copy-Item $drivers "\\$name\admin$"
Write-Host '    $drivers УСПЕШНО СКОПИРОВАНЫ' -ForegroundColor Green
$win = getWindowsDirectory $name
$windowsDir = $win.windowsdirectory
$systemDrive = $win.systemdrive
Write-Host '    УСТАНОВКА ДРАЙВЕРОВ' -ForegroundColor Blue
psexec  -i  "\\$name" devcon.exe install "$windowsDir\mv2.inf" mv_hook_display_driver2
Write-Output $_
}
}

cls

# можно использовать Get-QADcomputer от quest software
# примерно так Get-QADcomputer -Name "*" | Select-Object name | Ping-Address | installCertificate | installDriver | installUVNC

$computers  = "server1","server2","server3" #список компьютеров

[System.Collections.ArrayList]$comps2 = New-Object System.Collections.ArrayList #преобразованный список с подходящим форматом

foreach ($item in $computers){
$obj = New-Object System.Object
$obj | Add-Member -MemberType NoteProperty -Name name -Value $item
$comps2+=$obj
}
$comps2 | Ping-Address | installCertificate | installDriver | installUVNC

Вот, собственно, и все.

Отправить комментарий