TFS Release Remote Deploy

Team Service Erweiterung – Remote Deploy

Mit dem Remote Deploy Tool stellen Sie mithilfe von Windows Remote Management (WinRM) für PowerShell eine Verbindung zu den Host-Computern her, Deinstallieren und installieren Sie Ihr MSI Paket. Zusätzlich enthält das Skript noch die Ausführung von SQL Skripte für die Aktualisierung der Datenbank.

Über den folgenden Link bekommen Sie das komplette Paket als ZIP bereitgestellt. Das Skript ist kostenfrei und kann nach Ihren wünschen angepasst werden. Donload Remote Deploy Team Service extensions

f89cfef33b7c9dd537f5affcb4b4d296

ToDos:

Folgende Parameter können Sie mitgeben:

  • Server: Full Qualified Name des Servers (MeinServer.Domaende.de)
  • Admin Login: User der lokale Administrationsrechte besitzt (Domaende\Admin)
  • Password: Passwort des Administrators
  • Application URL / Name: Applikationsname für Protokollierung und SQL DB Name
  • MSI Name: MSI Name (Setup.msi)
  • Target Folder: MSI Ablageverzeichnis auf dem Zielsystem
  • Action: Abhängig von der Tätigkeit haben Sie die Auswahl MSI Uninstall, MSI Install, SQL Run.
  • MSI Arguments: MSI Parameter, z.B.
    INSTALLLOCATION=“$(WebIISRoot)\$(RELEASE.ENVIRONMENTNAME)“
    MSINEWINSTANCE=$(MSINEWINSTANCE)
    TRANSFORMS=$(TRANSFORMS)
    INSTALLATIONMODE=$(INSTALLATIONMODE)
    INSTALLATIONURL=“$(RELEASE.ENVIRONMENTNAME)“
    DATABASSERVERNAME=“$(SQLServer)“
    DATABASSERVERPORT=“$(SQLServerPort)“
    DATABASENAME=“$(RELEASE.ENVIRONMENTNAME)“
    DATABASEUSER=“$(RELEASE.ENVIRONMENTNAME)“
    DATABASEUSERPASSWORD=“$(AppSQLUserPassword)“
    DATABSEENCRYPTION=“$(SQLDBEncryption)“
    LOGDIR=“$(WebLogDir)\$(RELEASE.ENVIRONMENTNAME)“
    ENABLEDLOGFILES=“$(ENABLEDLOGFILES)“
Team Service Erweiterung Deploy
Team Service Erweiterung Deploy MSI Install
Team Service Erweiterung Deploy
Team Service Erweiterung Deploy MSI Uninstall
Team Service Erweiterung Deploy
Team Service Erweiterung Deploy SQL
param (
    [string]$Machine,
    [string]$AdminUserName,
    [string]$AdminPassword,
	[string]$DBName,
	[string]$Action,
	[string]$MSIFolderOrCode,
    [string]$AppName,
    [string]$MSIName
	[string]$TargetFolder,
	[string]$MSIArguments,
	[int]$Timeout
)
		
if($Timeout -NOTmatch "[1-9]"){$Timeout = 300}

Write-Output "Machine Name - $Machine"
Write-Output "Admin User Name - $AdminUserName"
Write-Output "Admin User Password - **********"
Write-Output "Application Name - $AppName"
Write-Output "Database Name - $DBName"
Write-Output "Action selected - $Action"
Write-Output "MSI Path or productcode - $MSIFolderOrCode"
Write-Output "MSI Path - $MSIPath"
Write-Output "Target Folder - $TargetFolder"
Write-Output "MSI Arguments - $MSIArguments"
Write-Output "Timeout in sec - $Timeout"

Write-Output "Start RemoteConnection"

$pass = ConvertTo-SecureString -AsPlainText $AdminPassword -Force
$credential = new-object -typename System.Management.Automation.PSCredential -argumentlist $AdminUserName,$pass

