Close

Breakdown command-line options

A project log for Source Code Analysis: PowerShellEditorServices

Source Code Breakdown of PowerShellEditorServices (at the time of v3.5.4)

nicholas-jacksonNicholas Jackson 10/14/2022 at 20:260 Comments

PROBLEM: VAGUE COMMAND LINE ARGUMENTS.

Start-EditorServices.ps1 has vague command line arguments

RESEARCH: Start-EditorServices.ps1

[CmdletBinding(DefaultParameterSetName="NamedPipe")]
param(
    [Parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [string]
    $HostName,

    [Parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [string]
    $HostProfileId,

    [Parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [string]
    $HostVersion,

    [ValidateNotNullOrEmpty()]
    [string]
    $BundledModulesPath,

    [ValidateNotNullOrEmpty()]
    $LogPath,

    [ValidateSet("Diagnostic", "Verbose", "Normal", "Warning", "Error")]
    $LogLevel,

    [Parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [string]
    $SessionDetailsPath,

    [switch]
    $EnableConsoleRepl,

    [switch]
    $UseLegacyReadLine,

    [switch]
    $DebugServiceOnly,

    [switch]
    $LanguageServiceOnly,

    [string[]]
    $AdditionalModules,

    [string[]]
    $FeatureFlags,

    [switch]
    $WaitForDebugger,

    [switch]
    $ConfirmInstall,

    [Parameter(ParameterSetName="Stdio", Mandatory=$true)]
    [switch]
    $Stdio,

    [Parameter(ParameterSetName="NamedPipe")]
    [string]
    $LanguageServicePipeName = $null,

    [Parameter(ParameterSetName="NamedPipe")]
    [string]
    $DebugServicePipeName = $null,

    [Parameter(ParameterSetName="NamedPipeSimplex")]
    [switch]
    $SplitInOutPipes,

    [Parameter(ParameterSetName="NamedPipeSimplex")]
    [string]
    $LanguageServiceInPipeName,

    [Parameter(ParameterSetName="NamedPipeSimplex")]
    [string]
    $LanguageServiceOutPipeName,

    [Parameter(ParameterSetName="NamedPipeSimplex")]
    [string]
    $DebugServiceInPipeName = $null,

    [Parameter(ParameterSetName="NamedPipeSimplex")]
    [string]
    $DebugServiceOutPipeName = $null
)

Import-Module -Name "$PSScriptRoot/PowerShellEditorServices.psd1"
Start-EditorServices @PSBoundParameters

This script is just a wrapper for the Start-EditorServices function in PowerShellEditorServices.psd1

RESEARCH: PowerShellEditorServices.psd1

This psd1 (hashtable as a manifest) with the following relevant keys:

# Script module or binary module file associated with this manifest.
RootModule = if ($PSEdition -eq 'Core')
    {
        'bin/Core/Microsoft.PowerShell.EditorServices.Hosting.dll'
    }
    else
    {
        'bin/Desktop/Microsoft.PowerShell.EditorServices.Hosting.dll'
    }

...

# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = @('Start-EditorServices')

I'm running core on my instance, so we will checkout cre

RESEARCH: core/Microsoft.PowerShell.EditorServices.Hosting.dll

I need to figure out how this module was built.

RESEARCH: PSES/PowerShellEditorServices.build.ps1

Code that publishes the output of the build:

    # PSES/bin/Core
    foreach ($hostComponent in Get-ChildItem $script:HostCoreOutput) {
        if (-not $includedDlls.Contains($hostComponent.Name)) {
            Copy-Item -Path $hostComponent.FullName -Destination $psesCoreHostPath -Force
        }
    }

 The directory with build output is stored at $script:HostCoreOutput

RESEARCH: $script:HostCoreOutput

Definition:

$script:HostCoreOutput = "$PSScriptRoot/src/PowerShellEditorServices.Hosting/bin/$Configuration/$($script:NetRuntime.PS7)/publish"

It is only used once. Maybe we can find more from $Configuration and NetRuntime.PS7?

This doesn't seem to turn up much

Maybe we can get some data from buildinfo?

RESEARCH:CreateBuildInfo

There are 2 variations of CreateBuildInfo:

Option A

Task Build FindDotNet, CreateBuildInfo, {
    # NOTE: We use /p:UseSharedCompilation=false to work around a bug with CodeQL.
    Exec { & dotnet restore $VerbosityArgs }
    Exec { & dotnet publish /p:UseSharedCompilation=false $VerbosityArgs -c $Configuration .\src\PowerShellEditorServices\PowerShellEditorServices.csproj -f $script:NetRuntime.Standard }
    Exec { & dotnet publish /p:UseSharedCompilation=false $VerbosityArgs -c $Configuration .\src\PowerShellEditorServices.Hosting\PowerShellEditorServices.Hosting.csproj -f $script:NetRuntime.PS7 }
    if (-not $script:IsNix) {
        Exec { & dotnet publish /p:UseSharedCompilation=false $VerbosityArgs -c $Configuration .\src\PowerShellEditorServices.Hosting\PowerShellEditorServices.Hosting.csproj -f $script:NetRuntime.Desktop }
    }

    # Build PowerShellEditorServices.VSCode module
    Exec { & dotnet publish /p:UseSharedCompilation=false $VerbosityArgs -c $Configuration .\src\PowerShellEditorServices.VSCode\PowerShellEditorServices.VSCode.csproj -f $script:NetRuntime.Standard }
}

This reveals that there is build information in these files:

It calls the last one twice, once for core, and once for windows

Option B

Task CreateBuildInfo {
    $buildVersion = "<development-build>"
    $buildOrigin = "Development"
    $buildCommit = git rev-parse HEAD

    # Set build info fields on build platforms
    if ($env:TF_BUILD) {
        if ($env:BUILD_BUILDNUMBER -like "PR-*") {
            $buildOrigin = "PR"
        } elseif ($env:BUILD_DEFINITIONNAME -like "*-CI") {
            $buildOrigin = "CI"
        } else {
            $buildOrigin = "Release"
        }

        $propsXml = [xml](Get-Content -Raw -LiteralPath "$PSScriptRoot/PowerShellEditorServices.Common.props")
        $propsBody = $propsXml.Project.PropertyGroup
        $buildVersion = $propsBody.VersionPrefix

        if ($propsBody.VersionSuffix) {
            $buildVersion += '-' + $propsBody.VersionSuffix
        }
    }

    # Allow override of build info fields (except date)
    if ($env:PSES_BUILD_VERSION) {
        $buildVersion = $env:PSES_BUILD_VERSION
    }

    if ($env:PSES_BUILD_ORIGIN) {
        $buildOrigin = $env:PSES_BUILD_ORIGIN
    }

    [string]$buildTime = [datetime]::Today.ToString("s", [System.Globalization.CultureInfo]::InvariantCulture)

    $buildInfoContents = @"
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Globalization;
namespace Microsoft.PowerShell.EditorServices.Hosting
{
    public static class BuildInfo
    {
        public static readonly string BuildVersion = "$buildVersion";
        public static readonly string BuildOrigin = "$buildOrigin";
        public static readonly string BuildCommit = "$buildCommit";
        public static readonly System.DateTime? BuildTime = System.DateTime.Parse("$buildTime", CultureInfo.InvariantCulture.DateTimeFormat);
    }
}
"@

    if (Compare-Object $buildInfoContents.Split([Environment]::NewLine) (Get-Content $script:BuildInfoPath)) {
        Write-Host "Updating build info."
        Set-Content -LiteralPath $script:BuildInfoPath -Value $buildInfoContents -Force
    }
}

This reveals that there is data within .\PowerShellEditorServices.Common.props

This also suggests that whatever is in $script:BuildInfoPath contains more build info

RESEARCH: $script:BuildInfoPath

It is resolved on this line:

$script:BuildInfoPath = [System.IO.Path]::Combine($PSScriptRoot, "src", "PowerShellEditorServices.Hosting", "BuildInfo.cs")

Which should resolve to .\src\PowerShellEditorServices.Hosting\BuildInfo.cs

RESEARCH: BuildInfo.cs

This appears to just be a cs file that packs the build number into the published app

RESEARCH: PowerShellEditorServices.Common.props

This appears to just be some kind of .NET manifest

RESEARCH: PowerShellEditorServices.csproj + PowerShellEditorServices.Hosting.csproj

Neither of these 2 provide anything super revealing. So maybe the builder just compiles everything in their parent directories?

Discussions