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 }
$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 “n
nEffective 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">"&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 (“n
n”) -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">"&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
}