ProgramUpdater.ps1, Teil 2

Function EnsureGuiName ($strFolder) { $strFolder = BackslashTrailToFolder($strFolder) [string]$strFolderGui = “Company.Program.Gui\” if ($strFolder.Length -lt $strFolderGui.Length) { [int]$intStartIx = 0 } else { [int]$intStartIx = $strFolder.Length$strFolderGui.Length }

if ($strFolder.Substring($intStartIx) -ne $strFolderGui) { $strFolder += $strFolderGui }

if ($strFolder.Substring(0, “D:\Websites\”.Length) -ne “D:\Websites\”) { $strFolder = “D:\Websites\” + $strFolder }

return $strFolder }

function Expand-File($file, $destination) { if ((Test-Path $destination) -eq $false) { New-Item -Path (Split-Path -Path $destination -Parent) -Name (Split-Path -Path $destination -Leaf) -ItemType directory | Out-Null }

$shell = new-object -com shell.application $zip = $shell.NameSpace($file) foreach($item in $zip.items()) { $shell.Namespace($destination).copyhere($item) } }

function TestRequirementFilesys($astrFileList, $strLog) { [bool]$blnResult = $true

For ($i=0; $i -lt ($astrFileList.Count); $i++) { Write-Host “Testing “ $astrFileList[$i] ” ... “ -NoNewline if ((Test-Path $astrFileList[$i]) -eq $false) { Add-Content -Value ($astrFileList[$i] + ” missing”) -Path $strLog Write-Host “`n” Throw ($astrFileList[$i] + ” missing”) $blnResult = $false } else { Write-Host “OK” } } if ($PSVersionTable.PSVersion.Major -lt 4) { Add-Content -Value “This script requires at least version 4 of PowerShell (in WMF 4, http://www.microsoft.com/en-us/download/details.aspx?id=40855)." -Path $strLog -PassThru $blnResult = $false } return $blnResult }

function GetDevExpressVersionFromProgramVersion($strNewVersion) { [int]$intProgMainVersion = ($strNewVersion.Split(”.”))[0]

switch ($intProgMainVersion)

{ 2 { return 9 } 3 { return 15 } } }

function GetFilePropTags([string]$strPath) { $objShell = New-Object -COMObject Shell.Application [string]$strFolder = Split-Path $strPath [string]$strFile = Split-Path $strPath -Leaf $objShellfolder = $objShell.Namespace($strFolder) $objShellfile = $objShellfolder.ParseName($strFile)

# To get a list of index numbers and their meaning, use this: # 0..287 | Foreach-Object { '{0} = {1}' -f $, $shellfolder.GetDetailsOf($null, $) }

[int]$intExtFilePropsTags = 18 $objShellfolder.GetDetailsOf($objShellfile, $intExtFilePropsTags) }

function GetMsiProdVer([string]$strPath) { $strTagsFromMsi = GetFilePropTags($strPath) [string[]]$astrFileTags = $strTagsFromMsi.Split(”,”) [int[]]$aintVno = ($astrFileTags[1]).split(”.”) [string]::Join(”.”, $aintVno) }

function GetDevExpressVersion([string]$strDevExpressFolder) { $dirDevExpress = Get-ChildItem $strDevExpressFolder *.dll ((Get-ItemProperty ($dirDevExpress[0].FullName)).VersionInfo).FileVersion }

#endregion

$hshProgramUpdaterSettings = Get-IniContent $IniFileUser $hshProgramUpdaterSettings += Get-IniContent $IniFileWebConfig

[string]$strDeploymentFolder = “D:\Websites\Deploy\” [string]$strLogFolder = $strDeploymentFolder + “UpdateLogs\” + (Get-Date -format “yyyyMMdd.HHmm”) + “h\” if ((Test-Path $strLogFolder) -eq $false) { New-Item -Path (Split-Path -Path $strLogFolder -Parent) -Name (Split-Path -Path $strLogFolder -Leaf) -ItemType directory | Out-Null } [string]$strLog = $strLogFolder + “ProgramUpdater + (Get-Date -format “yyyyMMddHHmm”) + “h.log”

if ( ( $hshProgramUpdaterSettings[“HeaderUser”][“Version”] -ne $strIniVersion ) -or ( $hshProgramUpdaterSettings[“HeaderWebConfig”][“Version”] -ne $strIniVersion ) ) { Add-Content -Value “Wrong version of at least 1 .ini.” -Path $strLog -PassThru Exit }

[string]$strVerMsSql = $hshProgramUpdaterSettings[“MssqlVersionen”][“DEFAULT”] [string]$strHostname = $env:COMPUTERNAME if ($null -ne $hshProgramUpdaterSettings[“MssqlVersionen”][$strHostname]) { $strVerMsSql = $hshProgramUpdaterSettings[“MssqlVersionen”][$strHostname] }

[string]$strWebsiteFolder = $hshProgramUpdaterSettings[“Website folder to Upgrade”][“Folder”] # $strWebsiteFolder.Trim(” “) while ( $strWebsiteFolder.EndsWith(” “) ) { $strWebsiteFolder = $strWebsiteFolder.Substring( 0, ($strWebsiteFolder.Length – 1) ) } $strWebsiteFolder = EnsureGuiName($strWebsiteFolder) [string]$strIISWebsiteName = (Get-Website | Where-Object -Property “PhysicalPath” -EQ -Value (FolderNameWoTrailingBackslash($strWebsiteFolder))).Name [string]$strIISAppPool = (Get-Item (“IIS:\Sites\” + $strIISWebsiteName) | Select-Object applicationPool).applicationPool [string]$strDeployZipFile = $strDeploymentFolder + “Company.Program.CC.Web.Gui.” + $strVerMsSql + ”.zip”

[string]$strOldVersion = ((Get-ItemProperty ($strWebsiteFolder + “bin\Company.Program.BusinessLogik.dll”)).VersionInfo).ProductVersion $msidir = Get-Item ($strDeploymentFolder + “Company.Program.Nb.Setup.” + $strVerMsSql + ”.*.msi”) [string]$strFirstMsiNewVer = $strDeploymentFolder + ($msidir[0].Name) [string]$strNewVersion = GetMsiProdVer($strFirstMsiNewVer) while ($null -eq $strNewVersion -or $strNewVersion -eq ””) { Write-Host “Die Zielversion konnte nicht aus $strFirstMsiNewVer ermittelt werden, bitte hier eingeben ('3.xx.x.xxxxx'):” -ForegroundColor Red $strNewVersion = Read-Host } [string]$strDevExpressFolder = $strDeploymentFolder + “DevExpress{0}\” -f (GetDevExpressVersionFromProgramVersion($strNewVersion)) [string]$strBackupFolder = FolderNameWoTrailingBackslash($strWebsiteFolder) $strBackupFolder += $strBackupFolder += $strOldVersion $strBackupFolder += $strBackupFolder += (Get-Date -format “yyyyMMdd.HHmm”) $strBackupFolder += “h\”

Write-Host -BackgroundColor Gray -ForegroundColor Blue -Object nnEffective Parameters for current run of this script” [string]$strThisScriptVersion = (Get-Help $PSCommandPath -Full).alertSet.alert[0] -split(“`n”) -match “Version: “ -replace(”}”,””)

$objParamTable = New-Object PSObject $objParamTable | Add-Member “Ini Files” ($IniFileUser + ”, “ + $IniFileWebConfig + ” — optional command line parameters”) $objParamTable | Add-Member “Website folder” $strWebsiteFolder $objParamTable | Add-Member “This script's version” $strThisScriptVersion $objParamTable | Add-Member “IIS website name” $strIISWebsiteName $objParamTable | Add-Member “IIS application pool name” $strIISAppPool $objParamTable | Add-Member “Old version” $strOldVersion $objParamTable | Add-Member “New version” $strNewVersion $objParamTable | Add-Member “MS SQL version” $strVerMsSql $objParamTable | Add-Member “Deploy folder” $strDeploymentFolder $objParamTable | Add-Member “Deploy zip file” $strDeployZipFile $objParamTable | Add-Member “DevExpress folder” $strDevExpressFolder $objParamTable | Add-Member “Backup folder” $strBackupFolder $objParamTable | Add-Member “Log folder” $strLogFolder $objParamTable | Format-List

[string[]]$astrFileList = ($strDeploymentFolder + .msi”) $astrFileList += ($strDeploymentFolder + “UpgradeTool-” + $strVerMsSql + ”.exe”) $astrFileList += $strDeployZipFile $astrFileList += ($strDevExpressFolder + “) $astrFileList += ($strWebsiteFolder + “*”) [bool]$blnResult = TestRequirementFilesys $astrFileList $strLog

if ($blnResult -eq $false) { Exit }

Write-Host -BackgroundColor Gray -ForegroundColor Blue -Object “If necessary, stop and run script again. Run '.\ProgramUpdater.ps1 –?' for more details.” Write-Host -BackgroundColor Gray -ForegroundColor Red -Object “If you don't understand what this script does read the <Program> installation guides.”

[string]$strTitle = “ProgramUpdater” [string]$strMessage = “Do you want to go on?” $yes = New-Object System.Management.Automation.Host.ChoiceDescription “&Yes”, <span style="color:#4070a0">"Go on."</span> <span style="color:#19177c">$no</span> = <span style="color:#06287e">New-Object</span> System.<span style="color:#06287e">Management</span>.<span style="color:#06287e">Automation</span>.<span style="color:#06287e">Host</span>.<span style="color:#06287e">ChoiceDescription</span> <span style="color:#4070a0">"&amp;No"</span>, “Exit the script.” $options = System.Management.Automation.Host.ChoiceDescription[] [int]$intResult = $host.ui.PromptForChoice($strTitle, $strMessage, $options, 1) switch ($intResult) { 1 {Exit} }

[string]$strFQDNThisMachine = [System.Net.Dns]::GetHostByName((hostname)).HostName Add-Content -Value (“Computer name (FQDN): “ + $strFQDNThisMachine) -Path $strLog Add-Content -Value (“Script starter: “ + $env:USERDOMAIN + “\” + $env:USERNAME) -Path $strLog Add-Content -Value (“Website folder: “ + $strWebsiteFolder) -Path $strLog Add-Content -Value (“Deploy folder: “ + $strDeploymentFolder) -Path $strLog Add-Content -Value (“Dev express folder: “ + $strDevExpressFolder) -Path $strLog Add-Content -Value (“Backup folder: “ + $strBackupFolder) -Path $strLog Add-Content -Value (“New version: “ + $strNewVersion) -Path $strLog Add-Content -Value (“IIS website name: “ + $strIISWebsiteName) -Path $strLog Add-Content -Value (“IIS application pool name: “ + $strIISAppPool) -Path $strLog Add-Content -Value (“MS SQL version: “ + $strVerMsSql) -Path $strLog Add-Content -Value (nn”) -Path $strLog

# Out-Null: Do not continue before this line has been completely executed Stop-Website -Name $strIISWebsiteName | Out-Null Stop-WebAppPool -Name $strIISAppPool | Out-Null Add-Content -Value (“Attempted to stop IIS website “ + $strIISWebsiteName + + (Get-Date -format “yyyyMMddHHmm”)) -Path $strLog -PassThru Add-Content -Value (“Attempted to stop IIS application pool “ + $strIISAppPool + + (Get-Date -format “yyyyMMddHHmm”)) -Path $strLog -PassThru

Add-Content -Value (“Attempting to ensure apppool” + $strIISAppPool + ” and website “ + $strIISWebsiteName + ” are stopped. _ “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

Add-Content -Value (“Apppool “ + $strIISAppPool + ” status: “ + (Get-WebAppPoolState $strIISAppPool).Value + ”. _ “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru Add-Content -Value (“Website “ + $strIISWebsiteName + ” status: “ + (Get-WebsiteState $strIISWebsiteName).Value + ”. _ “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

“Waiting” | Out-Null

[int]$intSec = 0 while ( ( (Get-WebAppPoolState $strIISAppPool).Value -ne “Stopped” ) -and ( (Get-WebsiteState $strIISWebsiteName).Value -ne “Stopped” ) ) { Start-Sleep 2 $intSec += 2 Add-Content -Value (“Waited “ + $intSec + ” of 60 seconds. _ “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru if ($intSec -eq 60) { Add-Content -Value (“apppool and website apparently still running, exiting. _ “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru Exit } }

[string]$strNewVerFolder = FolderNameWoTrailingBackslash($strWebsiteFolder) $strNewVerFolder += “_New\”

Expand-File -file $strDeployZipFile -destination $strNewVerFolder | Out-Null Add-Content -Value (“Unzipped “ + $strDeployZipFile + ” “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

Remove-Item -Path ($strWebsiteFolder + “bin\DevExpress) -Force -Recurse | Out-Null Add-Content -Value (“Deleted “ + $strWebsiteFolder + “bin\DevExpress “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

if ((Test-Path $strNewVerFolder) -eq $false) { New-Item -Path (Split-Path -Path $strNewVerFolder -Parent) -Name (Split-Path -Path $strNewVerFolder -Leaf) -ItemType directory | Out-Null } if ((Test-Path $strBackupFolder) -eq $false) { New-Item -Path (Split-Path -Path $strBackupFolder -Parent) -Name (Split-Path -Path $strBackupFolder -Leaf) -ItemType directory | Out-Null }

Copy-Item -Path ($strDevExpressFolder + ) -Destination ($strNewVerFolder + “bin”) -Force | Out-Null Add-Content -Value (“Copied “ + $strDevExpressFolder + “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

try { Move-Item -Path ($strWebsiteFolder + ) -Destination $strBackupFolder -Exclude “Log”,“Setup”,“Temp”,“logo” -Force -ErrorAction SilentlyContinue | Out-Null
} catch { } Add-Content -Value (“Moved “ + $strWebsiteFolder +
except Log\, Setup\, Temp\, logo\ “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

Copy-Item -Path ($strWebsiteFolder + “*”) -Destination $strBackupFolder -Force -Recurse | Out-Null Add-Content -Value (“Copied “ + $strWebsiteFolder + “\Log\, ...\Setup\, ...\Temp\, ...\logo\ “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

AdaptWebConfig $strNewVerFolder $strBackupFolder $strNewVersion $strLog $hshProgramUpdaterSettings

Remove-Item -Path ($strWebsiteFolder + “Setup\Company.Program.Nb.Setup..msi”) -Force | Out-Null Add-Content -Value (“Deleted “ + $strWebsiteFolder + “Setup\Company.Program.Nb.Setup..msi “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

[string]$strMsiCopyPath = $strWebsiteFolder + “Setup\msi” if ((Test-Path $strMsiCopyPath) -eq $false) { New-Item -Path (Split-Path -Path $strMsiCopyPath -Parent) -Name (Split-Path -Path $strMsiCopyPath -Leaf) -ItemType directory | Out-Null } else { Remove-Item -Path ($strMsiCopyPath + “\Company.Program.Nb.Setup.*.msi”) -Force | Out-Null }

[string]$strWebConfigMsiPath = $strMsiCopyPath + “\web.config” if ((Test-Path $strWebConfigMsiPath) -eq $false) { $strWebConfigMsiContent | Out-File $strWebConfigMsiPath -Force -Encoding utf8 [string]$strWebConfigMsiAttr = (Get-Item -Force $strWebConfigMsiPath).Attributes -join(”,”) if ($strWebConfigMsiAttr -notmatch(“Hidden”)) { (Get-Item -Force $strWebConfigMsiPath).Attributes = $strWebConfigMsiAttr + ”,Hidden” } Add-Content -Value (“Created “ + $strWebConfigMsiPath + ” “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru }

Add-Content -Value (“Deleted “ + $strWebsiteFolder + “Setup\msi\Company.Program.Nb.Setup.*.msi “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

Remove-Item -Path ($strWebsiteFolder + “Setup\UpgradeLog.txt”) -Force | Out-Null Add-Content -Value (“Deleted “ + $strWebsiteFolder + “Setup\UpgradeLog.txt “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

Remove-Item -Path ($strWebsiteFolder + “Setup\UpgradeTool-” + $strVerMsSql + ”.exe”) -Force | Out-Null Add-Content -Value (“Deleted “ + $strWebsiteFolder + “Setup\UpgradeTool-” + $strVerMsSql + ”.exe “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

Remove-Item -Path ($strWebsiteFolder + “Log*.) -Force | Out-Null Add-Content -Value (“Deleted “ + $strWebsiteFolder + “Log*. “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

while ((Get-ChildItem $strNewVerFolder).Length -gt 0) { Move-Item -Path ($strNewVerFolder + ) -Destination $strWebsiteFolder -Force -ErrorAction SilentlyContinue | Out-Null } Add-Content -Value (“Moved “ + $strNewVerFolder + “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

Remove-Item -Path ($strNewVerFolder) -Force -Recurse | Out-Null Add-Content -Value (“Deleted “ + $strNewVerFolder + ” “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

Copy-Item -Path ($strDeploymentFolder + “Company.Program.Nb.Setup.” + $strVerMsSql + .msi”) -Destination ($strWebsiteFolder + “Setup”) -Force | Out-Null Add-Content -Value (“Copied “ + $strDeploymentFolder + “Company.Program.Nb.Setup.” + $strVerMsSql + .msi to Setup\” + ” “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

Copy-Item -Path ($strDeploymentFolder + “Company.Program.Nb.Setup.” + $strVerMsSql + .msi”) -Destination ($strWebsiteFolder + “Setup\msi”) -Force | Out-Null Add-Content -Value (“Copied “ + $strDeploymentFolder + “Company.Program.Nb.Setup.” + $strVerMsSql + .msi to Setup\msi\” + ” “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

Copy-Item -Path ($strDeploymentFolder + “UpgradeTool-” + $strVerMsSql + ”.exe”) -Destination ($strWebsiteFolder + “Setup”) -Force | Out-Null Add-Content -Value (“Copied “ + $strDeploymentFolder + “UpgradeTool-” + $strVerMsSql + ”.exe” + ” “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

[string]$strTitle = “ProgramUpdater” [string]$strMessage = “Do you want the script to copy the path to the web.config to clipboard, for UpgradeTool? “ $strMessage += “This will overwrite current contents of clipboard.” $yes = New-Object System.Management.Automation.Host.ChoiceDescription “&Yes”, <span style="color:#4070a0">"Copy the path, overwrite the clipboard contents."</span> <span style="color:#19177c">$no</span> = <span style="color:#06287e">New-Object</span> System.<span style="color:#06287e">Management</span>.<span style="color:#06287e">Automation</span>.<span style="color:#06287e">Host</span>.<span style="color:#06287e">ChoiceDescription</span> <span style="color:#4070a0">"&amp;No"</span>, “Do not copy anything, just start the UpgradeTool.” $options = System.Management.Automation.Host.ChoiceDescription[] [int]$intResult = $host.ui.PromptForChoice($strTitle, $strMessage, $options, 0) switch ($intResult) { 0 { [Windows.Forms.Clipboard]::SetText($strWebsiteFolder + “web.config”) } }

$UpgradeToolPid = (Start-Process -FilePath ($strWebsiteFolder + “Setup\UpgradeTool-” + $strVerMsSql + ”.exe”) -Wait -PassThru).Id try { Wait-Process -Id $UpgradeToolPid -ErrorAction SilentlyContinue } catch {
}

Copy-Item -Path ($strWebsiteFolder + “Setup\UpgradeLog.txt”) -Destination ($strLogFolder) -Force | Out-Null

Start-Website -Name $strIISWebsiteName Start-WebAppPool -Name $strIISAppPool | Out-Null # “Started IIS website ” + $strIISWebsiteName + “ ” + (Get-Date -format “yyyyMMddHHmm”) -> PassThru # “Started IIS application pool ” + $strIISAppPool + “ ” + (Get-Date -format “yyyyMMddHHmm”) Add-Content -Value (“Attempting to start IIS website “ + $strIISWebsiteName + ” “ + (Get-Date -format “yyyyMMddHHmm”)) -Path $strLog -PassThru | Out-Null Add-Content -Value (“Attempting to start IIS application pool “ + $strIISAppPool + ” “ + (Get-Date -format “yyyyMMddHHmm”)) -Path $strLog -PassThru | Out-Null

“Waiting” | Out-Null

[int]$intSec = 0 while ( ( (Get-WebAppPoolState $strIISAppPool).Value -ne “Started” ) -and ( (Get-WebsiteState $strIISWebsiteName).Value -ne “Started” ) ) { Start-Sleep 2 $intSec += 2 Add-Content -Value (“Waited “ + $intSec + ” of 60 seconds. _ “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru if ($intSec -eq 60) { Add-Content -Value (“apppool and website not running, upgrader failed, result mail might fail. _ “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru break } }

Add-Content -Value (“Apppool “ + $strIISAppPool + ” status: “ + (Get-WebAppPoolState $strIISAppPool).Value + ”. _ “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru Add-Content -Value (“Website “ + $strIISWebsiteName + ” status: “ + (Get-WebsiteState $strIISWebsiteName).Value + ”. _ “ + (Get-Date -format “yyyyMMdd_HHmm”)) -Path $strLog -PassThru

$Error | Select-Object * | Out-File ($strLogFolder + “ProgramUpdater.errors” + (Get-Date -format “yyyyMMdd.HHmm”) + “h.log”)

MailResult $strLogFolder $hshProgramUpdaterSettings

}