Function Install-WebExtension { <# .SYNOPSIS Install a WebExtension to the appropriate place (generally C:\orb\) .DESCRIPTION Install a WebExtension to the appropriate place. (generally C:\orb\) Will make certain assumptions based on best practices, such as locations to install to based on flags. .PARAMETER ExtensionName [string] The name of the extension. Will be used to build a dynamic path. Typically the package id. .PARAMETER SourcePath [string] The folder that contains the files. Typically a chocolatey path. .PARAMETER IsAdmin [switch] Is this package installed to admin? .PARAMETER RemoveLogs [switch] Remove logs if the service was running? .PARAMETER NoSymlink [switch] Override the machine settings for handling Symlinks? .INPUTS ExtensionName and SourcePath are required. .OUTPUTS Various diagnostic information about the install process .EXAMPLE Install-WebExtension -ExtensionName Alkami.Client.WebExtension.Example -SourcePath C:\ProgramData\chocolatey\lib\Alkami.Client.WebExtension.Example Various diagnostic information about the install process. #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, Position=0)] [string]$ExtensionName, [Parameter(Mandatory=$true, Position=1)] [string]$SourcePath, [switch]$isAdmin, [switch]$RemoveLogs, [Parameter(Mandatory = $false)] [switch]$NoSymlink ) process { $loglead = (Get-LogLeadName) if (!(Test-IsDeveloperMachine) -and !(Test-IsWebServer)) { Write-Warning "$loglead : Can not install WebExtensions on the app tier" return } if (!(Test-IsAdmin)){ throw "You are not running as administrator. Can not continue." } $usingSymlinkStrategy = $false # See if there is an override if($NoSymlink) { Write-Host "$loglead : Override provided! Skipping Symlink strategy." } else { $usingSymlinkStrategy = Test-InstallerUseSymlinkStrategy if($usingSymlinkStrategy) { Write-Host "$loglead : Using Symlink Installer Strategy." } else { Write-Host "$loglead : Using Legacy non-Symlink Installer Strategy" } } Write-Host "$loglead : $ExtensionName being installed by $($env:username) on $($env:computername) at $(Get-Date)" # Build the Source Path if (!(Test-Path $SourcePath)) { throw "Could not find the source path specified at $SourcePath" } # Append lib to the chocolatey directory # ex: c:\ProgramData\chocolatey\lib\Alkami.Sample.Service\lib $libSourcePath = (Join-Path $SourcePath 'lib') if (!(Test-Path $libSourcePath)) { throw "Could not find the lib folder path specified at $libSourcePath" } ## Write warning that more than one lib folder was detected # Go into the first subfolder. # ex: c:\ProgramData\chocolatey\lib\Alkami.Sample.Service\lib\net472 $libSourceFolderName = (Get-ChildItem $libSourcePath -Directory) | Sort-Object -Descending | Select-Object -First 1 $libSourceFolder = (Join-Path $libSourcePath $libSourceFolderName) if ((Get-ChildItem (Join-Path $libSourceFolder "*.dll")).Count -eq 0) { throw "Could not find any dll files under $libSourceFolder" } Write-Host "$loglead : Looks like we are ready to install $ExtensionName" $appName = 'WebClient' if ($isAdmin) { $appName = 'WebClientAdmin' } # Build the target path # ex: c:\orb\WebClient\Modules $moduleRootPath = Join-Path (Join-Path (Get-OrbPath) $appName) 'Modules' # ex: c:\orb\WebClient\Modules\Alkami.Sample.Service $orbExtensionPath = (Join-Path -Path $moduleRootPath -ChildPath $ExtensionName) $isRunning = (Test-IISAppPoolByName $appName) if ($isRunning) { Write-Host "$loglead : Stopping $appName" Stop-WebAppPool $appName Do { Start-Sleep -Milliseconds 100 } Until ((Get-WebAppPoolState -Name $appName).Value -eq "Stopped" ) } # Check if we're Removing logs and it was running (because there should be no new logs if it isn't running) if ($RemoveLogs -and $isRunning) { $logfiles = Get-LogPathsForOrbApplication $appName # Delete each log file. foreach($logPath in $logfiles) { if (Test-Path $logPath) { Remove-FileSystemItem $logPath -ErrorAction Stop } } } ## Clear .NET Temp files associated with the site $tempFilePath = (Get-SiteTempDirectoryPath $appName) if ($isRunning -and !([string]::IsNullOrWhiteSpace($tempFilePath)) -and (Test-Path $tempFilePath)) { Remove-FileSystemItem $tempFilePath -Recurse -ErrorAction Stop } # Always delete the target folder as we'll recreate it or symlink it below if (Test-Path $orbExtensionPath) { ## Update OrbCore manifest if it exists to say that I've removed these files from the folder Remove-FileSystemItem $orbExtensionPath -Recurse -ErrorAction Stop } ## This is because we are changing the way we path our extensions ## Originally people got to choose their own folder name, ex: Signalr ## We are changing the pattern to Alkami.Modules.SignalR for the folder name ## Therefore, if the old folder exists at the last part of the split, then we remove that folder too ## That way there's only one version of the module, assuming reasonable assumptions from developer discussions $badOldFolderName = ($ExtensionName -split '\.')[-1] $badOldFolderPath = (Join-Path (Join-Path (Join-Path (Get-OrbPath) $appName) 'Modules') $badOldFolderName) if (Test-Path $badOldFolderPath) { ## Update OrbCore manifest if it exists to say that I've removed these files from the folder Write-Host "I am removing all files from $badOldFolderPath because it is an old path." Remove-FileSystemItem $badOldFolderPath -Recurse -ErrorAction Stop } if($usingSymlinkStrategy) { # Setup Symlinks Write-Host "$loglead : In the block to do Symlinking" Write-Host "$loglead : Symlinking files from $libSourceFolder into Destination $moduleRootPath" New-Symlink -path $libSourceFolder -Destination $moduleRootPath -TargetName $ExtensionName } else { Write-Host "$loglead : In the block to do Copying." ## It should never exist because we deleted it but let's make sure it doesn't ... if (!(Test-Path $orbExtensionPath)) { (New-Item $orbExtensionPath -ItemType Directory) | Out-Null } Write-Host "$loglead : Copying contents of $libSourceFolder into Destination $orbExtensionPath" (Copy-Item -Path (Join-Path $libSourceFolder '*') -Destination $orbExtensionPath -Recurse -Force) | Out-Null } if ($isRunning) { Write-Host "$loglead : Starting $appName" Start-WebAppPool $appName } } }