PowerShell Gallery | ContainerHandling/New-NavImage.ps1 6.0.19 (2024)

ContainerHandling/New-NavImage.ps1

<#
.Synopsis
Create or refresh NAV/BC image
.Description
Creates a new image based on artifacts and a base image
The function returns the imagename of the image created
.Parameter artifactUrl
Url for application artifact to use
.Parameter imageName
Name of the image getting build. Default is myimage:<tag describing version>.
.Parameter baseImage
BaseImage to use. Default is using Get-BestGenericImage to get the best generic image to use.
.Parameter databaseBackupPath
Path to database backup to use in place of Cronus backup. By default database backup from manifest is used. This parameter can be used to override this and use your custom backup.
.Parameter registryCredential
Credentials for the registry for baseImage if you are using a private registry (incl. bcinsider)
.Parameter isolation
Isolation mode for the image build process (default is process if baseImage OS matches host OS)
.Parameter memory
Memory allocated for building image. 8G is default.
.Parameter myScripts
This allows you to specify a number of scripts you want to copy to the c:\run\my folder in the container (override functionality)
.Parameter skipDatabase
Adding this parameter creates an image without a database
.Parameter filesOnly
Include this switch to create a filesOnly container. A filesOnly container does not contain SQL Server, IIS or the ServiceTier, it only contains the files from BC in the same locations as a normal container.
A FilesOnly container can be used to compile apps and it can be used as a proxy container for an online Business Central environment
.Parameter multitenant
Adding this parameter creates an image with multitenancy
.Parameter addFontsFromPath
Enumerate all fonts from this path or array of paths and install them in the container
.Parameter runSandboxAsOnPrem
This parameter will attempt to run sandbox artifacts as onprem (will only work with version 18 and later)
.Parameter populateBuildFolder
Adding this parameter causes the function to populate this folder with DOCKERFILE and other files needed to build the image instead of building the image
.Parameter additionalLabels
additionalLabels can contain an array of additional labels for the image
#>

