Remote installation

Problem: Install Monitoring agent on a machine remotely, or if possible on many machines.

Started like this


$server = "server01"
$Package = "NSClient++-0.3.9-Win32.msi"
$Path = "\\fileserver\nsclient"

Copy-Item "$Path\$Package" -Destination \\$server\c$\windows\temp

$newProc=([WMICLASS]"\\$server\root\cimv2:win32_Process").Create("Msiexec /I C:\windows\temp\$Package")
If ($newProc.ReturnValue -eq 0)
{
   Write-Output "Installation spawned on $server"
}
else
{
   Write-Output "Could not start installation on $server"
}

Well that works.. But just for the hard coded stuff. Would be nice to have it reusable and as a function… Let’s try this…

function Install-NSClient
{
   Param
   {
      $server = "server01"
      $Package = "NSClient++-0.3.9-Win32.msi"
      $Path = "\\fileserver\nsclient"
   }

   Copy-Item "$Path\$Package" -Destination \\$server\c$\windows\temp

   $newProc=([WMICLASS]"\\$server\root\cimv2:win32_Process").Create("Msiexec /I C:\windows\temp\$Package")
   If ($newProc.ReturnValue -eq 0)
   {
      Write-Output "Installation spawned on $server"
   }
   else
   {
      Write-Output "Could not start installation on $server"
   }
}

I’m still not satisfied… Let’s make it more like a Cmdlet… Let’s do this instead…

<#
.SYNOPSIS
Installs NSClient++ on Windows clients.
.DESCRIPTION
Installs NSClient++ and Copys the latest configuration file and script files to the client.
.PARAMETER ComputerName
Computer(s) to install NSCLient++ on.
.PARAMETER Path
Path to where installation media is located.
Don't change this unless you know what you are doing!
.PARAMETER Package64
Name of 64-bit MSI package.
Don't change this unless you know what you are doing!
.PARAMETER Package32
Name of 32-bit MSI package.
Don't change this unless you know what you are doing!
.PARAMETER Parameters
Extra parameters to be sent to the MSI package.
Don't change this unless you know what you are doing!
.EXAMPLE
Install-NSClients -ComputerName server01
Installs NSClient++ on server server01.
.EXAMPLE
Install-NSClients -ComputerName server01 -Verbose
Installs NSClient++ on server server01 and write each step to the console window.
.EXAMPLE
Install-NSClients -ComputerName server01,server02
Installs NSClient++ on server server01 and server02.
.EXAMPLE
Install-NSClient -ComputerName (Get-Content .\servers.txt)
Installs NSClient++ to all servers in the file servers.txt.
#>
function Install-NSClient
{
    [CmdletBinding()]
    Param
    (
        [Parameter (Mandatory=$true,ValueFromPipeLineByPropertyName=$true)]
        [string[]]$ComputerName,
        [string]$Path="\\fileserver\NSClient",
        [string]$Package64="NSClient++-0.3.9-x64.msi",
        [string]$Package32="NSClient++-0.3.9-Win32.msi",
        [string]$Parameters="/quiet /norestart"
    )

    Process
    {
       foreach ( $server in $ComputerName )
       {
            Write-Verbose "Server: $server"
            Write-Verbose "Check OS Architecture"
            If (Test-Path "\\$server\c$\Program Files (x86)")
            {
                Write-Verbose "Will use 64-bit package"
                $Package = $Package64
            }
            else
            {
                Write-Verbose "Will use 32-bit package"
                $Package = $Package32
            }

            Write-Verbose "Copy install media locally"
            Copy-Item "$Path\$Package" -Destination \\$server\c$\windows\temp

            Write-Verbose "Start installation"
            $newProc=([WMICLASS]"\\$server\root\cimv2:win32_Process").Create("Msiexec /I C:\windows\temp\$Package")

            If ($newProc.ReturnValue -eq 0) 
            { 
                Write-Verbose "Wait for Service to be created"
                While (!(Get-service -ComputerName $server nsclientpp -ErrorAction SilentlyContinue )){}
                Write-Verbose "Service have been created"
                Write-Verbose "Push Configuration to the server"
                Set-NSClientSettings -ComputerName $server -Verbose:$VerbosePreference
                Write-Verbose "Installation Completed"
            } 
            else 
            { 
                Write-Error "Could not start installation on $Server, error code $newProc.ReturnValue"
            }
       }
    }
}

Now we have a function that takes input from the pipeline, can use -Verbose, it checks to see if it’s 32 or 64-bit and it also implements an endless loop if installation fails after it have been spawned :)

While (!(Get-service -ComputerName $server nsclientpp -ErrorAction SilentlyContinue )){}

That line will never end if the installation fails, maybe a timer of some sort could be used, like, while service not created OR timer not elapsed, do nothing…

Leave a Reply

Your email address will not be published. Required fields are marked *