# Deploy
Write-Output "Deploy"
Invoke-Command -ComputerName $Machine -credential $credential -ScriptBlock {

    param (
		[string]$Machine,
		[string]$AdminUserName,
		[string]$AdminPassword,
        [string]$AppName,
		[string]$DBName,
        [string]$AppVersion,
        [string]$Action,
        [string]$MSIName,
		[string]$TargetFolder,
        [string]$MSIArguments,
        [int]$Timeout
	)
    
    $DataStamp = get-date -Format yyyyMMddTHHmmss
	
	$MSIArguments = $MSIArguments -replace "`t|`n|`r"," "

	$timeouted = $null 
     
    if ($Action -eq "uninstall")
    {
        Write-Output "Uninstall App - ($AppName)......."  
		
		$uninstall = 0

		# Check productcode and MSI exists
		if ($MSIFolderOrCode -like "{*}"){		
			$properties = "identifyingnumber","name","vendor","version"
			Get-ChildItem HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\*\Products | ForEach-Object {
				$root  = $_.PsPath
				$_.GetSubKeyNames() | ForEach-Object {
					try {
						$RegKeyPath = (Join-Path -Path (Join-Path -Path $root -ChildPath $_) -ChildPath InstallProperties)
						$obj = Get-ItemProperty -Path $RegKeyPath -ErrorAction Stop
						if ($obj.UninstallString) {
							$guid = ($obj.UninstallString -replace "msiexec\.exe\s/[IX]{1}","")
							if($guid -eq $MSIFolderOrCode){
								Write-Output "Uninstall guid: " + $guid 
								Write-Output "Uninstall version: " + $obj.DisplayVersion 
								Write-Output "Uninstall name: " + $obj.DisplayName 
								Write-Output "Uninstall vendor: " + $obj.Publisher 
								
								$obj = ''
								$uninstall = 1
							}
						}
					} catch {
					}
				}
			}
		}
		elseif ($MSIFolderOrCode -like "*\*.msi") {  
			if (Test-Path $MSIFolderOrCode) {
				$uninstall = 1
			}
		}
		# Uninstall
		if($uninstall -eq 1){				
				$logFile = '"'+$AppName+'-'+$AppVersion+'-Uninstall-' + $DataStamp+'.log"' 
				$arguments = '/q /x ' + $MSIFolderOrCode + ' /passive ' + $MSIArguments + ' /l*v ' + $logFile

				$output = 'Start-Process "msiexec.exe" -ArgumentList ' + $arguments + ' -PassThru'
				Write-Output $output   

				$Request = Start-Process "msiexec.exe" -ArgumentList $arguments -PassThru
								
				$Request | Wait-Process -Timeout $Timeout
				If ($($Request.ExitCode) -eq '0')
				{
					Write-Output "$AppName uninstalled successfully!"
				}
				else{
					Write-Error -Message "$AppName failed to uninstall with exit error: $($Request.ExitCode)"
				}
				Write-Output "Request: $Request"
			}
		}
		else{
			Write-Error 'MSI or productcode not found: $MSIFolderOrCode'
		}
    }
	
    if ($Action -eq "install")
    {
        Write-Output "Install App - ($AppName)......."  
        
		$msi = $TargetFolder + '\' + $MSIName
		# Check MSI exists
		if (Test-Path $msi) {
			$logFile = '"'+$TargetFolder+'\'+$AppName+'-'+$AppVersion+'-Install-' + $DataStamp+'.log"'
			$arguments = '/q /i "' + $msi + '" ALLUSERS="ALLUSERS" /passive ' + $MSIArguments + ' /l*v ' + $logFile

			$output = 'Start-Process "msiexec.exe" -ArgumentList ' + $arguments + ' -PassThru'
			Write-Output $output

			$Request = Start-Process "msiexec.exe" -ArgumentList $arguments -PassThru
			
			$Request | Wait-Process -Timeout $Timeout
			If($($Request.ExitCode) -eq '0')
			{
				Write-Output "$AppName installed successfully!"
			}
			else{
				Write-Error -Message "$AppName failed to install with exit error: $($Request.ExitCode)"
			}
		}
		else{
			Write-Error 'MSI not found: $msi'
		}
    }
	
	if ($Action -eq "sql")
    {
        Write-Output "Run SQL Script - ($AppName)......."  
		
        Write-Output "Provide modul sqlps in powershell"
        import-module "sqlps" -DisableNameChecking
		
		# Check SQL files and run
		if (Test-Path $TargetFolder) {
            # Dateien suchen und ausfuehren            
            Write-Output "SQL file search: $TargetFolder\*.slq"
            $files = Get-ChildItem "$TargetFolder\*.sql" -Recurse | Select-Object Name, Fullname | Sort-Object Name
            foreach  ($file in $files){
                try{
                    Write-Output "Script run: invoke-sqlcmd -ServerInstance $Machine -Database $DBName -InputFile $file.FullName -QueryTimeout $Timeout -ConnectionTimeout $Timeout  -ErrorAction 'Stop'"
                    invoke-sqlcmd -ServerInstance $Machine -Database $DBName -InputFile $file.FullName -QueryTimeout $Timeout -ConnectionTimeout $Timeout  -ErrorAction 'Stop'
                }
                catch{
                    Write-Error "Error in script: " + $file.FullName
                    Write-Error $error -foregroundcolor red
                }
            }    
        }
		else{
			Write-Error 'SQL path not found: $TargetFolder'
		}
    }	
} -ArgumentList ($Machine, $AdminUserName, $AdminPassword, $AppName, $DBName, $AppVersion, $Action, $MSIName, $TargetFolder, $MSIArguments, $Timeout)


Weitere Infos:

Release Management

Team Service Erweiterung – Application Pool Start / Stop

Team Service Erweiterung – Download Artifacts

Team Service Erweiterung – Deploy