functionNew-BcImage{
Param(
[Parameter(Mandatory=$true)]
[string]$artifactUrl,
[string]$imageName="myimage",
[string]$baseImage="",
[string]$databaseBackupPath="",
[PSCredential]$registryCredential,
[ValidateSet('','process','hyperv')]
[string]$isolation="",
[string]$memory="",
$myScripts=@(),
[switch]$skipDatabase,
[switch]$multitenant,
[switch]$filesOnly,
[string[]]$addFontsFromPath=@(""),
[string]$licenseFile="",
[switch]$includeTestToolkit,
[switch]$includeTestLibrariesOnly,
[switch]$includeTestFrameworkOnly,
[switch]$includePerformanceToolkit,
[switch]$skipIfImageAlreadyExists,
[switch]$runSandboxAsOnPrem,
[string]$populateBuildFolder="",
[string[]]$additionalLabels=@(),
$allImages
)

functionRoboCopyFiles{
Param(
[string]$source,
[string]$destination,
[string]$files="*",
[switch]$e
)

Write-Host$source
if($e){
RoboCopy"$source""$destination""$files"/e/NFL/NDL/NJH/NJS/nc/ns/np/mt/z/nooffload|Out-Null
Get-ChildItem-Path$source-Filter$files-Recurse|ForEach-Object{
$destPath=Join-Path$destination$_.FullName.Substring($source.Length)
while(!(Test-Path$destPath)){
Write-Host"Waiting for $destPath to be available"
Start-Sleep-Seconds1
}
}
}
else{
RoboCopy"$source""$destination""$files"/NFL/NDL/NJH/NJS/nc/ns/np/mt/z/nooffload|Out-Null
Get-ChildItem-Path$source-Filter$files|ForEach-Object{
$destPath=Join-Path$destination$_.FullName.Substring($source.Length)
while(!(Test-Path$destPath)){
Write-Host"Waiting for $destPath to be available"
Start-Sleep-Seconds1
}
}
}
}

$telemetryScope=InitTelemetryScope`
-name$MyInvocation.InvocationName`
-parameterValues$PSBoundParameters`
-includeParameters@("containerName","artifactUrl","isolation","imageName","baseImage","registryCredential","multitenant","filesOnly")
try{

if($memory-eq""){
$memory="8G"
}

$imageName=$imageName.ToLowerInvariant()

$myScripts|ForEach-Object{
if($_-is[string]){
if($_.StartsWith("https://","OrdinalIgnoreCase")-or$_.StartsWith("http://","OrdinalIgnoreCase")){
}elseif(!(Test-Path$_)){
throw"Script directory or file $_ does not exist"
}
}elseif($_-isnot[Hashtable]){
throw"Illegal value in myScripts"
}
}

$os=(Get-CimInstanceWin32_OperatingSystem)
if($os.OSType-ne18-or!$os.Version.StartsWith("10.0.")){
throw"Unknown Host Operating System"
}
$UBR=(Get-ItemProperty'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'-NameUBR).UBR

$hostOsVersion=[System.Version]::Parse("$($os.Version).$UBR")
$hostOs="Unknown/Insider build"
$bestGenericImageName=Get-BestGenericImageName-onlyMatchingBuilds-filesOnly:$filesOnly
$isServerHost=$os.ProductType-eq3

if("$baseImage"-eq""){
if("$bestGenericImageName"-eq""){
$bestGenericImageName=Get-BestGenericImageName-filesOnly:$filesOnly
Write-Host"WARNING: Unable to find matching generic image for your host OS. Using $bestGenericImageName"
}
$baseImage=$bestGenericImageName
}

if($os.BuildNumber-eq22631){
$hostOs="23H2"
}
elseif($os.BuildNumber-eq22621){
$hostOs="22H2"
}
elseif($os.BuildNumber-eq22000){
$hostOs="21H2"
}
elseif($os.BuildNumber-eq20348){
$hostOs="ltsc2022"
}
elseif($os.BuildNumber-eq19045){
$hostOs="22H2"
}
elseif($os.BuildNumber-eq19044){
$hostOs="21H2"
}
elseif($os.BuildNumber-eq19043){
$hostOs="21H1"
}
elseif($os.BuildNumber-eq19042){
$hostOs="20H2"
}
elseif($os.BuildNumber-eq19041){
$hostOs="2004"
}
elseif($os.BuildNumber-eq18363){
$hostOs="1909"
}
elseif($os.BuildNumber-eq18362){
$hostOs="1903"
}
elseif($os.BuildNumber-eq17763){
$hostOs="ltsc2019"
}
elseif($os.BuildNumber-eq17134){
$hostOs="1803"
}
elseif($os.BuildNumber-eq16299){
$hostOs="1709"
}
elseif($os.BuildNumber-eq15063){
$hostOs="1703"
}
elseif($os.BuildNumber-eq14393){
$hostOs="ltsc2016"
}

$artifactPaths=Download-Artifacts-artifactUrl$artifactUrl-includePlatform
$appArtifactPath=$artifactPaths[0]
$platformArtifactPath=$artifactPaths[1]

$appManifestPath=Join-Path$appArtifactPath"manifest.json"
$appManifest=Get-Content$appManifestPath|ConvertFrom-Json
if(!$runSandboxAsOnPrem-and$appManifest.PSObject.Properties.name-eq"isBcSandbox"){
if($appManifest.isBcSandbox){
if(!($PSBoundParameters.ContainsKey('multitenant'))-and!$skipDatabase){
$multitenant=$bcContainerHelperConfig.sandboxContainersAreMultitenantByDefault
}
}
}

if($appManifest.version-like"21.0.*"-and$licenseFile-eq""){
Write-Host"The CRONUS Demo License shipped in Version 21.0 artifacts doesn't contain sufficient rights to all Test Libraries objects. Patching the license file."
$country=$appManifest.Country.ToLowerInvariant()
if(@('at','au','be','ca','ch','cz','de','dk','es','fi','fr','gb','in','is','it','mx','nl','no','nz','ru','se','us')-contains$country){
$licenseFile="https://bcartifacts-exdbf9fwegejdqak.b02.azurefd.net/prerequisites/21demolicense/$country/3048953.bclicense"
}
else{
$licenseFile="https://bcartifacts-exdbf9fwegejdqak.b02.azurefd.net/prerequisites/21demolicense/w1/3048953.bclicense"
}
}

$dbstr=""
$mtstr=""
if(!$imageName.Contains(':')){
$appUri=[Uri]::new($artifactUrl)
$imageName+=":$($appUri.AbsolutePath.ToLowerInvariant().Replace('/','-').TrimStart('-'))"
if($filesOnly){
$imageName+="-filesonly"
$dbstr=" with files only"
}
else{
if($skipDatabase){
$imageName+="-nodb"
$dbstr=" without database"

}
if($multitenant){
$imageName+="-mt"
$mtstr=" multitenant"
}
}
}

$imageName

if($populateBuildFolder-eq""){
$buildMutexName="img-$imageName"
$buildMutex=New-ObjectSystem.Threading.Mutex($false,$buildMutexName)
}
try{
try{
if($populateBuildFolder-eq""){
if(!$buildMutex.WaitOne(1000)){
Write-Host"Waiting for other process building image $imageName"
$buildMutex.WaitOne()|Out-Null
Write-Host"Other process completed building"
$allImages=@()
}
}
}
catch[System.Threading.AbandonedMutexException]{
Write-Host"Other process terminated abnormally"
}

$forceRebuild=$true
if($skipIfImageAlreadyExists){

if(-not($allImages)){
Write-Host"Fetching all docker images"
$allImages=@(dockerimages--format"{{.Repository}}:{{.Tag}}")
}

if($allImages|Where-Object{$_-eq$imageName}){

$forceRebuild=$false

try{
Write-Host"Image $imageName already exists"
$inspect=dockerinspect$imageName|ConvertFrom-Json
$labels=Get-BcContainerImageLabels-imageName$baseImage-registryCredential$registryCredential

$imageArtifactUrl=($inspect.config.env|?{$_-like"artifactUrl=*"}).SubString(12).Split('?')[0]
if((ReplaceCDN-sourceUrl$imageArtifactUrl-useBlobUrl)-ne(ReplaceCDN-sourceUrl$artifactUrl.Split('?')[0]-useBlobUrl)){
Write-Host"Image $imageName was built with artifactUrl $imageArtifactUrl, should be $($artifactUrl.Split('?')[0])"
$forceRebuild=$true
}
if($inspect.Config.Labels.version-ne$appManifest.Version){
Write-Host"Image $imageName was built with version $($inspect.Config.Labels.version), should be $($appManifest.Version)"
$forceRebuild=$true
}
elseif($inspect.Config.Labels.Country-ne$appManifest.Country){
Write-Host"Image $imageName was built with country $($inspect.Config.Labels.country), should be $($appManifest.country)"
$forceRebuild=$true
}
elseif($inspect.Config.Labels.osversion-ne$labels.osversion){
Write-Host"Image $imageName was built for OS Version $($inspect.Config.Labels.osversion), should be $($labels.osversion)"
$forceRebuild=$true
}
elseif($inspect.Config.Labels.tag-ne$labels.tag){
Write-Host"Image $imageName has generic Tag $($inspect.Config.Labels.tag), should be $($labels.tag)"
$forceRebuild=$true
}

if(($inspect.Config.Labels.PSObject.Properties.Name-eq"Multitenant")-and($inspect.Config.Labels.Multitenant-eq"Y")){
if(!$multitenant){
Write-Host"Image $imageName was built multi tenant, should have been single tenant"
$forceRebuild=$true
}
}
else{
if($multitenant){
Write-Host"Image $imageName was built single tenant, should have been multi tenant"
$forceRebuild=$true
}
}

if(($inspect.Config.Labels.PSObject.Properties.Name-eq"SkipDatabase")-and($inspect.Config.Labels.SkipDatabase-eq"Y")){
if(!$skipdatabase){
Write-Host"Image $imageName was built without a database, should have a database"
$forceRebuild=$true
}
}
else{
# Do not rebuild if database is there, just don't use it
}
}
catch{
Write-Host"Exception $($_.ToString())"
$forceRebuild=$true
}
}
}

if($forceRebuild){

Write-Host"Building$mtstr image $imageName based on $baseImage with $($artifactUrl.Split('?')[0])$dbstr"
$startTime=[DateTime]::Now

if($populateBuildFolder){
$genericTag=[Version]"1.0.2.15"
}
else{
if($baseImage-like'mcr.microsoft.com/businesscentral:*'){
Write-Host"Pulling latest image $baseImage"
DockerDo-commandpull-imageName$baseImage|Out-Null
}
else{
$baseImageExists=dockerimages--format"{{.Repository}}:{{.Tag}}"|Where-Object{$_-eq"$baseImage"}
if(!($baseImageExists)){
Write-Host"Pulling non-existing base image $baseImage"
DockerDo-commandpull-imageName$baseImage|Out-Null
}
}

$genericTag=[Version](Get-BcContainerGenericTag-containerOrImageName$baseImage)
Write-Host"Generic Tag: $genericTag"
if($genericTag-lt[Version]"0.1.0.16"){
throw"Generic tag must be at least 0.1.0.16. Cannot build image based on $genericTag"
}

$containerOsVersion=[Version](Get-BcContainerOsVersion-containerOrImageName$baseImage)
if("$containerOsVersion".StartsWith('10.0.14393.')){
$containerOs="ltsc2016"
}
elseif("$containerOsVersion".StartsWith('10.0.15063.')){
$containerOs="1703"
}
elseif("$containerOsVersion".StartsWith('10.0.16299.')){
$containerOs="1709"
}
elseif("$containerOsVersion".StartsWith('10.0.17134.')){
$containerOs="1803"
}
elseif("$containerOsVersion".StartsWith('10.0.17763.')){
$containerOs="ltsc2019"
}
elseif("$containerOsVersion".StartsWith('10.0.18362.')){
$containerOs="1903"
}
elseif("$containerOsVersion".StartsWith('10.0.18363.')){
$containerOs="1909"
}
elseif("$containerOsVersion".StartsWith('10.0.19041.')){
$containerOs="2004"
}
elseif("$containerOsVersion".StartsWith('10.0.19042.')){
$containerOs="20H2"
}
elseif("$containerOsVersion".StartsWith('10.0.19043.')){
$containerOs="21H1"
}
elseif("$containerOsVersion".StartsWith('10.0.19044.')){
$containerOs="21H2"
}
elseif("$containerOsVersion".StartsWith('10.0.19045.')){
$containerOs="22H2"
}
elseif("$containerOsVersion".StartsWith('10.0.20348.')){
$containerOs="ltsc2022"
}
else{
$containerOs="unknown"
}
Write-Host"Container OS Version: $containerOsVersion ($containerOs)"
Write-Host"Host OS Version: $hostOsVersion ($hostOs)"

if(($hostOsVersion.Major-lt$containerOsversion.Major)-or
($hostOsVersion.Major-eq$containerOsversion.Major-and$hostOsVersion.Minor-lt$containerOsversion.Minor)-or
($hostOsVersion.Major-eq$containerOsversion.Major-and$hostOsVersion.Minor-eq$containerOsversion.Minor-and$hostOsVersion.Build-lt$containerOsversion.Build)){

throw"The container operating system is newer than the host operating system, cannot use image"
}

if($hostOsVersion-eq$containerOsVersion){
if($isolation-eq""){
$isolation="process"
}
}
elseif($hostOsVersion.Build-ge20348-and$containerOsVersion.Build-ge20348){
if($isolation-eq""){
Write-Host-ForegroundColorYellow"WARNING: Container and host OS build is 20348 or above, defaulting to process isolation. If you encounter issues, you could try to install HyperV."
$isolation="process"
}
}
elseif(("$hostOsVersion".StartsWith('10.0.19043.')-or"$hostOsVersion".StartsWith('10.0.19044.')-or"$hostOsVersion".StartsWith('10.0.19045.'))-and"$containerOsVersion".StartsWith("10.0.19041.")){
if($isolation-eq""){
Write-Host-ForegroundColorYellow"WARNING: Host OS is Windows 10 21H1 or newer and Container OS is 2004, defaulting to process isolation. If you experience problems, add -isolation hyperv."
$isolation="process"
}
}
else{
if($isolation-eq""){
if($isAdministrator){
if(Get-HypervState-ne"Disabled"){
$isolation="hyperv"
}
else{
$isolation="process"
Write-Host"WARNING: Host OS and Base Image Container OS doesn't match and Hyper-V is not installed. If you encounter issues, you could try to install Hyper-V."
}
}
else{
$isolation="hyperv"
Write-Host"WARNING: Host OS and Base Image Container OS doesn't match, defaulting to hyperv. If you do not have Hyper-V installed or you encounter issues, you could try to specify -isolation process"
}

}
elseif($isolation-eq"process"){
Write-Host"WARNING: Host OS and Base Image Container OS doesn't match and process isolation is specified. If you encounter issues, you could try to specify -isolation hyperv"
}
}
Write-Host"Using $isolation isolation"
}

$downloadsPath=$bcContainerHelperConfig.bcartifactsCacheFolder
if(!(Test-Path$downloadsPath)){
New-Item$downloadsPath-ItemTypeDirectory|Out-Null
}

if($populateBuildFolder){
$buildFolder=$populateBuildFolder
if(Test-Path$buildFolder){
throw"$populateBuildFolder already exists"
}
New-Item$buildFolder-ItemTypeDirectory|Out-Null
}
else{
do{
$buildFolder=Join-Path$bcContainerHelperConfig.bcartifactsCacheFolder([System.IO.Path]::GetRandomFileName())
}
until(New-Item$buildFolder-ItemTypeDirectory-ErrorActionSilentlyContinue)
}

try{

$myFolder=Join-Path$buildFolder"my"
new-Item-Path$myFolder-ItemTypeDirectory|Out-Null

$InstallDotNet=""
if($genericTag-le[Version]"1.0.2.13"-and[Version]$appManifest.Version-ge[Version]"22.0.0.0"){
Write-Host"Patching SetupConfiguration.ps1 due to issue #2874"
$myscripts+=@("https://raw.githubusercontent.com/microsoft/nav-docker/master/generic/Run/210-new/SetupConfiguration.ps1")
Write-Host"Patching prompt.ps1 due to issue #2891"
$myScripts+=@("https://raw.githubusercontent.com/microsoft/nav-docker/master/generic/Run/Prompt.ps1")
$myScripts+=@("https://download.visualstudio.microsoft.com/download/pr/04389c24-12a9-4e0e-8498-31989f30bb22/141aef28265938153eefad0f2398a73b/dotnet-hosting-6.0.27-win.exe")
Write-Host"Base image is generic image 1.0.2.13 or below, installing dotnet 6.0.27"
$InstallDotNet='RUN start-process -Wait -FilePath "c:\run\dotnet-hosting-6.0.27-win.exe" -ArgumentList /quiet'
}

if($genericTag-le[Version]"1.0.2.14"-and[Version]$appManifest.Version-ge[Version]"24.0.0.0"){
$myScripts+=@("https://download.visualstudio.microsoft.com/download/pr/98ff0a08-a283-428f-8e54-19841d97154c/8c7d5f9600eadf264f04c82c813b7aab/dotnet-hosting-8.0.2-win.exe")
$myScripts+=@("https://github.com/PowerShell/PowerShell/releases/download/v7.4.1/PowerShell-7.4.1-win-x64.msi")
Write-Host"Base image is generic image 1.0.2.14 or below, installing dotnet 8.0.2"
$InstallDotNet='RUN start-process -Wait -FilePath "c:\run\dotnet-hosting-8.0.2-win.exe" -ArgumentList /quiet ; start-process -Wait -FilePath c:\run\powershell-7.4.1-win-x64.msi -ArgumentList /quiet'
}

if($genericTag-ge[Version]"1.0.2.15"-and[Version]$appManifest.Version-ge[Version]"15.0.0.0"-and[Version]$appManifest.Version-lt[Version]"19.0.0.0"){
$myScripts+=@("https://download.microsoft.com/download/6/F/B/6FB4F9D2-699B-4A40-A674-B7FF41E0E4D2/DotNetCore.1.0.7_1.1.4-WindowsHosting.exe")
Write-Host"Base image is generic image 1.0.2.15 or higher, installing ASP.NET Core 1.1"
$InstallDotNet='RUN start-process -Wait -FilePath "c:\run\DotNetCore.1.0.7_1.1.4-WindowsHosting.exe" -ArgumentList /quiet'
}

if($genericTag-eq[Version]"1.0.2.15"-and[Version]$appManifest.Version-ge[Version]"24.0.0.0"){
$myScripts+=@('https://raw.githubusercontent.com/microsoft/nav-docker/4b8870e6c023c399d309e389bf32fde44fcb1871/generic/Run/240/navinstall.ps1')
Write-Host"Patching installer from generic image 1.0.2.15"
}

$myScripts|ForEach-Object{
if($_-is[string]){
if($_.StartsWith("https://","OrdinalIgnoreCase")-or$_.StartsWith("http://","OrdinalIgnoreCase")){
$uri=[System.Uri]::new($_)
$filename=[System.Uri]::UnescapeDataString($uri.Segments[$uri.Segments.Count-1])
$destinationFile=Join-Path$myFolder$filename
Download-File-sourceUrl$_-destinationFile$destinationFile
if($destinationFile.EndsWith(".zip","OrdinalIgnoreCase")){
Write-Host"Extracting .zip file "-NoNewline
Expand-7zipArchive-Path$destinationFile-DestinationPath$myFolder
Remove-Item-Path$destinationFile-Force
}
}elseif(Test-Path$_-PathTypeContainer){
Copy-Item-Path"$_\*"-Destination$myFolder-Recurse-Force
}else{
if($_.EndsWith(".zip","OrdinalIgnoreCase")){
Write-Host"Extracting .zip file "-NoNewline
Expand-7zipArchive-Path$_-DestinationPath$myFolder
}else{
Copy-Item-Path$_-Destination$myFolder-Force
}
}
}else{
$hashtable=$_
$hashtable.Keys|ForEach-Object{
Set-Content-Path(Join-Path$myFolder$_)-Value$hashtable[$_]
}
}
}

$licenseFilePath=""
if($licenseFile){
if($licensefile.StartsWith("https://","OrdinalIgnoreCase")-or$licensefile.StartsWith("http://","OrdinalIgnoreCase")){
Write-Host"Using license file $($licenseFile.Split('?')[0])"
$ext=[System.IO.Path]::GetExtension($licenseFile.Split('?')[0])
$licenseFilePath=Join-Path$myFolder"license$ext"
Download-File-sourceUrl$licenseFile-destinationFile$licenseFilePath
if((Get-Content$licenseFilePath-First1)-ne"Microsoft Software License Information"){
Remove-Item-Path$licenseFilePath-Force
throw"Specified license file Uri isn't a direct download Uri"
}
}
else{
Write-Host"Using license file $licenseFile"
$licenseFilePath=$licenseFile
}
}

Write-Host"Files in $($myfolder):"
get-childitem-Path$myfolder|ForEach-Object{Write-Host"- $($_.Name)"}

$isBcSandbox="N"
if(!$runSandboxAsOnPrem-and$appManifest.PSObject.Properties.name-eq"isBcSandbox"){
if($appManifest.isBcSandbox){
$IsBcSandbox="Y"
}
}

if(!$skipDatabase){
$database=$appManifest.database
$databasePath=Join-Path$appArtifactPath$database
if($licenseFile-eq""){
if($appManifest.PSObject.Properties.name-eq"licenseFile"){
$licenseFilePath=$appManifest.licenseFile
if($licenseFilePath){
$licenseFilePath=Join-Path$appArtifactPath$licenseFilePath
}
}
}
}

$nav=""
if($appManifest.PSObject.Properties.name-eq"Nav"){
$nav=$appManifest.Nav
}
$cu=""
if($appManifest.PSObject.Properties.name-eq"Cu"){
$cu=$appManifest.Cu
}

$navDvdPath=Join-Path$buildFolder"NAVDVD"
New-Item$navDvdPath-ItemTypeDirectory|Out-Null

Write-Host"Copying Platform Artifacts"
RobocopyFiles-source"$platformArtifactPath"-destination"$navDvdPath"-e

if(!$skipDatabase){
$dbPath=Join-Path$navDvdPath"SQLDemoDatabase\CommonAppData\Microsoft\Microsoft Dynamics NAV\ver\Database"
New-Item$dbPath-ItemTypeDirectory|Out-Null
if(($databaseBackupPath)-and(Test-Path$databaseBackupPath-PathTypeLeaf))
{
Write-Host"Using database backup from $databaseBackupPath"
$databasePath=$databaseBackupPath
}
Write-Host"Copying Database"
Copy-Item-path$databasePath-Destination$dbPath-Force
if($licenseFilePath){
Write-Host"Copying Licensefile"
Copy-Item-path$licenseFilePath-Destination"$dbPath\CRONUS.flf"-Force
}
}

"Installers","ConfigurationPackages","TestToolKit","UpgradeToolKit","Extensions","Applications","Applications.*"|ForEach-Object{
$appSubFolder=Join-Path$appArtifactPath$_
if(Test-Path$appSubFolder-PathTypeContainer){
$appSubFolder=(Get-Item$appSubFolder).FullName
$name=[System.IO.Path]::GetFileName($appSubFolder)
$destFolder=Join-Path$navDvdPath$name
if(Test-Path$destFolder){
Remove-Item-path$destFolder-Recurse-Force
}
Write-Host"Copying $name"
RoboCopyFiles-Source"$appSubFolder"-Destination"$destFolder"-e
}
}

if($populateBuildFolder-eq""){
dockerimages--format"{{.Repository}}:{{.Tag}}"|ForEach-Object{
if($_-eq$imageName)
{
dockerrmi--no-prune$imageName-f|Out-Host
}
}
}

Write-Host$buildFolder

$skipDatabaseLabel=""
if($skipDatabase){
$skipDatabaseLabel="skipdatabase=""Y"" \`n "
}

$multitenantLabel=""
$multitenantParameter=""
if($multitenant){
$multitenantLabel="multitenant=""Y"" \`n "
$multitenantParameter=" -multitenant"
}

$dockerFileAddFonts=""
if($addFontsFromPath){
$found=$false
$fontsFolder=Join-Path$buildFolder"Fonts"
New-Item$fontsFolder-ItemTypeDirectory|Out-Null
$extensions=@(".fon",".fnt",".ttf",".ttc",".otf")
Get-ChildItem$addFontsFromPath-ErrorActionIgnore|ForEach-Object{
if($extensions.Contains($_.Extension.ToLowerInvariant())){
Copy-Item-Path$_.FullName-Destination$fontsFolder
$found=$true
}
}
if($found){
Write-Host"Adding fonts"
Copy-Item-Path(Join-Path$PSScriptRoot"..\AddFonts.ps1")-Destination$fontsFolder
$dockerFileAddFonts="COPY Fonts /Fonts/`nRUN . C:\Fonts\AddFonts.ps1`n"
}
}

$TestToolkitParameter=""
if($genericTag-ge[Version]"0.1.0.18"){
if($includeTestToolkit){
if(!($licenseFile)-and($appManifest.version-lt[Version]"22.0.0.0")){
Write-Host"Cannot include TestToolkit without a licensefile, please specify licensefile"
}
$TestToolkitParameter=" -includeTestToolkit"
if($includeTestLibrariesOnly){
$TestToolkitParameter+=" -includeTestLibrariesOnly"
}
elseif($includeTestFrameworkOnly){
$TestToolkitParameter+=" -includeTestFrameworkOnly"
}
}
}
if($genericTag-ge[Version]"0.1.0.21"){
if($includeTestToolkit){
if($includePerformanceToolkit){
$TestToolkitParameter+=" -includePerformanceToolkit"
}
}
}

$additionalLabelsStr=""
$additionalLabels|ForEach-Object{
$additionalLabelsStr+="$_ \`n "
}
@"
FROM $baseimage

ENV DatabaseServer=localhost DatabaseInstance=SQLEXPRESS DatabaseName=CRONUS IsBcSandbox=$isBcSandbox artifactUrl=$artifactUrl filesOnly=$filesOnly

COPY my /run/
COPY NAVDVD /NAVDVD/
$DockerFileAddFonts
$InstallDotNet

RUN \Run\start.ps1 -installOnly$multitenantParameter$TestToolkitParameter

LABEL legal="http://go.microsoft.com/fwlink/?LinkId=837447" \
created="$([DateTime]::Now.ToUniversalTime().ToString("yyyyMMddHHmm"))" \
nav="$nav" \
cu="$cu" \
$($skipDatabaseLabel)$($multitenantLabel)$($additionalLabelsStr)country="$($appManifest.Country)" \
version="$($appmanifest.Version)" \
platform="$($appManifest.Platform)"
"@
|Set-Content(Join-Path$buildFolder"DOCKERFILE")

if($populateBuildFolder){
Write-Host"$populateBuildFolder populated, skipping build of image"
}
else{
if(!(DockerDo-commandbuild-parameters@("--isolation=$isolation","--memory $memory","--no-cache","--tag $imageName")-imageName$buildFolder)){
throw"Docker Build didn't indicate success"
}

$timespend=[Math]::Round([DateTime]::Now.Subtract($startTime).Totalseconds)
Write-Host"Building image took $timespend seconds"
}
}
finally{
if($populateBuildFolder-eq""){
Remove-Item$buildFolder-Recurse-Force-ErrorActionSilentlyContinue
}
}
}
}
finally{
if($populateBuildFolder-eq""){
$buildMutex.ReleaseMutex()
}
}
}
catch{
TrackException-telemetryScope$telemetryScope-errorRecord$_
throw
}
finally{
TrackTrace-telemetryScope$telemetryScope
}
}
Set-Alias-NameNew-NavImage-ValueNew-BcImage
Export-ModuleMember-FunctionNew-BcImage-AliasNew-NavImage

# SIG # Begin signature block
# MIImbAYJKoZIhvcNAQcCoIImXTCCJlkCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBexIvPztABNCTi
# IKl80HHSUD45ZkkYkTrWZvirTtWE5KCCH4QwggWNMIIEdaADAgECAhAOmxiO+dAt
# 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV
# BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa
# Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy
# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD
# ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E
# MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy
# unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF
# xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1
# 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB
# MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR
# WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6
# nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB
# YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S
# UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x
# q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB
# NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP
# TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC
# AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
# Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv
# bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0
# aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB
# LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc
# Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov
# Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy
# oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW
# juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF
# mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z
# twGpn1eqXijiuZQwggYaMIIEAqADAgECAhBiHW0MUgGeO5B5FSCJIRwKMA0GCSqG
# SIb3DQEBDAUAMFYxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0
# ZWQxLTArBgNVBAMTJFNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBSb290IFI0
# NjAeFw0yMTAzMjIwMDAwMDBaFw0zNjAzMjEyMzU5NTlaMFQxCzAJBgNVBAYTAkdC
# MRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxKzApBgNVBAMTIlNlY3RpZ28gUHVi
# bGljIENvZGUgU2lnbmluZyBDQSBSMzYwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAw
# ggGKAoIBgQCbK51T+jU/jmAGQ2rAz/V/9shTUxji*ztNsfvxYB5UXeWUzCxEeAEZG
# bEN4QMgCsJLZUKhWThj/yPqy0iSZhXkZ6Pg2A2NVDgFigOMYzB2OKhdqfWGVoYW3
# haT29PSTahYkwmMv0b/83nbeECbiMXhSOtbam+/36F09fy1tsB8je/RV0mIk8XL/
# tfCK6cPuYHE215wzrK0h1SWHTxPbPuYkRdkP05ZwmRmTnAO5/arnY83jeNzhP06S
# hdnRqtZlV59+8yv+KIhE5ILMqgOZYAENHNX9SJDm+qxp4VqpB3MV/h53yl41aHU5
# pledi9lCBbH9JeIkNFICiVHNkRmq4TpxtwfvjsUedyz8rNyfQJy/aOs5b4s+ac7I
# H60B+Ja7TVM+EKv1WuTGwcLmoU3FpOFMbmPj8pz44MPZ1f9+YEQIQty/NQd/2yGg
# W+ufflcZ/ZE9o1M7a5Jnqf2i2/uMSWymR8r2oQBMdlyh2n5HirY4jKnFH/9gRvd+
# QOfdRrJZb1sCAwEAAaOCAWQwggFgMB8GA1UdIwQYMBaAFDLrkpr/NZZILyhAQnAg
# NpFcF4XmMB0GA1UdDgQWBBQPKssghyi47G9IritUpimqF6TNDDAOBgNVHQ8BAf8E
# BAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADATBgNVHSUEDDAKBggrBgEFBQcDAzAb
# BgNVHSAEFDASMAYGBFUdIAAwCAYGZ4EMAQQBMEsGA1UdHwREMEIwQKA+oDyGOmh0
# dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nUm9v
# dFI0Ni5jcmwwewYIKwYBBQUHAQEEbzBtMEYGCCsGAQUFBzAChjpodHRwOi8vY3J0
# LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ1Jvb3RSNDYucDdj
# MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTANBgkqhkiG9w0B
# AQwFAAOCAgEABv+C4XdjNm57oRUgmxP/BP6YdURhw1aVcdGRP4Wh60BAscjW4HL9
# hcpkOTz5jUug2oeunbYAowbFC2AKK+cMcXIBD0ZdOaWTsyNyBBsMLHqafvIhrCym
# laS98+QpoBCyKppP0OcxYEdU0hpsaqBBIZOtBajjcw5+w/KeFvPYfLF/ldYpmlG+
# vd0xqlqd099iChnyIMvY5HexjO2AmtsbpVn0OhNcWbWDRF/3sBp6fWXhz7DcML4i
# TAWS+MVXeNLj1lJziVKEoroGs9Mlizg0bUMbOalOhOfCipnx8CaLZeVme5yELg09
# Jlo8BMe80jO37PU8ejfkP9/uPak7VLwELKxAMcJszkyeiaerlphwoKx1uHRzNyE6
# bxuSKcutisqmKL5OTunAvtONEoteSiabkPVSZ2z76mKnzAfZxCl/3dq3dUNw4rg3
# sTCggkHSRqTqlLMS7gjrhTqBmzu1L90Y1KWN/Y5JKdGvspbOrTfOXyXvmPL6E52z
# 1NZJ6ctuMFBQZH3pwWvqURR8AgQdULUvrxjUYbHHj95Ejza63zdrEcxWLDX6xWls
# /GDnVNueKjWUH3fTv1Y8Wdho698YADR7TNx8X8z2Bev6SivBBOHY+uqiirZtg0y9
# ShQoPzmCcn63Syatatvx157YK9hlcPmVoa1oDE5/L9Uo2bC5a4CH2RwwggZZMIIE
# waADAgECAhANIM3qwHRbWKHw+Zq6JhzlMA0GCSqGSIb3DQEBDAUAMFQxCzAJBgNV
# BAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxKzApBgNVBAMTIlNlY3Rp
# Z28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYwHhcNMjExMDIyMDAwMDAwWhcN
# MjQxMDIxMjM1OTU5WjBdMQswCQYDVQQGEwJESzEUMBIGA1UECAwLSG92ZWRzdGFk
# ZW4xGzAZBgNVBAoMEkZyZWRkeSBLcmlzdGlhbnNlbjEbMBkGA1UEAwwSRnJlZGR5
# IEtyaXN0aWFuc2VuMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAgYC5
# tlg+VRktRRkahxxaV8+DAd6vHoDpcO6w7yT24lnSoMuA6nR7kgy90Y/sHIwKE9Ww
# t/px/GAY8eBePWjJrFpG8fBtJbXadRTVd/470Hs/q9t+kh6A/0ELj7wYsKSNOyuF
# Poy4rtClOv9ZmrRpoDVnh8Epwg2DpklX2BNzykzBQxIbkpp+xVo2mhPNWDIesntc
# 4/BnSebLGw1Vkxmu2acKkIjYrne/7lsuyL9ue0vk8TGk9JBPNPbGKJvHu9szP9oG
# oH36fU1sEZ+AacXrp+onsyPf/hkkpAMHAhzQHl+5Ikvcus/cDm06twm7VywmZcas
# 2rFAV5MyE6WMEaYAolwAHiPz9WAs2GDhFtZZg1tzbRjJIIgPpR+doTIcpcDBcHnN
# dSdgWKrTkr2f339oT5bnJfo7oVzc/2HGWvb8Fom6LQAqSC11vWmznHYsCm72g+fo
# TKqW8lLDfLF0+aFvToLosrtW9l6Z+l+RQ8MtJ9EHOm2Ny8cFLzZCDZYw32BydwcL
# V5rKdy4Ica9on5xZvyMOLiFwuL4v2V4pjEgKJaGSS/IVSMEGjrM9DHT6YS4/oq9q
# 20rQUmMZZQmGmEyyKQ8t11si8VHtScN5m0Li8peoWfCU9mRFxSESwTWow8d462+o
# 9/SzmDxCACdFwzvfKx4JqDMm55cL+beunIvc0NsCAwEAAaOCAZwwggGYMB8GA1Ud
# IwQYMBaAFA8qyyCHKLjsb0iuK1SmKaoXpM0MMB0GA1UdDgQWBBTZD6uy9ZWIIqQh
# 3srYu1FlUhdM0TAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADATBgNVHSUE
# DDAKBggrBgEFBQcDAzARBglghkgBhvhCAQEEBAMCBBAwSgYDVR0gBEMwQTA1Bgwr
# BgEEAbIxAQIBAwIwJTAjBggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9D
# UFMwCAYGZ4EMAQQBMEkGA1UdHwRCMEAwPqA8oDqGOGh0dHA6Ly9jcmwuc2VjdGln
# by5jb20vU2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nQ0FSMzYuY3JsMHkGCCsGAQUF
# BwEBBG0wazBEBggrBgEFBQcwAoY4aHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0
# aWdvUHVibGljQ29kZVNpZ25pbmdDQVIzNi5jcnQwIwYIKwYBBQUHMAGGF2h0dHA6
# Ly9vY3NwLnNlY3RpZ28uY29tMA0GCSqGSIb3DQEBDAUAA4IBgQASEbZACurQeQN8
# WDTR+YyNpoQ29YAbbdBRhhzHkT/1ao7LE0QIOgGR4GwKRzufCAwu8pCBiMOUTDHT
# ezkh0rQrG6khxBX2nSTBL5i4LwKMR08HgZBsbECciABy15yexYWoB/D0H8WuGe63
# PhGWueR4IFPbIz+jEVxfW0Nyyr7bXTecpKd1iprm+TOmzc2E6ab95dkcXdJVx6Zy
# s++QrrOfQ+a57qEXkS/wnjjbN9hukL0zg+g8L4DHLKTodzfiQOampvV8QzbnB7Y8
# YjNcxR9s/nptnlQH3jorNFhktiBXvD62jc8pAIg6wyH6NxSMjtTsn7QhkIp2kusw
# IQwD8hN/fZ/m6gkXZhRJWFr2WRZOz+edZ62Jf25C/NYWscwfBwn2hzRZf1HgyxkX
# Al88dvvUA3kw1T6uo8aAB9IcL6Owiy7q4T+RLRF7oqx0vcw0193Yhq/gPOaUFlqz
# ExP6TQ5TR9XWVPQk+a1B1ATKMLi1JShO6KWTmNkFkgkgpkW69BEwggauMIIElqAD
# AgECAhAHNje3JFR82Ees/ShmKl5bMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYT
# AlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2Vy
# dC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMjAz
# MjMwMDAwMDBaFw0zNzAzMjIyMzU5NTlaMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQK
# Ew5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBS
# U0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwggIiMA0GCSqGSIb3DQEBAQUA
# A4ICDwAwggIKAoICAQDGhjUGSbPBPXJJUVXHJQPE8pE3qZdRodbSg9GeTKJtoLDM
# g/la9hGhRBVCX6SI82j6ffOciQt/nR+eDzMfUBMLJnOWbfhXqAJ9/UO0hNoR8XOx
# s+4rgISKIhjf69o9xBd/qxkrPkLcZ47qUT3w1lbU5ygt69OxtXXnHwZljZQp09ns
# ad/ZkIdGAHvbREGJ3HxqV3rwN3mfXazL6IRktFLydkf3YYMZ3V+0VAshaG43IbtA
# rF+y3kp9zvU5EmfvDqVjbOSmxR3NNg1c1eYbqMFkdECnwHLf*ck4fsbVYTXn+149z
# k6wsOeKlSNbwsDETqVcplicu9Yemj052FVUmcJgmf6AaRyBD40NjgHt1biclkJg6
# OBGz9vae5jtb7IHeIhTZgirHkr+g3uM+onP65x9abJTyUpURK1h0QCirc0PO30qh
# HGs4xSnzyqqWc0Jon7ZGs506o9UD4L/wojzKQtwYSH8UNM/STKvvmz3+DrhkKvp1
# KCRB7UK/BZxmSVJQ9FHzNklNiyDSLFc1eSuo80VgvCONWPfcYd6T/jnA+bIwpUzX
# 6ZhKWD7TA4j+s4/TXkt2ElGTyYwMO1uKIqjBJgj5FBASA31fI7tk42PgpuE+9sJ0
# sj8eCXbsq11GdeJgo1gJASgADoRU7s7pXcheMBK9Rp6103a50g5rmQzSM7TNsQID
# AQABo4IBXTCCAVkwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUuhbZbU2F
# L3MpdpovdYxqII+eyG8wHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08w
# DgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEB
# BGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsG
# AQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVz
# dGVkUm9vdEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdp
# Y2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgG
# BmeBDAEEAjALBglghkgBhv1sBwEwDQYJKoZIhvcNAQELBQADggIBAH1ZjsCTtm+Y
# qUQiAX5m1tghQuGwGC4QTRPPMFPOvxj7x1Bd4ksp+3CKDaopafxpwc8dB+k+YMjY
# C+VcW9dth/qEICU0MWfNthKWb8RQTGIdDAiCqBa9qVbPFXONASIlzpVpP0d3+3J0
# FNf/q0+KLHqrhc1DX+1gtqpPkWaeLJ7giqzl/Yy8ZCaHbJK9nXzQcAp876i8dU+6
# WvepELJd6f8oVInw1YpxdmXazPByoyP6wCeCRK6ZJxurJB4mwbfeKuv2nrF5mYGj
# VoarCkXJ38SNoOeY+/umnXKvxMfBwWpx2cYTgAnEtp/Nh4cku0+jSbl3ZpHxcpzp
# SwJSpzd+k1OsOx0ISQ+UzTl63f8lY5knLD0/a6fxZsNBzU+2QJshIUDQtxMkzdwd
# eDrknq3lNHGS1yZr5Dhzq6YBT70/O3itTK37xJV77QpfMzmHQXh6OOmc4d0j/R0o
# 08f56PGYX/sr2H7yRp11LB4nLCbbbxV7HhmLNriT1ObyF5lZynDwN7+YAN8gFk8n
# +2BnFqFmut1VwDophrCYoCvtlUG3OtUVmDG0YgkPCr2B2RP+v6TR81fZvAT6gt4y
# 3wSJ8ADNXcL50CN/AAvkdgIm2fBldkKmKYcJRyvmfxqkhQ/8mJb2VVQrH4D6wPIO
# K+XW+6kvRBVK5xMOHds3OBqhK/bt1nz8MIIGwjCCBKqgAwIBAgIQBUSv85SdCDmm
# v9s/X+VhFjANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMO
# RGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNB
# NDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMB4XDTIzMDcxNDAwMDAwMFoXDTM0
# MTAxMzIzNTk1OVowSDELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ
# bmMuMSAwHgYDVQQDExdEaWdpQ2VydCBUaW1lc3RhbXAgMjAyMzCCAiIwDQYJKoZI
# hvcNAQEBBQADggIPADCCAgoCggIBAKNTRYcdg45brD5UsyPgz5/X5dLnXaEOCdwv
# SKOXejsqnGfcYhVYwamTEafNqrJq3RApih5iY2nTWJw1cb86l+uUUI8cIOrHmjsv
# lmbjaedp/lvD1isgHMGXlLSlUIHyz8sHpjBoyoNC2vx/CSSUpIIa2mq62DvKXd4Z
# GIX7ReoNYWyd/nFexAaaPPDFLnkPG2ZS48jWPl/aQ9OE9dDH9kgtXkV1lnX+3RCh
# G4PBuOZSlbVH13gpOWvgeFmX40QrStWVzu8IF+qCZE3/I+PKhu60pCFkcOvV5aDa
# Y7Mu6QXuqvYk9R28mxyyt1/f8O52fTGZZUdVnUokL6wrl76f5P17cz4y7lI0+9S7
# 69SgLDSb495uZBkHNwGRDxy1Uc2qTGaDiGhiu7xBG3gZbeTZD+BYQfvYsSzhUa+0
# rRUGFOpiCBPTaR58ZE2dD9/O0V6MqqtQFcmzyrzXxDtoRKOlO0L9c33u3Qr/eTQQ
# fqZcClhMAD6FaXXHg2TWdc2PEnZWpST618RrIbroHzSYLzrqawGw9/sqhux7Ujip
# mAmhcbJsca8+uG+W1eEQE/5hRwqM/vC2x9XH3mwk8L9CgsqgcT2ckpMEtGlwJw1P
# t7U20clfCKRwo+wK8REuZODLIivK8SgTIUlRfgZm0zu++uuRONhRB8qUt+JQofM6
# 04qDy0B7AgMBAAGjggGLMIIBhzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIw
# ADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAgBgNVHSAEGTAXMAgGBmeBDAEEAjAL
# BglghkgBhv1sBwEwHwYDVR0jBBgwFoAUuhbZbU2FL3MpdpovdYxqII+eyG8wHQYD
# VR0OBBYEFKW27xPn783QZKHVVqllMaPe1eNJMFoGA1UdHwRTMFEwT6BNoEuGSWh0
# dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZT
# SEEyNTZUaW1lU3RhbXBpbmdDQS5jcmwwgZAGCCsGAQUFBwEBBIGDMIGAMCQGCCsG
# AQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wWAYIKwYBBQUHMAKGTGh0
# dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQw
# OTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5jcnQwDQYJKoZIhvcNAQELBQADggIBAIEa
# 1t6gqbWYF7xwjU+KPGic2CX/yyzkzepdIpLsjCICqbjPgKjZ5+PF7SaCinEvGN1O
# tt5s1+FgnCvt7T1IjrhrunxdvcJhN2hJd6PrkKoS1yeF844ektrCQDifXcigLiV4
# JZ0qBXqEKZi2V3mP2yZWK7Dzp703DNiYdk9WuVLCtp04qYHnbUFcjGnRuSvExnvP
# nPp44pMadqJpddNQ5EQSviANnqlE0PjlSXcIWiHFtM+YlRpUurm8wWkZus8W8oM3
# NG6wQSbd3lqXTzON1I13fXVFoaVYJmoDRd7ZULVQjK9WvUzF4UbFKNOt50MAcN7M
# mJ4ZiQPq1JE3701S88lgIcRWR+3aEUuMMsOI5ljitts++V+wQtaP4xeR0arAVeOG
# v6wnLEHQmjNKqDbUuXKWfpd5OEhfysLcPTLfddY2Z1qJ+Panx+VPNTwAvb6cKmx5
# AdzaROY63jg7B145WPR8czFVoIARyxQMfq68/qTreWWqaNYiyjvrmoI1VygWy2ny
# Mpqy0tg6uLFGhmu6F/3Ed2wVbK6rr3M66ElGt9V/zLY4wNjsHPW2obhDLN9OTH0e
# aHDAdwrUAuBcYLso/zjlUlrWrBciI0707NMX+1Br/wd3H3GXREHJuEbTbDJ8WC9n
# R2XlG3O2mflrLAZG70Ee8PBf4NvZrZCARK+AEEGKMYIGPjCCBjoCAQEwaDBUMQsw
# CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJT
# ZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgQ0EgUjM2AhANIM3qwHRbWKHw+Zq6
# JhzlMA0GCWCGSAFlAwQCAQUAoIGEMBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAw
# GQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisG
# AQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEICbwpdM/Kd0SwgfVWPm/KnTKyIm6FRas
# RIypDThdxhUBMA0GCSqGSIb3DQEBAQUABIICAGn7f3xE5h9RCPSwawK1yJKnogrR
# W1XVViHsC16YSpgEYWlJz0h/1sG6fSpLuq/QtIBUl3eZqCA+ql+nn5YKpnwBbKRe
# 9/aPwLicn1YE/YqXABw83sxWDAlzfawLnCbCrFUvFaekhhOlXD+j/69kSUIANXjV
# RUp3Usu80R/uuBly5HY/NvEk5PTyq0KVvaHr3IotxL7VlFSXvMEyG0FpOnD/ZnnN
# IYwlVyPGzGZiI8TNV+3rFdOg/21EsGTFK7B1Awl+/KuT7DalmGoykh69oLxslcOl
# HgDk0zQN+nQaMfLhjzRicM60DILzUM2x4gLoL1vtGHeaO/VoskM361yAlS3HX5+Z
# EY+L88t8LWhGaPs7eJPBxS5BhonAqqKeiilEcs+ilCznjvjKG+X+4cdmt4I7LR74
# ebb5NvaB7PLdmEI3d5svkkuMaSea6aQc/96H2OWp2xzFZOUrzB4SmzGNvr5Hmy6w
# AHy56L1Jp4jMfl7MwhjMEjTIV5MWviI0NN+uxQgludr1SLw125NU4SX7PiJ6CsDy
# pqdkhROQrfSxRIQCxVWYnPUwYcz/jpd4v4hbT50qQBRBTWfolEeAlzeWnYG2HCT9
# hxF3u676ChjbaHfs1ZLS+MpOW3WfySFqWJrG/adLH52308hABbi74+re7fDp/idg
# k62IhYnhM4kVle6GoYIDIDCCAxwGCSqGSIb3DQEJBjGCAw0wggMJAgEBMHcwYzEL
# MAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJE
# aWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBD
# QQIQBUSv85SdCDmmv9s/X+VhFjANBglghkgBZQMEAgEFAKBpMBgGCSqGSIb3DQEJ
# AzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTI0MDYyNDE2NTI1NVowLwYJ
# KoZIhvcNAQkEMSIEINrPMiOMxb+neGk/JJtYAqlX1JV+O8dnc4NfYsc39gmeMA0G
# CSqGSIb3DQEBAQUABIICAGkEi7fbJwN05UH2GihxLmo7gWL5Fs0LbFJPx6ZyFl85
# 1PcpOhDEncJQ4NzcGe3v3G4cGwhW7FU0vsEuEiIa8sdSVqkBKtTbEQcesvfAAymk
# RIm2/S4s8mjvHvdc02KxpB9xJQFLCvDAJEYkHqOjN8EyjOw1f2h3VfE7kHd8yJ5i
# hB4p6at44VqD0/x0nkMfW2XDqiKwHLFfwzo3tq0BzdQFSml+Ks1uTqEksF0l+r/h
# rxkN6/qe+VZK2oBLwSitcmr0ptERC8cpOYAZGEXdNU7BgHOG7IF5YmkcFK38EI+K
# 4VyOGBI9d0o8fVDmleIa6ihQE/wfaaW2SVJfWvXx4UH7rGFtRg9a+3AYbpFfFdXo
# Ra/JHXw9SLnOuDdPGqJqUqiahiVY/VnBLTqCL48nGPhDiptt+1K3fvIV1lndL2ia
# E0yNUcqAxfcwBtteEYmrav7yKUzEyZ1MQaL1JywUyTCqjkIRnTfFumt4tMDgqfF1
# sOODZ5PYWIe/5JWStSEmKypw2PhwffPJ7nyqbi8lBTGnEzlt4avhDph1lM4d4C4n
# 6UQ5kW3zZQOuW4kt0VQ9x86VqAuxAnWw1LmAdM92hhu9ICN5bx76TUuJR+Kc7uRL
# B2zIEB7LB9r4ClaXRuc4evPjUkIKMvSWajGNAd2+CwA6EA1JVWJn2pM8QDQ+sm+r
# SIG # End signature block

PowerShell Gallery
        | ContainerHandling/New-NavImage.ps1 6.0.19 (2024)
Top Articles
Latest Posts
Article information

Author: Rev. Porsche Oberbrunner

Last Updated:

Views: 5996

Rating: 4.2 / 5 (73 voted)

Reviews: 88% of readers found this page helpful

Author information

Name: Rev. Porsche Oberbrunner

Birthday: 1994-06-25

Address: Suite 153 582 Lubowitz Walks, Port Alfredoborough, IN 72879-2838

Phone: +128413562823324

Job: IT Strategist

Hobby: Video gaming, Basketball, Web surfing, Book restoration, Jogging, Shooting, Fishing

Introduction: My name is Rev. Porsche Oberbrunner, I am a zany, graceful, talented, witty, determined, shiny, enchanting person who loves writing and wants to share my knowledge and understanding with you.