diff options
Diffstat (limited to 'Tools/dotnetcli/sdk/NuGetFallbackFolder/microsoft.entityframeworkcore.tools/2.0.1/tools/EntityFrameworkCore.psm1')
-rw-r--r-- | Tools/dotnetcli/sdk/NuGetFallbackFolder/microsoft.entityframeworkcore.tools/2.0.1/tools/EntityFrameworkCore.psm1 | 1307 |
1 files changed, 1307 insertions, 0 deletions
diff --git a/Tools/dotnetcli/sdk/NuGetFallbackFolder/microsoft.entityframeworkcore.tools/2.0.1/tools/EntityFrameworkCore.psm1 b/Tools/dotnetcli/sdk/NuGetFallbackFolder/microsoft.entityframeworkcore.tools/2.0.1/tools/EntityFrameworkCore.psm1 new file mode 100644 index 0000000000..32164c7eb7 --- /dev/null +++ b/Tools/dotnetcli/sdk/NuGetFallbackFolder/microsoft.entityframeworkcore.tools/2.0.1/tools/EntityFrameworkCore.psm1 @@ -0,0 +1,1307 @@ +$ErrorActionPreference = 'Stop' + +# +# Add-Migration +# + +Register-TabExpansion Add-Migration @{ + OutputDir = { <# Disabled. Otherwise, paths would be relative to the solution directory. #> } + Context = { param($x) GetContextTypes $x.Project $x.StartupProject } + Project = { GetProjects } + StartupProject = { GetProjects } +} + +<# +.SYNOPSIS + Adds a new migration. + +.DESCRIPTION + Adds a new migration. + +.PARAMETER Name + The name of the migration. + +.PARAMETER OutputDir + The directory (and sub-namespace) to use. Paths are relative to the project directory. Defaults to "Migrations". + +.PARAMETER Context + The DbContext type to use. + +.PARAMETER Project + The project to use. + +.PARAMETER StartupProject + The startup project to use. Defaults to the solution's startup project. + +.LINK + Remove-Migration + Update-Database + about_EntityFrameworkCore +#> +function Add-Migration +{ + [CmdletBinding(PositionalBinding = $false)] + param( + [Parameter(Position = 0, Mandatory = $true)] + [string] $Name, + [string] $OutputDir, + [string] $Context, + [string] $Project, + [string] $StartupProject) + + WarnIfEF6 'Add-Migration' + + $dteProject = GetProject $Project + $dteStartupProject = GetStartupProject $StartupProject $dteProject + + $params = 'migrations', 'add', $Name, '--json' + + if ($OutputDir) + { + $params += '--output-dir', $OutputDir + } + + $params += GetParams $Context + + # NB: -join is here to support ConvertFrom-Json on PowerShell 3.0 + $result = (EF $dteProject $dteStartupProject $params) -join "`n" | ConvertFrom-Json + Write-Output 'To undo this action, use Remove-Migration.' + + $dteProject.ProjectItems.AddFromFile($result.migrationFile) | Out-Null + $DTE.ItemOperations.OpenFile($result.migrationFile) | Out-Null + ShowConsole + + $dteProject.ProjectItems.AddFromFile($result.metadataFile) | Out-Null + + $dteProject.ProjectItems.AddFromFile($result.snapshotFile) | Out-Null +} + +# +# Drop-Database +# + +Register-TabExpansion Drop-Database @{ + Context = { param($x) GetContextTypes $x.Project $x.StartupProject } + Project = { GetProjects } + StartupProject = { GetProjects } +} + +<# +.SYNOPSIS + Drops the database. + +.DESCRIPTION + Drops the database. + +.PARAMETER Context + The DbContext to use. + +.PARAMETER Project + The project to use. + +.PARAMETER StartupProject + The startup project to use. Defaults to the solution's startup project. + +.LINK + Update-Database + about_EntityFrameworkCore +#> +function Drop-Database +{ + [CmdletBinding(PositionalBinding = $false, SupportsShouldProcess = $true, ConfirmImpact = 'High')] + param([string] $Context, [string] $Project, [string] $StartupProject) + + $dteProject = GetProject $Project + $dteStartupProject = GetStartupProject $StartupProject $dteProject + + $params = 'dbcontext', 'info', '--json' + $params += GetParams $Context + + # NB: -join is here to support ConvertFrom-Json on PowerShell 3.0 + $info = (EF $dteProject $dteStartupProject $params) -join "`n" | ConvertFrom-Json + + if ($PSCmdlet.ShouldProcess("database '$($info.databaseName)' on server '$($info.dataSource)'")) + { + $params = 'database', 'drop', '--force' + $params += GetParams $Context + + EF $dteProject $dteStartupProject $params -skipBuild + } +} + +# +# Enable-Migrations (Obsolete) +# + +function Enable-Migrations +{ + WarnIfEF6 'Update-Database' + Write-Warning 'Enable-Migrations is obsolete. Use Add-Migration to start using Migrations.' +} + +# +# Get-DbContext +# + +Register-TabExpansion Get-DbContext @{ + Context = { param($x) GetContextTypes $x.Project $x.StartupProject } + Project = { GetProjects } + StartupProject = { GetProjects } +} + +<# +.SYNOPSIS + Gets information about a DbContext type. + +.DESCRIPTION + Gets information about a DbContext type. + +.PARAMETER Context + The DbContext to use. + +.PARAMETER Project + The project to use. + +.PARAMETER StartupProject + The startup project to use. Defaults to the solution's startup project. + +.LINK + about_EntityFrameworkCore +#> +function Get-DbContext +{ + [CmdletBinding(PositionalBinding = $false)] + param([string] $Context, [string] $Project, [string] $StartupProject) + + $dteProject = GetProject $Project + $dteStartupProject = GetStartupProject $StartupProject $dteProject + + $params = 'dbcontext', 'info', '--json' + $params += GetParams $Context + + # NB: -join is here to support ConvertFrom-Json on PowerShell 3.0 + return (EF $dteProject $dteStartupProject $params) -join "`n" | ConvertFrom-Json +} + +# +# Remove-Migration +# + +Register-TabExpansion Remove-Migration @{ + Context = { param($x) GetContextTypes $x.Project $x.StartupProject } + Project = { GetProjects } + StartupProject = { GetProjects } +} + +<# +.SYNOPSIS + Removes the last migration. + +.DESCRIPTION + Removes the last migration. + +.PARAMETER Force + Don't check to see if the migration has been applied to the database. Always implied on UWP apps. + +.PARAMETER Context + The DbContext to use. + +.PARAMETER Project + The project to use. + +.PARAMETER StartupProject + The startup project to use. Defaults to the solution's startup project. + +.LINK + Add-Migration + about_EntityFrameworkCore +#> +function Remove-Migration +{ + [CmdletBinding(PositionalBinding = $false)] + param([switch] $Force, [string] $Context, [string] $Project, [string] $StartupProject) + + $dteProject = GetProject $Project + $dteStartupProject = GetStartupProject $StartupProject $dteProject + + $params = 'migrations', 'remove', '--json' + + if ($Force) + { + $params += '--force' + } + + $params += GetParams $Context + + # NB: -join is here to support ConvertFrom-Json on PowerShell 3.0 + $result = (EF $dteProject $dteStartupProject $params) -join "`n" | ConvertFrom-Json + + $files = $result.migrationFile, $result.metadataFile, $result.snapshotFile + $files | ?{ $_ -ne $null } | %{ + $projectItem = GetProjectItem $dteProject $_ + if ($projectItem) + { + $projectItem.Remove() + } + } +} + +# +# Scaffold-DbContext +# + +Register-TabExpansion Scaffold-DbContext @{ + Provider = { param($x) GetProviders $x.Project } + Project = { GetProjects } + StartupProject = { GetProjects } + OutputDir = { <# Disabled. Otherwise, paths would be relative to the solution directory. #> } +} + +<# +.SYNOPSIS + Scaffolds a DbContext and entity types for a database. + +.DESCRIPTION + Scaffolds a DbContext and entity types for a database. + +.PARAMETER Connection + The connection string to the database. + +.PARAMETER Provider + The provider to use. (E.g. Microsoft.EntityFrameworkCore.SqlServer) + +.PARAMETER OutputDir + The directory to put files in. Paths are relaive to the project directory. + +.PARAMETER Context + The name of the DbContext to generate. + +.PARAMETER Schemas + The schemas of tables to generate entity types for. + +.PARAMETER Tables + The tables to generate entity types for. + +.PARAMETER DataAnnotations + Use attributes to configure the model (where possible). If omitted, only the fluent API is used. + +.PARAMETER Force + Overwrite existing files. + +.PARAMETER Project + The project to use. + +.PARAMETER StartupProject + The startup project to use. Defaults to the solution's startup project. + +.LINK + about_EntityFrameworkCore +#> +function Scaffold-DbContext +{ + [CmdletBinding(PositionalBinding = $false)] + param( + [Parameter(Position = 0, Mandatory = $true)] + [string] $Connection, + [Parameter(Position = 1, Mandatory = $true)] + [string] $Provider, + [string] $OutputDir, + [string] $Context, + [string[]] $Schemas = @(), + [string[]] $Tables = @(), + [switch] $DataAnnotations, + [switch] $Force, + [string] $Project, + [string] $StartupProject) + + $dteProject = GetProject $Project + $dteStartupProject = GetStartupProject $StartupProject $dteProject + + $params = 'dbcontext', 'scaffold', $Connection, $Provider, '--json' + + if ($OutputDir) + { + $params += '--output-dir', $OutputDir + } + + if ($Context) + { + $params += '--context', $Context + } + + $params += $Schemas | %{ '--schema', $_ } + $params += $Tables | %{ '--table', $_ } + + if ($DataAnnotations) + { + $params += '--data-annotations' + } + + if ($Force) + { + $params += '--force' + } + + # NB: -join is here to support ConvertFrom-Json on PowerShell 3.0 + $result = (EF $dteProject $dteStartupProject $params) -join "`n" | ConvertFrom-Json + + $files = $result.entityTypeFiles + $result.contextFile + $files | %{ $dteProject.ProjectItems.AddFromFile($_) | Out-Null } + $DTE.ItemOperations.OpenFile($result.contextFile) | Out-Null + ShowConsole +} + +# +# Script-Migration +# + +Register-TabExpansion Script-Migration @{ + From = { param($x) GetMigrations $x.Context $x.Project $x.StartupProject } + To = { param($x) GetMigrations $x.Context $x.Project $x.StartupProject } + Context = { param($x) GetContextTypes $x.Project $x.StartupProject } + Project = { GetProjects } + StartupProject = { GetProjects } +} + +<# +.SYNOPSIS + Generates a SQL script from migrations. + +.DESCRIPTION + Generates a SQL script from migrations. + +.PARAMETER From + The starting migration. Defaults to '0' (the initial database). + +.PARAMETER To + The ending migration. Defaults to the last migration. + +.PARAMETER Idempotent + Generate a script that can be used on a database at any migration. + +.PARAMETER Output + The file to write the result to. + +.PARAMETER Context + The DbContext to use. + +.PARAMETER Project + The project to use. + +.PARAMETER StartupProject + The startup project to use. Defaults to the solution's startup project. + +.LINK + Update-Database + about_EntityFrameworkCore +#> +function Script-Migration +{ + [CmdletBinding(PositionalBinding = $false)] + param( + [Parameter(ParameterSetName = 'WithoutTo', Position = 0)] + [Parameter(ParameterSetName = 'WithTo', Position = 0, Mandatory = $true)] + [string] $From, + [Parameter(ParameterSetName = 'WithTo', Position = 1, Mandatory = $true)] + [string] $To, + [switch] $Idempotent, + [string] $Output, + [string] $Context, + [string] $Project, + [string] $StartupProject) + + $dteProject = GetProject $Project + $dteStartupProject = GetStartupProject $StartupProject $dteProject + + if (!$Output) + { + $intermediatePath = GetIntermediatePath $dteProject + if (!(Split-Path $intermediatePath -IsAbsolute)) + { + $projectDir = GetProperty $dteProject.Properties 'FullPath' + $intermediatePath = Join-Path $projectDir $intermediatePath -Resolve | Convert-Path + } + + $scriptFileName = [IO.Path]::ChangeExtension([IO.Path]::GetRandomFileName(), '.sql') + $Output = Join-Path $intermediatePath $scriptFileName + } + elseif (!(Split-Path $Output -IsAbsolute)) + { + $Output = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Output) + } + + $params = 'migrations', 'script', '--output', $Output + + if ($From) + { + $params += $From + } + + if ($To) + { + $params += $To + } + + if ($Idempotent) + { + $params += '--idempotent' + } + + $params += GetParams $Context + + EF $dteProject $dteStartupProject $params + + $DTE.ItemOperations.OpenFile($Output) | Out-Null + ShowConsole +} + +# +# Update-Database +# + +Register-TabExpansion Update-Database @{ + Migration = { param($x) GetMigrations $x.Context $x.Project $x.StartupProject } + Context = { param($x) GetContextTypes $x.Project $x.StartupProject } + Project = { GetProjects } + StartupProject = { GetProjects } +} + +<# +.SYNOPSIS + Updates the database to a specified migration. + +.DESCRIPTION + Updates the database to a specified migration. + +.PARAMETER Migration + The target migration. If '0', all migrations will be reverted. Defaults to the last migration. + +.PARAMETER Context + The DbContext to use. + +.PARAMETER Project + The project to use. + +.PARAMETER StartupProject + The startup project to use. Defaults to the solution's startup project. + +.LINK + Script-Migration + about_EntityFrameworkCore +#> +function Update-Database +{ + [CmdletBinding(PositionalBinding = $false)] + param( + [Parameter(Position = 0)] + [string] $Migration, + [string] $Context, + [string] $Project, + [string] $StartupProject) + + WarnIfEF6 'Update-Database' + + $dteProject = GetProject $Project + $dteStartupProject = GetStartupProject $StartupProject $dteProject + + $params = 'database', 'update' + + if ($Migration) + { + $params += $Migration + } + + $params += GetParams $Context + + EF $dteProject $dteStartupProject $params +} + +# +# (Private Helpers) +# + +function GetProjects +{ + return Get-Project -All | %{ $_.ProjectName } +} + +function GetProviders($projectName) +{ + if (!$projectName) + { + $projectName = (Get-Project).ProjectName + } + + return Get-Package -ProjectName $projectName | %{ $_.Id } +} + +function GetContextTypes($projectName, $startupProjectName) +{ + $project = GetProject $projectName + $startupProject = GetStartupProject $startupProjectName $project + + $params = 'dbcontext', 'list', '--json' + + # NB: -join is here to support ConvertFrom-Json on PowerShell 3.0 + $result = (EF $project $startupProject $params -skipBuild) -join "`n" | ConvertFrom-Json + + return $result | %{ $_.safeName } +} + +function GetMigrations($context, $projectName, $startupProjectName) +{ + $project = GetProject $projectName + $startupProject = GetStartupProject $startupProjectName $project + + $params = 'migrations', 'list', '--json' + $params += GetParams $context + + # NB: -join is here to support ConvertFrom-Json on PowerShell 3.0 + $result = (EF $project $startupProject $params -skipBuild) -join "`n" | ConvertFrom-Json + + return $result | %{ $_.safeName } +} + +function WarnIfEF6 ($cmdlet) +{ + if (Get-Module 'EntityFramework') + { + Write-Warning "Both Entity Framework Core and Entity Framework 6 are installed. The Entity Framework Core tools are running. Use 'EntityFramework\$cmdlet' for Entity Framework 6." + } +} + +function GetProject($projectName) +{ + if (!$projectName) + { + return Get-Project + } + + return Get-Project $projectName +} + +function GetStartupProject($name, $fallbackProject) +{ + if ($name) + { + return Get-Project $name + } + + $startupProjectPaths = $DTE.Solution.SolutionBuild.StartupProjects + if ($startupProjectPaths) + { + if ($startupProjectPaths.Length -eq 1) + { + $startupProjectPath = $startupProjectPaths[0] + if (!(Split-Path -IsAbsolute $startupProjectPath)) + { + $solutionPath = Split-Path (GetProperty $DTE.Solution.Properties 'Path') + $startupProjectPath = Join-Path $solutionPath $startupProjectPath -Resolve | Convert-Path + } + + $startupProject = GetSolutionProjects | ?{ + try + { + $fullName = $_.FullName + } + catch [NotImplementedException] + { + return $false + } + + if ($fullName -and $fullName.EndsWith('\')) + { + $fullName = $fullName.Substring(0, $fullName.Length - 1) + } + + return $fullName -eq $startupProjectPath + } + if ($startupProject) + { + return $startupProject + } + + Write-Warning "Unable to resolve startup project '$startupProjectPath'." + } + else + { + Write-Verbose 'More than one startup project found.' + } + } + else + { + Write-Verbose 'No startup project found.' + } + + return $fallbackProject +} + +function GetSolutionProjects() +{ + $projects = New-Object 'System.Collections.Stack' + + $DTE.Solution.Projects | %{ + $projects.Push($_) + } + + while ($projects.Count) + { + $project = $projects.Pop(); + + <# yield return #> $project + + if ($project.ProjectItems) + { + $project.ProjectItems | ?{ $_.SubProject } | %{ + $projects.Push($_.SubProject) + } + } + } +} + +function GetParams($context) +{ + $params = @() + + if ($context) + { + $params += '--context', $context + } + + return $params +} + +function ShowConsole +{ + $componentModel = Get-VSComponentModel + $powerConsoleWindow = $componentModel.GetService([NuGetConsole.IPowerConsoleWindow]) + $powerConsoleWindow.Show() +} + +function WriteErrorLine($message) +{ + try + { + # Call the internal API NuGet uses to display errors + $componentModel = Get-VSComponentModel + $powerConsoleWindow = $componentModel.GetService([NuGetConsole.IPowerConsoleWindow]) + $bindingFlags = [Reflection.BindingFlags]::Instance -bor [Reflection.BindingFlags]::NonPublic + $activeHostInfo = $powerConsoleWindow.GetType().GetProperty('ActiveHostInfo', $bindingFlags).GetValue($powerConsoleWindow) + $internalHost = $activeHostInfo.WpfConsole.Host + $reportErrorMethod = $internalHost.GetType().GetMethod('ReportError', $bindingFlags, $null, [Exception], $null) + $exception = New-Object Exception $message + $reportErrorMethod.Invoke($internalHost, $exception) + } + catch + { + Write-Host $message -ForegroundColor DarkRed + } +} + +function EF($project, $startupProject, $params, [switch] $skipBuild) +{ + if (IsXproj $startupProject) + { + throw "Startup project '$($startupProject.ProjectName)' is an ASP.NET Core or .NET Core project for Visual " + + 'Studio 2015. This version of the Entity Framework Core Package Manager Console Tools doesn''t support ' + + 'these types of projects.' + } + if (IsDocker $startupProject) + { + throw "Startup project '$($startupProject.ProjectName)' is a Docker project. Select an ASP.NET Core Web " + + 'Application as your startup project and try again.' + } + if (IsUWP $startupProject) + { + throw "Startup project '$($startupProject.ProjectName)' is a Universal Windows Platform app. This version of " + + 'the Entity Framework Core Package Manager Console Tools doesn''t support this type of project. For more ' + + 'information on using the EF Core Tools with UWP projects, see ' + + 'https://go.microsoft.com/fwlink/?linkid=858496' + } + + Write-Verbose "Using project '$($project.ProjectName)'." + Write-Verbose "Using startup project '$($startupProject.ProjectName)'." + + if (!$skipBuild) + { + Write-Verbose 'Build started...' + + # TODO: Only build startup project. Don't use BuildProject, you can't specify platform + $solutionBuild = $DTE.Solution.SolutionBuild + $solutionBuild.Build(<# WaitForBuildToFinish: #> $true) + if ($solutionBuild.LastBuildInfo) + { + throw 'Build failed.' + } + + Write-Verbose 'Build succeeded.' + } + + $startupProjectDir = GetProperty $startupProject.Properties 'FullPath' + $outputPath = GetProperty $startupProject.ConfigurationManager.ActiveConfiguration.Properties 'OutputPath' + $targetDir = Join-Path $startupProjectDir $outputPath -Resolve | Convert-Path + $startupTargetFileName = GetOutputFileName $startupProject + $startupTargetPath = Join-Path $targetDir $startupTargetFileName + $targetFrameworkMoniker = GetProperty $startupProject.Properties 'TargetFrameworkMoniker' + $frameworkName = New-Object 'System.Runtime.Versioning.FrameworkName' $targetFrameworkMoniker + $targetFramework = $frameworkName.Identifier + + if ($targetFramework -in '.NETFramework') + { + $platformTarget = GetPlatformTarget $startupProject + if ($platformTarget -eq 'x86') + { + $exePath = Join-Path $PSScriptRoot 'net461\ef.x86.exe' + } + elseif ($platformTarget -in 'AnyCPU', 'x64') + { + $exePath = Join-Path $PSScriptRoot 'net461\ef.exe' + } + else + { + throw "Startup project '$($startupProject.ProjectName)' has an active platform of '$platformTarget'. Select " + + 'a different platform and try again.' + } + } + elseif ($targetFramework -eq '.NETCoreApp') + { + $exePath = (Get-Command 'dotnet').Path + + $startupTargetName = GetProperty $startupProject.Properties 'AssemblyName' + $depsFile = Join-Path $targetDir ($startupTargetName + '.deps.json') + $projectAssetsFile = GetCsproj2Property $startupProject 'ProjectAssetsFile' + $runtimeConfig = Join-Path $targetDir ($startupTargetName + '.runtimeconfig.json') + $runtimeFrameworkVersion = GetCsproj2Property $startupProject 'RuntimeFrameworkVersion' + $efPath = Join-Path $PSScriptRoot 'netcoreapp2.0\ef.dll' + + $dotnetParams = 'exec', '--depsfile', $depsFile + + if ($projectAssetsFile) + { + # NB: -Raw is here to support ConvertFrom-Json on PowerShell 3.0 + $projectAssets = Get-Content $projectAssetsFile -Raw | ConvertFrom-Json + $projectAssets.packageFolders.psobject.Properties.Name | %{ + $dotnetParams += '--additionalprobingpath', $_.TrimEnd('\') + } + } + + if (Test-Path $runtimeConfig) + { + $dotnetParams += '--runtimeconfig', $runtimeConfig + } + elseif ($runtimeFrameworkVersion) + { + $dotnetParams += '--fx-version', $runtimeFrameworkVersion + } + + $dotnetParams += $efPath + + $params = $dotnetParams + $params + } + elseif ($targetFramework -eq '.NETStandard') + { + throw "Startup project '$($startupProject.ProjectName)' targets framework '.NETStandard'. There is no " + + 'runtime associated with this framework, and projects targeting it cannot be executed directly. To use ' + + 'the Entity Framework Core Package Manager Console Tools with this project, add an executable project ' + + 'targeting .NET Framework or .NET Core that references this project, and set it as the startup project; ' + + 'or, update this project to cross-target .NET Framework or .NET Core.' + } + else + { + throw "Startup project '$($startupProject.ProjectName)' targets framework '$targetFramework'. " + + 'The Entity Framework Core Package Manager Console Tools don''t support this framework.' + } + + $projectDir = GetProperty $project.Properties 'FullPath' + $targetFileName = GetOutputFileName $project + $targetPath = Join-Path $targetDir $targetFileName + $rootNamespace = GetProperty $project.Properties 'RootNamespace' + + $params += '--verbose', + '--no-color', + '--prefix-output', + '--assembly', $targetPath, + '--startup-assembly', $startupTargetPath, + '--project-dir', $projectDir + + if (IsWeb $startupProject) + { + $params += '--data-dir', (Join-Path $startupProjectDir 'App_Data') + } + + if ($rootNamespace) + { + $params += '--root-namespace', $rootNamespace + } + + $arguments = ToArguments $params + $startInfo = New-Object 'System.Diagnostics.ProcessStartInfo' -Property @{ + FileName = $exePath; + Arguments = $arguments; + UseShellExecute = $false; + CreateNoWindow = $true; + RedirectStandardOutput = $true; + StandardOutputEncoding = [Text.Encoding]::UTF8; + WorkingDirectory = $startupProjectDir; + } + + Write-Verbose "$exePath $arguments" + + $process = [Diagnostics.Process]::Start($startInfo) + + while ($line = $process.StandardOutput.ReadLine()) + { + $level = $null + $text = $null + + $parts = $line.Split(':', 2) + if ($parts.Length -eq 2) + { + $level = $parts[0] + + $i = 0 + $count = 8 - $level.Length + while ($i -lt $count -and $parts[1][$i] -eq ' ') + { + $i++ + } + + $text = $parts[1].Substring($i) + } + + switch ($level) + { + 'error' { WriteErrorLine $text } + 'warn' { Write-Warning $text } + 'info' { Write-Host $text } + 'data' { Write-Output $text } + 'verbose' { Write-Verbose $text } + default { Write-Host $line } + } + } + + $process.WaitForExit() + + if ($process.ExitCode) + { + exit + } +} + +function IsXproj($project) +{ + return $project.Kind -eq '{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}' +} + +function IsDocker($project) +{ + return $project.Kind -eq '{E53339B2-1760-4266-BCC7-CA923CBCF16C}' +} + +function IsCsproj2($project) +{ + return $project.Kind -eq '{9A19103F-16F7-4668-BE54-9A1E7A4F7556}' +} + +function IsWeb($project) +{ + $types = GetProjectTypes $project + + return $types -contains '{349C5851-65DF-11DA-9384-00065B846F21}' +} + +function IsUWP($project) +{ + $types = GetProjectTypes $project + + return $types -contains '{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A}' +} + +function GetIntermediatePath($project) +{ + # TODO: Remove when dotnet/roslyn-project-system#665 is fixed + if (IsCsproj2 $project) + { + return GetCsproj2Property $project 'IntermediateOutputPath' + } + + return GetProperty $project.ConfigurationManager.ActiveConfiguration.Properties 'IntermediatePath' +} + +function GetPlatformTarget($project) +{ + # TODO: Remove when dotnet/roslyn-project-system#669 is fixed + if (IsCsproj2 $project) + { + $platformTarget = GetCsproj2Property $project 'PlatformTarget' + if ($platformTarget) + { + return $platformTarget + } + + return GetCsproj2Property $project 'Platform' + } + + return GetProperty $project.ConfigurationManager.ActiveConfiguration.Properties 'PlatformTarget' +} + +function GetOutputFileName($project) +{ + # TODO: Remove when dotnet/roslyn-project-system#667 is fixed + if (IsCsproj2 $project) + { + return GetCsproj2Property $project 'TargetFileName' + } + + return GetProperty $project.Properties 'OutputFileName' +} + +function GetProjectTypes($project) +{ + $solution = Get-VSService 'Microsoft.VisualStudio.Shell.Interop.SVsSolution' 'Microsoft.VisualStudio.Shell.Interop.IVsSolution' + $hierarchy = $null + $hr = $solution.GetProjectOfUniqueName($project.UniqueName, [ref] $hierarchy) + [Runtime.InteropServices.Marshal]::ThrowExceptionForHR($hr) + + $aggregatableProject = Get-Interface $hierarchy 'Microsoft.VisualStudio.Shell.Interop.IVsAggregatableProject' + if (!$aggregatableProject) + { + return $project.Kind + } + + $projectTypeGuidsString = $null + $hr = $aggregatableProject.GetAggregateProjectTypeGuids([ref] $projectTypeGuidsString) + [Runtime.InteropServices.Marshal]::ThrowExceptionForHR($hr) + + return $projectTypeGuidsString.Split(';') +} + +function GetProperty($properties, $propertyName) +{ + try + { + return $properties.Item($propertyName).Value + } + catch + { + return $null + } +} + +function GetCsproj2Property($project, $propertyName) +{ + $browseObjectContext = Get-Interface $project 'Microsoft.VisualStudio.ProjectSystem.Properties.IVsBrowseObjectContext' + $unconfiguredProject = $browseObjectContext.UnconfiguredProject + $configuredProject = $unconfiguredProject.GetSuggestedConfiguredProjectAsync().Result + $properties = $configuredProject.Services.ProjectPropertiesProvider.GetCommonProperties() + + return $properties.GetEvaluatedPropertyValueAsync($propertyName).Result +} + +function GetProjectItem($project, $path) +{ + $fullPath = GetProperty $project.Properties 'FullPath' + + if (Split-Path $path -IsAbsolute) + { + $path = $path.Substring($fullPath.Length) + } + + $itemDirectory = (Split-Path $path -Parent) + + $projectItems = $project.ProjectItems + if ($itemDirectory) + { + $directories = $itemDirectory.Split('\') + $directories | %{ + if ($projectItems) + { + $projectItems = $projectItems.Item($_).ProjectItems + } + } + } + + if (!$projectItems) + { + return $null + } + + $itemName = Split-Path $path -Leaf + + try + { + return $projectItems.Item($itemName) + } + catch [Exception] + { + } + + return $null +} + +function ToArguments($params) +{ + $arguments = '' + for ($i = 0; $i -lt $params.Length; $i++) + { + if ($i) + { + $arguments += ' ' + } + + if (!$params[$i].Contains(' ')) + { + $arguments += $params[$i] + + continue + } + + $arguments += '"' + + $pendingBackslashs = 0 + for ($j = 0; $j -lt $params[$i].Length; $j++) + { + switch ($params[$i][$j]) + { + '"' + { + if ($pendingBackslashs) + { + $arguments += '\' * $pendingBackslashs * 2 + $pendingBackslashs = 0 + } + $arguments += '\"' + } + + '\' + { + $pendingBackslashs++ + } + + default + { + if ($pendingBackslashs) + { + if ($pendingBackslashs -eq 1) + { + $arguments += '\' + } + else + { + $arguments += '\' * $pendingBackslashs * 2 + } + + $pendingBackslashs = 0 + } + + $arguments += $params[$i][$j] + } + } + } + + if ($pendingBackslashs) + { + $arguments += '\' * $pendingBackslashs * 2 + } + + $arguments += '"' + } + + return $arguments +} + +# SIG # Begin signature block +# MIIkAQYJKoZIhvcNAQcCoIIj8jCCI+4CAQExDzANBglghkgBZQMEAgEFADB5Bgor +# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG +# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCEuN1vwMR4xAKv +# ohj10lo4t9IRE5afGB03p+0x7v+21qCCDYIwggYAMIID6KADAgECAhMzAAAAww6b +# p9iy3PcsAAAAAADDMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD +# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p +# bmcgUENBIDIwMTEwHhcNMTcwODExMjAyMDI0WhcNMTgwODExMjAyMDI0WjB0MQsw +# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u +# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy +# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +# AQC7V9c40bEGf0ktqW2zY596urY6IVu0mK6N1KSBoMV1xSzvgkAqt4FTd/NjAQq8 +# zjeEA0BDV4JLzu0ftv2AbcnCkV0Fx9xWWQDhDOtX3v3xuJAnv3VK/HWycli2xUib +# M2IF0ZWUpb85Iq2NEk1GYtoyGc6qIlxWSLFvRclndmJdMIijLyjFH1Aq2YbbGhEl +# gcL09Wcu53kd9eIcdfROzMf8578LgEcp/8/NabEMC2DrZ+aEG5tN/W1HOsfZwWFh +# 8pUSoQ0HrmMh2PSZHP94VYHupXnoIIJfCtq1UxlUAVcNh5GNwnzxVIaA4WLbgnM+ +# Jl7wQBLSOdUmAw2FiDFfCguLAgMBAAGjggF/MIIBezAfBgNVHSUEGDAWBgorBgEE +# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUpxNdHyGJVegD7p4XNuryVIg1Ga8w +# UQYDVR0RBEowSKRGMEQxDDAKBgNVBAsTA0FPQzE0MDIGA1UEBRMrMjMwMDEyK2M4 +# MDRiNWVhLTQ5YjQtNDIzOC04MzYyLWQ4NTFmYTIyNTRmYzAfBgNVHSMEGDAWgBRI +# bmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3 +# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEt +# MDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3 +# dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIw +# MTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAE2X +# TzR+8XCTnOPVGkucEX5rJsSlJPTfRNQkurNqCImZmssx53Cb/xQdsAc5f+QwOxMi +# 3g7IlWe7bn74fJWkkII3k6aD00kCwaytWe+Rt6dmAA6iTCXU3OddBwLKKDRlOzmD +# rZUqjsqg6Ag6HP4+e0BJlE2OVCUK5bHHCu5xN8abXjb1p0JE+7yHsA3ANdkmh1// +# Z+8odPeKMAQRimfMSzVgaiHnw40Hg16bq51xHykmCRHU9YLT0jYHKa7okm2QfwDJ +# qFvu0ARl+6EOV1PM8piJ858Vk8gGxGNSYQJPV0gc9ft1Esq1+fTCaV+7oZ0NaYMn +# 64M+HWsxw+4O8cSEQ4fuMZwGADJ8tyCKuQgj6lawGNSyvRXsN+1k02sVAiPGijOH +# OtGbtsCWWSygAVOEAV/ye8F6sOzU2FL2X3WBRFkWOCdTu1DzXnHf99dR3DHVGmM1 +# Kpd+n2Y3X89VM++yyrwsI6pEHu77Z0i06ELDD4pRWKJGAmEmWhm/XJTpqEBw51sw +# THyA1FBnoqXuDus9tfHleR7h9VgZb7uJbXjiIFgl/+RIs+av8bJABBdGUNQMbJEU +# fe7K4vYm3hs7BGdRLg+kF/dC/z+RiTH4p7yz5TpS3Cozf0pkkWXYZRG222q3tGxS +# /L+LcRbELM5zmqDpXQjBRUWlKYbsATFtXnTGVjELMIIHejCCBWKgAwIBAgIKYQ6Q +# 0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT +# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m +# dCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh +# dGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5 +# WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH +# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQD +# Ex9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0B +# AQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4 +# BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe +# 0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato +# 88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v +# ++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDst +# rjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN +# 91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4ji +# JV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmh +# D+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbi +# wZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8Hh +# hUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaI +# jAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTl +# UAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNV +# HQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQF +# TuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29m +# dC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNf +# MjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5t +# aWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNf +# MjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcC +# ARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnlj +# cHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5 +# AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oal +# mOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0ep +# o/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1 +# HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtY +# SWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInW +# H8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZ +# iWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMd +# YzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7f +# QccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKf +# enoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOpp +# O6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZO +# SEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCFdUwghXRAgEBMIGVMH4xCzAJ +# BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k +# MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jv +# c29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAADDDpun2LLc9ywAAAAAAMMw +# DQYJYIZIAWUDBAIBBQCggcQwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYK +# KwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIK4CTAgm +# 7BC2ASJnX3bqlcGz0P11baIjCGQvpHmU/9NxMFgGCisGAQQBgjcCAQwxSjBIoC6A +# LABNAGkAYwByAG8AcwBvAGYAdAAgAEEAUwBQAC4ATgBFAFQAIABDAG8AcgBloRaA +# FGh0dHBzOi8vd3d3LmFzcC5uZXQvMA0GCSqGSIb3DQEBAQUABIIBALIEg6ZLeRA7 +# MxxDDu8MTmCBIfUvvrLZTti5M1+8Oz5gGQD+KGlT/PSzBiWV9V7o4udK+TO/SiAL +# M/kdGI3wjgvNSXEIiaRLu4xSnOEcdy/kMU9cu9Wkyo9MjVj2XvVz5DN6GV//h7cZ +# ulDo0SvQoKSIRXlClK45UVt6sLFQrNxZKF6O4roy7Uy4+031Dfch883k9spGKeoy +# lbzk/luDIL0/bMp2bYDyTHxT4fwVA4dn0PHvjxi3s2FXgqg+zZVgxa9rrjLmz864 +# fPT/1ksJFd2s5aYrwTD+c5MxXeap01eaz8ghyYRTl4Aj6b/Cfjgd78qpVEQ5S3NE +# F72x3Ey1huyhghNJMIITRQYKKwYBBAGCNwMDATGCEzUwghMxBgkqhkiG9w0BBwKg +# ghMiMIITHgIBAzEPMA0GCWCGSAFlAwQCAQUAMIIBPAYLKoZIhvcNAQkQAQSgggEr +# BIIBJzCCASMCAQEGCisGAQQBhFkKAwEwMTANBglghkgBZQMEAgEFAAQgnShDyWC/ +# QgNQJ9B0vW5JP2j4/8G9uMlCaOcCk1AF7wECBlna3OyvuRgTMjAxNzEwMzAyMzU0 +# MTYuMDI4WjAHAgEBgAIB9KCBuKSBtTCBsjELMAkGA1UEBhMCVVMxEzARBgNVBAgT +# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m +# dCBDb3Jwb3JhdGlvbjEMMAoGA1UECxMDQU9DMScwJQYDVQQLEx5uQ2lwaGVyIERT +# RSBFU046MTJCNC0yRDVGLTg3RDQxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0 +# YW1wIFNlcnZpY2Wggg7NMIIGcTCCBFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG +# 9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO +# BgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEy +# MDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw +# MTAwHhcNMTAwNzAxMjEzNjU1WhcNMjUwNzAxMjE0NjU1WjB8MQswCQYDVQQGEwJV +# UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE +# ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGlt +# ZS1TdGFtcCBQQ0EgMjAxMDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +# AKkdDbx3EYo6IOz8E5f1+n9plGt0VBDVpQoAgoX77XxoSyxfxcPlYcJ2tz5mK1vw +# FVMnBDEfQRsalR3OCROOfGEwWbEwRA/xYIiEVEMM1024OAizQt2TrNZzMFcmgqNF +# DdDq9UeBzb8kYDJYYEbyWEeGMoQedGFnkV+BVLHPk0ySwcSmXdFhE24oxhr5hoC7 +# 32H8RsEnHSRnEnIaIYqvS2SJUGKxXf13Hz3wV3WsvYpCTUBR0Q+cBj5nf/VmwAOW +# RH7v0Ev9buWayrGo8noqCjHw2k4GkbaICDXoeByw6ZnNPOcvRLqn9NxkvaQBwSAJ +# k3jN/LzAyURdXhacAQVPIk0CAwEAAaOCAeYwggHiMBAGCSsGAQQBgjcVAQQDAgEA +# MB0GA1UdDgQWBBTVYzpcijGQ80N7fEYbxTNoWoVtVTAZBgkrBgEEAYI3FAIEDB4K +# AFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME +# GDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRw +# Oi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJB +# dXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5o +# dHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8y +# MDEwLTA2LTIzLmNydDCBoAYDVR0gAQH/BIGVMIGSMIGPBgkrBgEEAYI3LgMwgYEw +# PQYIKwYBBQUHAgEWMWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9QS0kvZG9jcy9D +# UFMvZGVmYXVsdC5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AUABv +# AGwAaQBjAHkAXwBTAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQAD +# ggIBAAfmiFEN4sbgmD+BcQM9naOhIW+z66bM9TG+zwXiqf76V20ZMLPCxWbJat/1 +# 5/B4vceoniXj+bzta1RXCCtRgkQS+7lTjMz0YBKKdsxAQEGb3FwX/1z5Xhc1mCRW +# S3TvQhDIr79/xn/yN31aPxzymXlKkVIArzgPF/UveYFl2am1a+THzvbKegBvSzBE +# JCI8z+0DpZaPWSm8tv0E4XCfMkon/VWvL/625Y4zu2JfmttXQOnxzplmkIz/amJ/ +# 3cVKC5Em4jnsGUpxY517IW3DnKOiPPp/fZZqkHimbdLhnPkd/DjYlPTGpQqWhqS9 +# nhquBEKDuLWAmyI4ILUl5WTs9/S/fmNZJQ96LjlXdqJxqgaKD4kWumGnEcua2A5H +# moDF0M2n0O99g/DhO3EJ3110mCIIYdqwUB5vvfHhAN/nMQekkzr3ZUd46PioSKv3 +# 3nJ+YWtvd6mBy6cJrDm77MbL2IK0cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI +# 5pgt6o3gMy4SKfXAL1QnIffIrE7aKLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0 +# MkvfY3v1mYovG8chr1m1rtxEPJdQcdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0e +# GTgvvM9YBS7vDaBQNdrvCScc1bN+NR4Iuto229Nfj950iEkSMIIE2TCCA8GgAwIB +# AgITMwAAAKdkXcUoDwE9RAAAAAAApzANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQG +# EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG +# A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg +# VGltZS1TdGFtcCBQQ0EgMjAxMDAeFw0xNjA5MDcxNzU2NTJaFw0xODA5MDcxNzU2 +# NTJaMIGyMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE +# BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMQwwCgYD +# VQQLEwNBT0MxJzAlBgNVBAsTHm5DaXBoZXIgRFNFIEVTTjoxMkI0LTJENUYtODdE +# NDElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCCASIwDQYJ +# KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbqGlDAX0/SU/mh7AR8DdcgVzEhUdjH +# 7gMKLnjOiy4iI2uWNhAfClF6heddFP5zstfSfGNVwQq4xpQ06LiJ2RecCbEYoZE/ +# Q1ZVVtlbxU/Wg37k6BCIG0x6G5Ci1LUC09H4v5vO/zVq1S6OTJNGerN9TlLQGBHY +# zJfMTJTkcotQ/OrSUgkQOIMRuJYDMThcQY06KYcRWBOjDq19rd765m7K0Lihc22+ +# tamlZ0lrB3x5iLRmNvIxJzgU4jUfwSddeMjiKjJrZ4FGUwXWe0M1akQw7bsh7TdJ +# f7JECZvaWcArPpL4DsAmSxeK7wjTVOeMC4+KjVL2oHmoT2YGMrmLKvECAwEAAaOC +# ARswggEXMB0GA1UdDgQWBBR8DUoLfftP/14QLD15byBNQlCIXTAfBgNVHSMEGDAW +# gBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8v +# Y3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNUaW1TdGFQQ0Ff +# MjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRw +# Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0YVBDQV8yMDEw +# LTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMIMA0G +# CSqGSIb3DQEBCwUAA4IBAQCaxiRL55eyUgFkhw/iQpMoVnl29PkKFWdNeg6JgDw/ +# M0LejnLyXKbzeLO5sIXSjyXt24q94Sx9VmAEEs8n82N4+EZUVEoW2mvqXLv7hnps +# Xn9Nc2KgNp2w3rPpzxJijPrwnGwkDGuILpGXvt9OMoxcbieEJ3mbncvf6OwRCwAJ +# XHovaiX20vY6KodtR3bMVa9OtvHVehqz+ZwdCEgo/XH/XgebJUKwo/gL/WHSX7p0 +# 6GHV8+LgRL8pDeOK8G1djFri5Q4NgQfRK47SeVCZrQGiyzUBur4AQoMjcbYdYIeq +# jFv+e+1whg4IcbVXhS+UECNttB+8o0a35RZLrvCutrpOoYIDdzCCAl8CAQEwgeKh +# gbikgbUwgbIxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD +# VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xDDAK +# BgNVBAsTA0FPQzEnMCUGA1UECxMebkNpcGhlciBEU0UgRVNOOjEyQjQtMkQ1Ri04 +# N0Q0MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiUKAQEw +# CQYFKw4DAhoFAAMVAOSCLp0yNm10ADIPHsEhtA3rDHfZoIHBMIG+pIG7MIG4MQsw +# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u +# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMQwwCgYDVQQLEwNBT0Mx +# JzAlBgNVBAsTHm5DaXBoZXIgTlRTIEVTTjoyNjY1LTRDM0YtQzVERTErMCkGA1UE +# AxMiTWljcm9zb2Z0IFRpbWUgU291cmNlIE1hc3RlciBDbG9jazANBgkqhkiG9w0B +# AQUFAAIFAN2iFY8wIhgPMjAxNzEwMzAyMTE4MDdaGA8yMDE3MTAzMTIxMTgwN1ow +# dzA9BgorBgEEAYRZCgQBMS8wLTAKAgUA3aIVjwIBADAKAgEAAgIcAQIB/zAHAgEA +# AgIZuTAKAgUA3aNnDwIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMB +# oAowCAIBAAIDFuNgoQowCAIBAAIDB6EgMA0GCSqGSIb3DQEBBQUAA4IBAQBBrBgf +# 4Pex4VbTUYXZvHmsNNF8WHg8GDCvtNJy9NbJpoJ2L1qLz5MnsEGt1Xh9pTIMoKUp +# 6mZbYpb9Gqya6ojLrjHggvgfbqrou8047YLFBONkTtiXdF34S4SN/ByLoydnVnho +# zrScYViUCFT0gQ39sjdRX4UbV+vZn+Fb3lzXFLtakoPH4s/08j7vtcTc92SVwLn9 +# ddFfVrAMWyao8oYhoQeTmBBklwjwrAit36zWAqpC8y9gzPn08DXLOzYAwVaD3Me8 +# Plv578m4sVVlaKotyXDa8itaYSJwRy82coORriIGjbsXt7P2Yi/vmu9oShaU3kt6 +# zrntQ3hmv9BnfwZ8MYIC9TCCAvECAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNV +# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv +# c29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAg +# UENBIDIwMTACEzMAAACnZF3FKA8BPUQAAAAAAKcwDQYJYIZIAWUDBAIBBQCgggEy +# MBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgiAsg +# BA8r+TUzxGuficwZ23EW+v206lAvSDjL5aBbPogwgeIGCyqGSIb3DQEJEAIMMYHS +# MIHPMIHMMIGxBBTkgi6dMjZtdAAyDx7BIbQN6wx32TCBmDCBgKR+MHwxCzAJBgNV +# BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w +# HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29m +# dCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAAp2RdxSgPAT1EAAAAAACnMBYEFJF8 +# Crj19kUQBRS2aTH4u7CegPioMA0GCSqGSIb3DQEBCwUABIIBAHsusZjovIuO1InG +# MxbciHmCGCVeoFGiSg7EGW55RVqx2YFsXzQ7DrnJsQvkYvf9IJ2a5oYPDfTdavOq +# w5+J6uhp8qy2CYUduQMBACdqgtdL1Oz8UJIuyhlVECGdoK28SpW5QJ4DJdqt9xf8 +# znTcTPxpt4+SPflVPesUfMTazD/TfgnIqBwoXb6c84YLcrBwjsoc4s7GhuCowR/0 +# ViO1IGvqwzS3wm/hQOkCsz755E94wSsSMoDeE4Vcckx75bTepGB8ZNNfBeoujpaf +# WOJuGQgpK7rCAAy3xRrGovVmWOIjTrTPNMtotJo1mA76ruMVYZq7DPx9oXoTL36t +# EbSybGg= +# SIG # End signature block |