Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run-ALCops (6.0.19-preview1213) stops working with missing file in BC24, BC23 works #3575

Open
MODUSCarstenScholling opened this issue Jun 12, 2024 · 22 comments

Comments

@MODUSCarstenScholling
Copy link
Contributor

MODUSCarstenScholling commented Jun 12, 2024

Hi Freddy, it's me again :)

Describe the issue
Run-ALCops (6.0.19-preview1213) stops working with missing file in BC24, BC23 works.

When running Run-ALCops on BC24 (tested .1 and .2) on Windows PS or on PowerShell 7.4.2, reading of the authenticode signature fails for the second or third app. When debugging, the behavior might be different and might work.

I can provide our apps per PM if needed.

Updated Run-ALCops.ps1 with debugging

<#
 .Synopsis
  Run AL Cops
 .Description
  Run AL Cops
 .Parameter containerName
  Name of the validation container. Default is bcserver.
 .Parameter credential
  These are the credentials used for the container. If not provided, the Run-AlValidation function will generate a random password and use that.
 .Parameter previousApps
  Array or comma separated list of previous version of apps to use for AppSourceCop validation and upgrade test
 .Parameter apps
  Array or comma separated list of apps to validate
 .Parameter affixes
  Array or comma separated list of affixes to use for AppSourceCop validation
 .Parameter supportedCountries
  Array or comma separated list of supportedCountries to use for AppSourceCop validation
 .Parameter obsoleteTagMinAllowedMajorMinor
  Objects that are pending obsoletion with an obsolete tag version lower than the minimum set in the AppSourceCop.json file are not allowed. (AS0105)
 .Parameter appPackagesFolder
  Folder in which symbols and apps will be cached. The folder must be shared with the container.
 .Parameter enableAppSourceCop
  Include this switch to enable AppSource Cop
 .Parameter enableCodeCop
  Include this switch to enable Code Cop
 .Parameter enableUICop
  Include this switch to enable UI Cop
 .Parameter enablePerTenantExtensionCop
  Include this switch to enable Per Tenant Extension Cop
 .Parameter failOnError
  Include this switch if you want to fail on the first error instead of returning all errors to the caller
 .Parameter ignoreWarnings
  Include this switch if you want to ignore Warnings
 .Parameter doNotIgnoreInfos
  Include this switch if you don't want to ignore Infos
 .Parameter rulesetFile
  Filename of the ruleset file for Compile-AppInBcContainer
 .Parameter skipVerification
  Include this parameter to skip verification of code signing certificate. Note that you cannot request Microsoft to set this parameter when validating for AppSource.
 .Parameter reportSuppressedDiagnostics
  Set reportSuppressedDiagnostics flag on ALC when compiling to ignore pragma warning disables
 .Parameter CompileAppInBcContainer
  Override function parameter for Compile-AppInBcContainer
#>
function Run-AlCops {
    Param(
        $containerName = $bcContainerHelperConfig.defaultContainerName,
        [PSCredential] $credential,
        $previousApps,
        $apps,
        $affixes,
        $supportedCountries,
        [string] $obsoleteTagMinAllowedMajorMinor = "",
        $appPackagesFolder = (Join-Path $bcContainerHelperConfig.hostHelperFolder ([Guid]::NewGuid().ToString())),
        [switch] $enableAppSourceCop,
        [switch] $enableCodeCop,
        [switch] $enableUICop,
        [switch] $enablePerTenantExtensionCop,
        [switch] $failOnError,
        [switch] $ignoreWarnings,
        [switch] $doNotIgnoreInfos,
        [switch] $reportsuppresseddiagnostics = $true,
        [switch] $skipVerification,
        [string] $rulesetFile = "",
        [scriptblock] $CompileAppInBcContainer
    )

    $telemetryScope = InitTelemetryScope -name $MyInvocation.InvocationName -parameterValues $PSBoundParameters -includeParameters @()
    try {

        if ($previousApps -is [String]) { $previousApps = @($previousApps.Split(',').Trim() | Where-Object { $_ }) }
        if ($apps -is [String]) { $apps = @($apps.Split(',').Trim()  | Where-Object { $_ }) }
        if ($affixes -is [String]) { $affixes = @($affixes.Split(',').Trim() | Where-Object { $_ }) }
        if ($supportedCountries -is [String]) { $supportedCountries = @($supportedCountries.Split(',').Trim() | Where-Object { $_ }) }
        $supportedCountries = $supportedCountries | Where-Object { $_ } | ForEach-Object { getCountryCode -countryCode $_ }

        if ($CompileAppInBcContainer) {
            Write-Host -ForegroundColor Yellow "CompileAppInBcContainer override"; Write-Host $CompileAppInBcContainer.ToString()
        }
        else {
            $CompileAppInBcContainer = { Param([Hashtable]$parameters) Compile-AppInBcContainer @parameters }
        }

        if ($enableAppSourceCop -and $enablePerTenantExtensionCop) {
            throw "You cannot run AppSourceCop and PerTenantExtensionCop at the same time"
        }

        $appsFolder = Join-Path $bcContainerHelperConfig.hostHelperFolder ([Guid]::NewGuid().ToString())
        New-Item -Path $appsFolder -ItemType Directory | Out-Null
        $apps = Sort-AppFilesByDependencies -containerName $containerName -appFiles @(CopyAppFilesToFolder -appFiles $apps -folder $appsFolder) -WarningAction SilentlyContinue

        $appPackFolderCreated = $false
        if (!(Test-Path $appPackagesFolder)) {
            New-Item -Path $appPackagesFolder -ItemType Directory | Out-Null
            $appPackFolderCreated = $true
        }

        $previousAppVersions = @{}
        if ($enableAppSourceCop -and $previousApps) {
            Write-Host "Copying previous apps to packages folder"
            $appList = CopyAppFilesToFolder -appFiles $previousApps -folder $appPackagesFolder
            $previousApps = Sort-AppFilesByDependencies -containerName $containerName -appFiles $appList -WarningAction SilentlyContinue
            $previousApps | ForEach-Object {
                $appFile = $_
                $tmpFolder = Join-Path ([System.IO.Path]::GetTempPath()) ([Guid]::NewGuid().ToString())
                try {
                    Extract-AppFileToFolder -appFilename $appFile -appFolder $tmpFolder -generateAppJson
                    $xappJsonFile = Join-Path $tmpFolder "app.json"
                    $xappJson = [System.IO.File]::ReadAllLines($xappJsonFile) | ConvertFrom-Json
                    Write-Host "$($xappJson.Publisher)_$($xappJson.Name) = $($xappJson.Version)"
                    $previousAppVersions += @{ "$($xappJson.Publisher)_$($xappJson.Name)" = $xappJson.Version }
                }
                catch {
                    throw "Cannot use previous app $([System.IO.Path]::GetFileName($appFile)), it might be a runtime package."
                }
                finally {
                    if (Test-Path $tmpFolder) {
                        Remove-Item $tmpFolder -Recurse -Force
                    }
                }
            }
        }

        $artifactUrl = Get-BcContainerArtifactUrl -containerName $containerName
        $artifactVersion = [System.Version]$artifactUrl.Split('/')[4]
        $latestSupportedRuntimeVersion = RunAlTool -arguments @('GetLatestSupportedRuntimeVersion',"$($artifactVersion.Major).$($artifactVersion.Minor)")
        Write-Host "Latest Supported Runtime Version: $latestSupportedRuntimeVersion"

        $global:_validationResult = @()
        $apps | ForEach-Object {
            $appFile = $_
            $appFileName = [System.IO.Path]::GetFileName($appFile)
            Write-Host "STEP 01: WORKING ON -$($appFile)-";
            $tmpFolder = Join-Path $bcContainerHelperConfig.hostHelperFolder ([Guid]::NewGuid().ToString())
            Write-Host "STEP 02: tmpFolder -$($tmpFolder)-";
            try {
                $length = $global:_validationResult.Length
                if (!$skipVerification) {
                    Write-Host "STEP 03: COPY ITEM FROM -$($appFile)- TO -$tmpFolder.app-";
                    Copy-Item -path $appFile -Destination "$tmpFolder.app"
                    Write-Host "STEP 03.1 EXISTS: -$tmpFolder.app- $(Test-Path -Path "$tmpFolder.app")";
                    Write-Host "STEP 03.2 EXISTS LEAF: -$tmpFolder.app- $(Test-Path -Path "$tmpFolder.app" -PathType Leaf)";
                    Write-Host "STEP 04: SIGNING -$((Get-BcContainerPath -containerName $containerName -path "$tmpFolder.app"))-";
                    $signResult = Invoke-ScriptInBcContainer -containerName $containerName -scriptBlock { Param($appTmpFile)
                        Write-Host "STEP 04.1: appTmpFile = -$($appTmpFile)-";
                        if (!(Test-Path "C:\Windows\System32\vcruntime140_1.dll")) {
                            Write-Host "Downloading vcredist_x64 (version 140)"
                            (New-Object System.Net.WebClient).DownloadFile('https://aka.ms/vs/17/release/vc_redist.x64.exe', 'c:\run\install\vcredist_x64-140.exe')
                            Write-Host "Installing vcredist_x64 (version 140)"
                            start-process -Wait -FilePath c:\run\install\vcredist_x64-140.exe -ArgumentList /q, /norestart
                        }
                        Write-Host "STEP 04.2: appTmpFile = -$($appTmpFile)- => EXISTS: $(Test-Path -Path $appTmpFile)";
                        Write-Host "STEP 04.3: appTmpFile = -$($appTmpFile)- => EXISTS LEAF $(Test-Path -Path $appTmpFile -PathType Leaf)";
                        Get-AuthenticodeSignature -FilePath $appTmpFile
                        Write-Host "STEP 04.4: appTmpFile = -$($appTmpFile)-";
                    } -argumentList (Get-BcContainerPath -containerName $containerName -path "$tmpFolder.app")
                    Write-Host "STEP 05: REMOVE ITEM -$tmpFolder.app-";
                    Remove-Item "$tmpFolder.app" -Force
                    Write-Host "STEP 06: REMOVED ITEM -$tmpFolder.app-";

                    if ($signResult.Status.Value -eq "valid") {
                        Write-Host -ForegroundColor Green "$appFileName is Signed with $($signResult.SignatureType.Value) certificate: $($signResult.SignerCertificate.Subject)"
                    }
                    else {
                        Write-Host -ForegroundColor Red "$appFileName is not signed, result is $($signResult.Status.Value)"
                        $global:_validationResult += @("$appFileName is not signed, result is $($signResult.Status.Value)")
                    }
                }

                Write-Host "STEP 06: EXTRACT-APPFILETOFOLDER FROM -$($appFile)- TO -$($tmpFolder)-";
                Extract-AppFileToFolder -appFilename $appFile -appFolder $tmpFolder -generateAppJson -latestSupportedRuntimeVersion $latestSupportedRuntimeVersion
                $appJson = [System.IO.File]::ReadAllLines((Join-Path $tmpFolder "app.json")) | ConvertFrom-Json

                $ruleset = $null

                if ("$rulesetFile" -ne "" -or $enableAppSourceCop) {
                    $ruleset = [ordered]@{
                        "name"             = "Run-AlCops RuleSet"
                        "description"      = "Generated by Run-AlCops"
                        "includedRuleSets" = @()
                    }
                }

                if ($rulesetFile) {
                    $customRulesetFile = Join-Path $tmpFolder "custom.ruleset.json"
                    Copy-Item -Path $rulesetFile -Destination $customRulesetFile
                    $ruleset.includedRuleSets += @(@{
                            "action" = "Default"
                            "path"   = Get-BcContainerPath -containerName $containerName -path $customRulesetFile
                        })
                }

                if ($enableAppSourceCop) {
                    Write-Host "Analyzing: $appFileName"
                    Write-Host "Using affixes: $([string]::Join(',',$affixes))"
                    $appSourceCopJson = @{
                        "mandatoryAffixes" = @($affixes)
                    }
                    if ($obsoleteTagMinAllowedMajorMinor) {
                        $appSourceCopJson += @{
                            "ObsoleteTagMinAllowedMajorMinor" = $obsoleteTagMinAllowedMajorMinor
                        }
                    }
                    if ($supportedCountries) {
                        Write-Host "Using supportedCountries: $([string]::Join(',',$supportedCountries))"
                        $appSourceCopJson += @{
                            "supportedCountries" = @($supportedCountries)
                        }
                    }
                    if ($previousAppVersions.ContainsKey("$($appJson.Publisher)_$($appJson.Name)")) {
                        $previousVersion = $previousAppVersions."$($appJson.Publisher)_$($appJson.Name)"
                        if ($previousVersion -ne $appJson.Version) {
                            $appSourceCopJson += @{
                                "Publisher" = $appJson.Publisher
                                "Name"      = $appJson.Name
                                "Version"   = $previousVersion
                            }
                            Write-Host "Using previous app: $($appJson.Publisher)_$($appJson.Name)_$previousVersion.app"
                        }
                    }
                    $appSourceCopJson | ConvertTo-Json -Depth 99 | Set-Content (Join-Path $tmpFolder "appSourceCop.json") -Encoding UTF8

                    $appSourceRulesetFile = Join-Path $tmpFolder "appsource.default.ruleset.json"
                    Download-File -sourceUrl "https://bcartifacts-exdbf9fwegejdqak.b02.azurefd.net/rulesets/appsource.default.ruleset.json" -destinationFile $appSourceRulesetFile
                    $ruleset.includedRuleSets += @(@{
                            "action" = "Default"
                            "path"   = Get-BcContainerPath -containerName $containerName -path $appSourceRulesetFile
                        })

                    Write-Host "AppSourceCop.json content:"
                    [System.IO.File]::ReadAllLines((Join-Path $tmpFolder "appSourceCop.json")) | Out-Host
                }
                Write-Host "STEP 07: REMOVE-ITEM -$((Join-Path $tmpFolder '*.xml'))";
                Remove-Item -Path (Join-Path $tmpFolder '*.xml') -Force

                $Parameters = @{
                    "containerName"               = $containerName
                    "credential"                  = $credential
                    "appProjectFolder"            = $tmpFolder
                    "appOutputFolder"             = $tmpFolder
                    "appSymbolsFolder"            = $appPackagesFolder
                    "CopySymbolsFromContainer"    = $true
                    "GenerateReportLayout"        = "No"
                    "EnableAppSourceCop"          = $enableAppSourceCop
                    "EnableUICop"                 = $enableUICop
                    "EnableCodeCop"               = $enableCodeCop
                    "EnablePerTenantExtensionCop" = $enablePerTenantExtensionCop
                    "Reportsuppresseddiagnostics" = $reportsuppresseddiagnostics
                    "outputTo"                    = { Param($line)
                        Write-Host $line
                        if ($line -like "error *" -or $line -like "warning *") {
                            $global:_validationResult += $line
                        }
                        elseif ($line -like "$($tmpFolder)*") {
                            $global:_validationResult += $line.SubString($tmpFolder.Length + 1)
                        }
                    }
                }
                if (!$failOnError) {
                    $Parameters += @{ "ErrorAction" = "SilentlyContinue" }
                }

                if ($ruleset) {
                    $myRulesetFile = Join-Path $tmpFolder "ruleset.json"
                    $ruleset | ConvertTo-Json -Depth 99 | Set-Content $myRulesetFile -Encoding UTF8
                    $Parameters += @{
                        "ruleset" = $myRulesetFile
                    }
                    Write-Host "Ruleset.json content:"
                    [System.IO.File]::ReadAllLines($myRulesetFile) | Out-Host
                }

                try {
                    Write-Host "STEP 08: INVOKE COMPILER";
                    Invoke-Command -ScriptBlock $CompileAppInBcContainer -ArgumentList ($Parameters) | Out-Null
                    Write-Host "STEP 09: END INVOKE COMPILER";
                }
                catch {
                    Write-Host "ERROR $($_.Exception.Message)"
                    $global:_validationResult += $_.Exception.Message
                }

                if ($ignoreWarnings) {
                    Write-Host "Ignoring warnings"
                    $global:_validationResult = @($global:_validationResult | Where-Object { $_ -notlike "*: warning *" -and $_ -notlike "warning *" })
                }
                if (!$doNotIgnoreInfos) {
                    Write-Host "Ignoring infos"
                    $global:_validationResult = @($global:_validationResult | Where-Object { $_ -notlike "*: info *" -and $_ -notlike "info *" })
                }

                Write-Host "STEP 10: AFTER IGNORE STUFF";

                $lines = $global:_validationResult.Length - $length
                if ($lines -gt 0) {
                    $i = 0
                    $global:_validationResult = $global:_validationResult | ForEach-Object {
                        if ($i++ -eq $length) {
                            "$lines $(if ($ignoreWarnings) { "errors" } else { "errors/warnings"}) found in $([System.IO.Path]::GetFileName($appFile)) on $($artifactUrl.Split('?')[0]):"
                        }
                        $_
                    }
                    $global:_validationResult += ""
                }
                Write-Host "STEP 11: COPY IN CONTAINER FROM -$((Get-BcContainerPath -containerName $containerName -path $appFile))- TO -$((Get-BcContainerPath -containerName $containerName -path $appPackagesFolder))-";
                Invoke-ScriptInBcContainer -containerName $containerName -scriptblock { Param($appFile, $appPackagesFolder)
                    # Copy inside container to ensure files are ready
                    Write-Host "Copy $appFile to $appPackagesFolder"
                    Copy-Item -Path $appFile -Destination $appPackagesFolder -Force
                    Write-Host "STEP 11.1: AFTER COPY -$($appFile) TO -$($appPackagesFolder)-";
                } -argumentList (Get-BcContainerPath -containerName $containerName -path $appFile), (Get-BcContainerPath -containerName $containerName -path $appPackagesFolder) | Out-Null
                Write-Host "STEP 12: AFTER COPY IN CONTAINER FROM -$((Get-BcContainerPath -containerName $containerName -path $appFile))- TO -$((Get-BcContainerPath -containerName $containerName -path $appPackagesFolder))-";
            }
            finally {
                Write-Host "STEP 13: FINALLY 01 -$tmpFolder.app-";
                if (Test-Path "$tmpFolder.app") {
                    Remove-Item -Path "$tmpFolder.app" -Force
                }
                Write-Host "STEP 14: FINALLY 02 -$tmpFolder-";
                if (Test-Path $tmpFolder) {
                    Remove-Item -Path $tmpFolder -Recurse -Force
                }
                Write-Host "STEP 15: FINALLY 03";
            }
        }
        Write-Host "STEP 16: REMOVE-ITEM -$($appPackagesFolder)-";
        if ($appPackFolderCreated) {
            Remove-Item $appPackagesFolder -Recurse -Force
        }
        Write-Host "STEP 17: REMOVE-ITEM -$($appsFolder)-";
        Remove-Item $appsFolder -Recurse -Force
        Write-Host "STEP 18: BEFORE CLEAR";

        $global:_validationResult
        Clear-Variable -Scope global -Name "_validationResult"
    }
    catch {
        Write-Host "STEP 18: FUNNY EXCEPTION -$($_)-";
        TrackException -telemetryScope $telemetryScope -errorRecord $_
        throw
    }
    finally {
        TrackTrace -telemetryScope $telemetryScope
    }
}
Export-ModuleMember -Function Run-AlCops

Script to get the error with BC24.1 (BC23.4 works), Remove-BCContainer has been commented out

Import-Module -Name 'BCContainerHelper' -Scope Local;

$scriptRoot = $PSScriptRoot;
$containerCredential = (New-Object System.Management.Automation.PSCredential -argumentList 'admin', (ConvertTo-SecureString -String "modus" -AsPlainText -Force));

$appsPath = "C:\Temp\RunAlCops";
$appNames = Get-ChildItem -Path $appsPath -Filter '*.app' | Select-Object -ExpandProperty 'FullName';

$artifactUrl = Get-BCArtifactUrl -type OnPrem -country 'de' -version '23.4' -select Latest -accept_insiderEula;
$containerName = 'RunAlCops234';

Start-Transcript -Path (Join-Path -Path $scriptRoot -ChildPath "$($containerName).txt") -Force;

if (!(Get-BcContainers | Where-Object { $_ -ieq $containerName }))
{
    New-BcContainer `
	    -accept_eula `
	    -accept_insiderEULA `
	    -accept_outdated `
	    -assignPremiumPlan `
        -isolation hyperv `
	    -containerName $containerName `
	    -artifactUrl $artifactUrl `
	    -enableTaskScheduler:$false `
	    -includeTestToolkit `
	    -includePerformanceToolkit `
	    -includeTestLibrariesOnly `
	    -auth NavUserPassword `
	    -Credential $containerCredential `
	    -updateHosts `
	    -shortcuts None `
	    -Verbose;
}

$alcOutput = Run-AlCops `
	-containerName $containerName `
	-credential $containerCredential `
	-apps $appNames `
    -Verbose;

#Remove-BcContainer -containerName $containerName;
Stop-Transcript;

$artifactUrl = Get-BCArtifactUrl -type OnPrem -country 'de' -version '24.1' -select Latest -accept_insiderEula;
$containerName = 'RunAlCops241';

Start-Transcript -Path (Join-Path -Path $scriptRoot -ChildPath "$($containerName).txt") -Force;

if (!(Get-BcContainers | Where-Object { $_ -ieq $containerName }))
{
    New-BcContainer `
	    -accept_eula `
	    -accept_insiderEULA `
	    -accept_outdated `
	    -assignPremiumPlan `
        -isolation hyperv `
	    -containerName $containerName `
	    -artifactUrl $artifactUrl `
	    -enableTaskScheduler:$false `
	    -includeTestToolkit `
	    -includePerformanceToolkit `
	    -includeTestLibrariesOnly `
	    -auth NavUserPassword `
	    -Credential $containerCredential `
	    -updateHosts `
	    -shortcuts None `
	    -Verbose;
}

$alcOutput = Run-AlCops `
	-containerName $containerName `
	-credential $containerCredential `
	-apps $appNames `
    -Verbose;

#Remove-BcContainer -containerName $containerName;
Stop-Transcript;

Full output of script RunAlCops234

[RunAlCops234.txt](https://github.com/user-attachments/files/15803154/RunAlCops234.txt)

Full output of script RunAlCops241

[RunAlCops241.txt](https://github.com/user-attachments/files/15803163/RunAlCops241.txt)

Additional context
If the error occurs, the file exists before Invoke-ScriptInBcContainer but not in the container/scriptblock. Get-AuthenticodeSignature fails with file not found.

                    Write-Host "STEP 03.1 EXISTS: -$tmpFolder.app- $(Test-Path -Path "$tmpFolder.app")";
                    Write-Host "STEP 03.2 EXISTS LEAF: -$tmpFolder.app- $(Test-Path -Path "$tmpFolder.app" -PathType Leaf)";
                    Write-Host "STEP 04: SIGNING -$((Get-BcContainerPath -containerName $containerName -path "$tmpFolder.app"))-";
                    $signResult = Invoke-ScriptInBcContainer -containerName $containerName -scriptBlock { Param($appTmpFile)
                        Write-Host "STEP 04.1: appTmpFile = -$($appTmpFile)-";
                        if (!(Test-Path "C:\Windows\System32\vcruntime140_1.dll")) {
                            Write-Host "Downloading vcredist_x64 (version 140)"
                            (New-Object System.Net.WebClient).DownloadFile('https://aka.ms/vs/17/release/vc_redist.x64.exe', 'c:\run\install\vcredist_x64-140.exe')
                            Write-Host "Installing vcredist_x64 (version 140)"
                            start-process -Wait -FilePath c:\run\install\vcredist_x64-140.exe -ArgumentList /q, /norestart
                        }
                        Write-Host "STEP 04.2: appTmpFile = -$($appTmpFile)- => EXISTS: $(Test-Path -Path $appTmpFile)";
                        Write-Host "STEP 04.3: appTmpFile = -$($appTmpFile)- => EXISTS LEAF $(Test-Path -Path $appTmpFile -PathType Leaf)";
                        Get-AuthenticodeSignature -FilePath $appTmpFile
                        Write-Host "STEP 04.4: appTmpFile = -$($appTmpFile)-";
                    } -argumentList (Get-BcContainerPath -containerName $containerName -path "$tmpFolder.app")
@freddydk
Copy link
Contributor

freddydk commented Jun 18, 2024

Could you try to insert these lines inside the Invoke-ScriptInBcContainer

# Wait for file to be accessible in container
While (-not (Test-Path $appTmpFile)) { Start-Sleep -Milliseconds 100 }

I have seen cases before, where a copied file isn't available immediately inside the container in either process or hyperv isolation (cannot remember which one)

@MODUSCarstenScholling
Copy link
Contributor Author

Well, of course. I've added the following

Write-Host "STEP 04.3: appTmpFile = -$($appTmpFile)- => EXISTS LEAF $(Test-Path -Path $appTmpFile -PathType Leaf)";
# Wait for file to be accessible in container
Write-Host "WAITED $((Measure-Command { while (!(Test-Path -Path $appTmpFile)) { Start-Sleep -Milliseconds 100 } }).TotalSeconds) SECONDS FOR FILE";
Write-Host "STEP 04.4: appTmpFile = -$($appTmpFile)- => EXISTS: $(Test-Path -Path $appTmpFile)";

And then I stored 12 files to process. This is the output:

  • INFO: WAITED 0.0037195 SECONDS FOR FILE
  • INFO: WAITED 3.1219697 SECONDS FOR FILE
  • INFO: WAITED 0.0264307 SECONDS FOR FILE
  • INFO: WAITED 5.5106264 SECONDS FOR FILE
  • INFO: WAITED 6.5841231 SECONDS FOR FILE
  • INFO: WAITED 4.4081718 SECONDS FOR FILE
  • INFO: WAITED 5.623214 SECONDS FOR FILE
  • INFO: WAITED 6.0379315 SECONDS FOR FILE
  • INFO: WAITED 6.9189453 SECONDS FOR FILE
  • INFO: WAITED 5.9311317 SECONDS FOR FILE
  • INFO: WAITED 5.6254099 SECONDS FOR FILE
  • INFO: WAITED 15.6128092 SECONDS FOR FILE

This is a delay of more than a minute in the process, an average of 5+ seconds per file. This is far to much. And it only applies to BC24 containers.

@MODUSCarstenScholling
Copy link
Contributor Author

MODUSCarstenScholling commented Jun 18, 2024

And an example of the original process with 12 apps on BC 25 using PS Core (above was Windows PS and BC 24):

First example output:

WAITED 0.0038076 SECONDS FOR FILE
MODUS Consult GmbH_MODUS M365 Foundation_23.3.24050801.24050801_app.app is Signed with Authenticode certificate: CN=MODUS Consult GmbH, O=MODUS Consult GmbH, L=Gütersloh, S=Nordrhein-Westfalen, C=DE
Extracting C:\ProgramData\BcContainerHelper\f7451a9b-3e22-4c2e-98ea-904635f7aef5\MODUS Consult GmbH_MODUS M365 Foundation_23.3.24050801.24050801_app.app

Times:

  • WAITED 0.0038076 SECONDS FOR FILE (365 KB)
  • WAITED 19.7782849 SECONDS FOR FILE (1021 KB)
  • WAITED 19.4347078 SECONDS FOR FILE (330 KB)
  • WAITED 19.6509246 SECONDS FOR FILE (990 KB)
  • WAITED 2.8118299 SECONDS FOR FILE (224 KB)
  • WAITED 19.7704506 SECONDS FOR FILE (1796 KB)
  • WAITED 19.3838229 SECONDS FOR FILE (103 KB)
  • WAITED 19.8164667 SECONDS FOR FILE (65 KB)
  • WAITED 2.3692748 SECONDS FOR FILE (74 KB)
  • WAITED 19.8973919 SECONDS FOR FILE (76 KB)
  • WAITED 19.8838192 SECONDS FOR FILE (45 KB)
  • WAITED 19.7951512 SECONDS FOR FILE (335 KB)

3 minutes waiting time. Not acceptable...

UPDATE: The times do not correspond to the size of the app files (added above). The sizes are different. Interesting is, that the 2.x second entries apply to our editor app and it's test app. But the latter is 3 times smaller than the editor itself.

@freddydk
Copy link
Contributor

3 minutes waiting time. Not acceptable...

Tell that to docker :-)

Obviously, we can find a different way to copy the file into the container - but files should really be available for docker when they are copied to a share. Maybe antivirus is playing a role here? or process/hyperv?

@MODUSCarstenScholling
Copy link
Contributor Author

3 minutes waiting time. Not acceptable...

Tell that to docker :-)

Really? What does docker differently between BC 23 and BC 24+?
I can't imagine what I should tell them, because the behavior changes with a different BC version.

@freddydk
Copy link
Contributor

BC24 runs PowerShell 7 inside the container - BC23 runs PowerShell 5.1

You can set $bcContainerHelperConfig.usePwshForBC24 = $false to see if this changes things.

I assume that it has something to do with that - but again, I copy the file to a share, then I run a script in the container, which cannot see the file - it likely isn't because the file is version 24 - it likely is because of PowerShell 7 in docker - but we have a similar waiting for a file inside the Compile-AppInBcContainer, so this is something we have seen before.

@MODUSCarstenScholling
Copy link
Contributor Author

Ok, thanks. I am now again using PS5 with $bcContainerHelperConfig.usePwshForBC24 = $false.
But that doesn't really feel good...

I'm not that experienced with all that docker stuff and sessions. But what I find strange is that the app files are copied directly into the host helper folder (root) as guid.app. Was that the original intention?

@freddydk
Copy link
Contributor

Reason is that this folder is shared with the container in order to check the signature inside the container.
You can also add -skipVerification to skip the validation of the certificate.

@freddydk
Copy link
Contributor

There has been a ton of problems after the PS7 stuff - needless to say that I didn't like that change.
If you can test Hyperv / Process to see whether that makes a difference?

@MODUSCarstenScholling
Copy link
Contributor Author

Reason is that this folder is shared with the container in order to check the signature inside the container. You can also add -skipVerification to skip the validation of the certificate.

Yes, I know. The question was >why are the apps copied directly to "C:\ProgramData\BCContainerHelper\guid.app" instead of copying them to a subfolder.<

@MODUSCarstenScholling
Copy link
Contributor Author

There has been a ton of problems after the PS7 stuff - needless to say that I didn't like that change. If you can test Hyperv / Process to see whether that makes a difference?

I will try that in the next days. But I cannot promise, because I had a lot of issues with process in the past. usePwSh btw. reduces the wairing time to 0 (or 0.004 seconds).

@freddydk
Copy link
Contributor

What OS are you running on the host?

@MODUSCarstenScholling
Copy link
Contributor Author

Windows Server 2019 and Windows 11. First is an Agent, second my Personal Maschine.

@freddydk
Copy link
Contributor

And I assume it fails on both?
Haven't heard about this before - but will run some tests.

@freddydk
Copy link
Contributor

Tried this

$containerName = 'bc24'
1..10 | ForEach-Object {
    $destname = Join-Path $bcContainerHelperConfig.hostHelperFolder "$([guid]::NewGuid().ToString()).app"
    $out = new-object byte[] 104857600; (new-object Random).NextBytes($out)
    [IO.File]::WriteAllBytes($destname, $out)
    Invoke-ScriptInBcContainer -containerName $containerName -scriptblock { Param($tmpfile)
        Write-Host "WAITED $((Measure-Command { while (!(Test-Path -Path $tmpfile)) { Start-Sleep -Milliseconds 100 } }).TotalSeconds) SECONDS FOR FILE";
    } -argumentList (Get-BcContainerPath -containerName $containerName -path $destname)
    Remove-Item $destname -force
}

returns

WAITED 0.0042423 SECONDS FOR FILE
WAITED 0.0033039 SECONDS FOR FILE
WAITED 0.0031617 SECONDS FOR FILE
WAITED 0.0026307 SECONDS FOR FILE
WAITED 0.0026237 SECONDS FOR FILE
WAITED 0.0028021 SECONDS FOR FILE
WAITED 0.0028249 SECONDS FOR FILE
WAITED 0.0031805 SECONDS FOR FILE
WAITED 0.0025439 SECONDS FOR FILE
WAITED 0.0021396 SECONDS FOR FILE

Can you repro the problem with a script like this?

@MODUSCarstenScholling
Copy link
Contributor Author

MODUSCarstenScholling commented Jun 19, 2024

That is interesting: Still with isolation hyperv and $bcContainerHelperConfig.usePwshForBC24 = $true.
Documentation of all my steps below.

  • Run-AlCops with one app only
  • Directly afterwards your file loop
  • The one Run-AlCops loop is fast, the first file loop takes "long" while other subsequent loops run 0.004 seconds again
$lessAppNames = @($appNames | Where-Object { ($_ -imatch 'Foundation') });#-or ($_ -imatch 'M365 Base') 

$alcOutput = Run-AlCops `
	-containerName $containerName `
	-credential $containerCredential `
	-apps $lessAppNames `
    -Verbose;

1..10 | ForEach-Object {
    $destname = Join-Path $bcContainerHelperConfig.hostHelperFolder "$([guid]::NewGuid().ToString()).app"
    $out = new-object byte[] 104857600; (new-object Random).NextBytes($out)
    [IO.File]::WriteAllBytes($destname, $out)

    Invoke-ScriptInBcContainer -containerName $containerName -scriptblock { Param($tmpfile)
        Write-Host "WAITED $((Measure-Command { while (!(Test-Path -Path $tmpfile)) { Start-Sleep -Milliseconds 100 } }).TotalSeconds) SECONDS FOR FILE";
    } -argumentList (Get-BcContainerPath -containerName $containerName -path $destname)

    Remove-Item $destname -force
}
STEP 01: WORKING ON -C:\ProgramData\BcContainerHelper\afcc57a0-c5b4-42ed-b907-939b6eb874ec\MODUS Consult GmbH_MODUS M365 Foundation_23.3.24050801.24050801_app.app-
STEP 02: tmpFolder -C:\ProgramData\BcContainerHelper\95a8af8b-f4af-4e94-a6fa-ca90f42f658d-
STEP 03: COPY ITEM FROM -C:\ProgramData\BcContainerHelper\afcc57a0-c5b4-42ed-b907-939b6eb874ec\MODUS Consult GmbH_MODUS M365 Foundation_23.3.24050801.24050801_app.app- TO -C:\ProgramData\BcCo
ntainerHelper\95a8af8b-f4af-4e94-a6fa-ca90f42f658d.app-
STEP 04: appTmpFile = -C:\ProgramData\BcContainerHelper\95a8af8b-f4af-4e94-a6fa-ca90f42f658d.app-
WAITED 0.002528 SECONDS FOR FILE
STEP 05: appTmpFile = -C:\ProgramData\BcContainerHelper\95a8af8b-f4af-4e94-a6fa-ca90f42f658d.app-

[...]

WAITED 8.8769057 SECONDS FOR FILE
WAITED 0.0027965 SECONDS FOR FILE
WAITED 0.0029831 SECONDS FOR FILE
WAITED 0.0029563 SECONDS FOR FILE
WAITED 0.0030594 SECONDS FOR FILE
WAITED 0.0033464 SECONDS FOR FILE
WAITED 0.0038508 SECONDS FOR FILE
WAITED 0.0032709 SECONDS FOR FILE
WAITED 0.0034 SECONDS FOR FILE
WAITED 0.0034419 SECONDS FOR FILE
  • Changed config to $bcContainerHelperConfig.usePsSession = $false
  • Same script, no delay seen...
STEP 01: WORKING ON -C:\ProgramData\BcContainerHelper\afcc57a0-c5b4-42ed-b907-939b6eb874ec\MODUS Consult GmbH_MODUS M365 Foundation_23.3.24050801.24050801_app.app-
STEP 02: tmpFolder -C:\ProgramData\BcContainerHelper\95a8af8b-f4af-4e94-a6fa-ca90f42f658d-
STEP 03: COPY ITEM FROM -C:\ProgramData\BcContainerHelper\afcc57a0-c5b4-42ed-b907-939b6eb874ec\MODUS Consult GmbH_MODUS M365 Foundation_23.3.24050801.24050801_app.app- TO -C:\ProgramData\BcCo
ntainerHelper\95a8af8b-f4af-4e94-a6fa-ca90f42f658d.app-
STEP 04: appTmpFile = -C:\ProgramData\BcContainerHelper\95a8af8b-f4af-4e94-a6fa-ca90f42f658d.app-
WAITED 0.0036081 SECONDS FOR FILE
STEP 05: appTmpFile = -C:\ProgramData\BcContainerHelper\95a8af8b-f4af-4e94-a6fa-ca90f42f658d.app-

[...]

WAITED 0.0084212 SECONDS FOR FILE
WAITED 0.0040656 SECONDS FOR FILE
WAITED 0.0037297 SECONDS FOR FILE
WAITED 0.0035159 SECONDS FOR FILE
WAITED 0.0034539 SECONDS FOR FILE
WAITED 0.0035291 SECONDS FOR FILE
WAITED 0.0036596 SECONDS FOR FILE
WAITED 0.0042364 SECONDS FOR FILE
WAITED 0.0039691 SECONDS FOR FILE
WAITED 0.0038899 SECONDS FOR FILE
  • Changed config to $bcContainerHelperConfig.usePsSession = $true again, first call delay
[...]
WAITED 18.0983485 SECONDS FOR FILE
WAITED 0.0029389 SECONDS FOR FILE
[...]
  • Added -skipVerification to the Run-AlCops call, first call delay
[...]
WAITED 18.1324487 SECONDS FOR FILE
WAITED 0.0029733 SECONDS FOR FILE
[...]
  • Created simple no-repro/repro scenarios
    isolation = hyperv, $bcContainerHelperConfig.usePwshForBC24 = $true, $bcContainerHelperConfig.usePsSession = $true
  • If any of usePwshForBc24 or usePsSession is false, then I see no repro
Write-Host "NO REPRO";

1..3 | ForEach-Object {
    $destname = Join-Path $bcContainerHelperConfig.hostHelperFolder "$([guid]::NewGuid().ToString()).app"; $destname | Out-File -FilePath $destname -Force;

    Invoke-ScriptInBcContainer -containerName $containerName -scriptblock { Param($tmpfile)
        Write-Host "WAITED $((Measure-Command { while (!(Test-Path -Path $tmpfile)) { Start-Sleep -Milliseconds 100 } }).TotalSeconds) SECONDS FOR FILE";
        $content = Get-Content -Path $tmpfile; Write-Host "Content: $($content)";
    } -argumentList (Get-BcContainerPath -containerName $containerName -path $destname)

    Remove-Item -Path $destname -Force;
}

Write-Host "DOES REPRO";

1..3 | ForEach-Object {
    $destname = Join-Path $bcContainerHelperConfig.hostHelperFolder "$([guid]::NewGuid().ToString()).app"; $destname | Out-File -FilePath $destname -Force;

    Invoke-ScriptInBcContainer -containerName $containerName -scriptblock { Param($tmpfile)
        Write-Host "WAITED $((Measure-Command { while (!(Test-Path -Path $tmpfile)) { Start-Sleep -Milliseconds 100 } }).TotalSeconds) SECONDS FOR FILE";
        $content = Get-Content -Path $tmpfile; Write-Host "Content: $($content)";
        Remove-Item -Path $tmpfile -Force;
    } -argumentList (Get-BcContainerPath -containerName $containerName -path $destname)
}

Output:

NO REPRO
WAITED 0.0055049 SECONDS FOR FILE
Content: C:\ProgramData\BcContainerHelper\87a957fd-b1ea-4b2f-9d00-d1bb197fc59d.app
WAITED 0.003846 SECONDS FOR FILE
Content: C:\ProgramData\BcContainerHelper\c61ed63f-0cb2-49fe-bded-c7a53dd227dc.app
WAITED 0.0039088 SECONDS FOR FILE
Content: C:\ProgramData\BcContainerHelper\fd16492c-7fb7-47ce-ab4b-392632e843f6.app
DOES REPRO
WAITED 0.0038345 SECONDS FOR FILE
Content: C:\ProgramData\BcContainerHelper\bf2c3f30-d76b-435f-91fb-531c9cc7395b.app
WAITED 19.8329501 SECONDS FOR FILE
Content: C:\ProgramData\BcContainerHelper\139256ee-eea8-4805-a5e5-4a92b3f7f637.app
WAITED 19.5155982 SECONDS FOR FILE
Content: C:\ProgramData\BcContainerHelper\76d75c9d-2ed0-4996-8b86-f6dd3d761bef.app

THE FINALS

  • All important parts (run script, get session) have been covered in own implementations
  • Tested with hyperv and process isolation. Process isolation does NOT repro, hyperv does!
$containerName = 'RunAlCops241';
$Global:sessionCache = @{};

function MyInvokeInABox
{
    param
    (
        [string]$containerName,
        [scriptblock]$scriptblock,
        [object[]]$argumentList,
        [switch]$useSessionCache
    )

    if ($Global:sessionCache.ContainsKey($containerName) -and $useSessionCache.IsPresent)
    {
        $session = $Global:sessionCache[$containerName];
    }
    else
    {
        $containerId = (docker ps --format "{{.Names}}:{{.ID}}" -a --no-trunc | Where-Object { $_.StartsWith("$($containerName):") }).Split(':')[1];
        $session = New-PSSession -ContainerId $containerId -RunAsAdministrator -ConfigurationName 'PowerShell.7';

        if ($Global:sessionCache.ContainsKey($containerName))
        {
            $Global:sessionCache.Remove($containerName);
        }

        $Global:sessionCache += @{ $containerName = $session; };
    }

    Invoke-Command -Session $session -ScriptBlock $scriptblock -ArgumentList $argumentList;
}


Write-Host "NO REPRO (SESSION CACHE, NO FILE OPERATION INSIDE CONTAINER)";

1..3 | ForEach-Object {
    $destname = Join-Path $bcContainerHelperConfig.hostHelperFolder "$([guid]::NewGuid().ToString()).app"; $destname | Out-File -FilePath $destname -Force;

    MyInvokeInABox -containerName $containerName -useSessionCache -scriptblock { Param($tmpfile)
        Write-Host "WAITED $((Measure-Command { while (!(Test-Path -Path $tmpfile)) { Start-Sleep -Milliseconds 100 } }).TotalSeconds) SECONDS FOR FILE";
        $content = Get-Content -Path $tmpfile; Write-Host "Content: $($content)";
    } -argumentList (Get-BcContainerPath -containerName $containerName -path $destname);

    Remove-Item -Path $destname -Force;
}

Write-Host "AGAIN NO REPRO (NO SESSION CACHE, WITH FILE OPERATION INSIDE CONTAINER)";

1..3 | ForEach-Object {
    $destname = Join-Path $bcContainerHelperConfig.hostHelperFolder "$([guid]::NewGuid().ToString()).app"; $destname | Out-File -FilePath $destname -Force;

    MyInvokeInABox -containerName $containerName -scriptblock { Param($tmpfile)
        Write-Host "WAITED $((Measure-Command { while (!(Test-Path -Path $tmpfile)) { Start-Sleep -Milliseconds 100 } }).TotalSeconds) SECONDS FOR FILE";
        $content = Get-Content -Path $tmpfile; Write-Host "Content: $($content)";
        Remove-Item -Path $tmpfile -Force;
    } -argumentList (Get-BcContainerPath -containerName $containerName -path $destname);
}

Write-Host "DOES REPRO (WITH SESSION CACHE, WITH FILE OPERATION INSIDE CONTAINER)";

1..3 | ForEach-Object {
    $destname = Join-Path $bcContainerHelperConfig.hostHelperFolder "$([guid]::NewGuid().ToString()).app"; $destname | Out-File -FilePath $destname -Force;

    MyInvokeInABox -containerName $containerName -useSessionCache -scriptblock { Param($tmpfile)
        Write-Host "WAITED $((Measure-Command { while (!(Test-Path -Path $tmpfile)) { Start-Sleep -Milliseconds 100 } }).TotalSeconds) SECONDS FOR FILE";
        $content = Get-Content -Path $tmpfile; Write-Host "Content: $($content)";
        Remove-Item -Path $tmpfile -Force;
    } -argumentList (Get-BcContainerPath -containerName $containerName -path $destname);
}

RESULT with isolation = hyperv

NO REPRO (SESSION CACHE, NO FILE OPERATION INSIDE CONTAINER)
WAITED 0.051443 SECONDS FOR FILE
Content: C:\ProgramData\BcContainerHelper\870455ef-4ac1-43f0-8a61-d5eefa8acc81.app
WAITED 0.0041427 SECONDS FOR FILE
Content: C:\ProgramData\BcContainerHelper\b766999e-49f5-4cd1-bb8d-fd8fcfe2a5d8.app
WAITED 0.0039541 SECONDS FOR FILE
Content: C:\ProgramData\BcContainerHelper\033a75c3-a093-4d8d-a0ca-cf2a90e67378.app
AGAIN NO REPRO (NO SESSION CACHE, WITH FILE OPERATION INSIDE CONTAINER)
WAITED 0.0621944 SECONDS FOR FILE
Content: C:\ProgramData\BcContainerHelper\38975827-d569-45de-9cec-55b739506cfc.app
WAITED 0.0562523 SECONDS FOR FILE
Content: C:\ProgramData\BcContainerHelper\8b3130a3-806b-4167-b5fb-6f5b8fc6aa13.app
WAITED 0.0570544 SECONDS FOR FILE
Content: C:\ProgramData\BcContainerHelper\6edfdb72-d3d1-45d9-ac86-a81db62fd90f.app
DOES REPRO (WITH SESSION CACHE, WITH FILE OPERATION INSIDE CONTAINER)
WAITED 19.3520606 SECONDS FOR FILE
Content: C:\ProgramData\BcContainerHelper\030d8ff5-364f-41db-94df-b53ad491b6a5.app
WAITED 19.4598572 SECONDS FOR FILE
Content: C:\ProgramData\BcContainerHelper\fcd85706-7ad6-4617-bcec-f698b3efd692.app
WAITED 19.5394904 SECONDS FOR FILE
Content: C:\ProgramData\BcContainerHelper\652d1ddc-cad2-44ac-8ca8-30eaf06d757d.app

Are you able to provide a fix, workaround, helpful comment? Is there something wrong with the PS7 session? Or the file operation? Or .NET?

Do you have contact to someone (PS team, .NET team, ...) who is able to point something out with tne above information?

@freddydk
Copy link
Contributor

Will have a look and see if I can understand what is happening here.

@freddydk
Copy link
Contributor

So, it really is this simple...

$containerName = 'bc24';
$scriptblock = { Param($tmpfile)
    Write-Host "WAITED $((Measure-Command { while (!(Test-Path -Path $tmpfile)) { Start-Sleep -Milliseconds 100 } }).TotalSeconds) SECONDS FOR FILE";
    $content = Get-Content -Path $tmpfile; Write-Host "Content: $($content)";
    Remove-Item -Path $tmpfile -Force;
}

$destname = Join-Path $bcContainerHelperConfig.hostHelperFolder "$([guid]::NewGuid().ToString()).app"; $destname | Out-File -FilePath $destname -Force;
Invoke-ScriptInBcContainer -containerName $containerName -scriptblock $scriptblock -argumentList (Get-BcContainerPath -containerName $containerName -path $destname);
$destname = Join-Path $bcContainerHelperConfig.hostHelperFolder "$([guid]::NewGuid().ToString()).app"; $destname | Out-File -FilePath $destname -Force;
Invoke-ScriptInBcContainer -containerName $containerName -scriptblock $scriptblock -argumentList (Get-BcContainerPath -containerName $containerName -path $destname);
Start-Sleep -Seconds 20
$destname = Join-Path $bcContainerHelperConfig.hostHelperFolder "$([guid]::NewGuid().ToString()).app"; $destname | Out-File -FilePath $destname -Force;
Invoke-ScriptInBcContainer -containerName $containerName -scriptblock $scriptblock -argumentList (Get-BcContainerPath -containerName $containerName -path $destname);

First is fast.
Second is slow
Third is fast

It seems like there is some kind of cache after performing a file operation inside a hyperv session, which flushes after 20 seconds. If I cannot figure out myself what this is, maybe I know somebody who can.

@freddydk
Copy link
Contributor

freddydk commented Jun 22, 2024

It becomes even more crazy - just tried a longshot

$scriptblock = { Param($tmpfile)
    Write-Host "WAITED $((Measure-Command { while (!(Test-Path -Path $tmpfile)) { Start-Sleep -Milliseconds 100 } }).TotalSeconds) SECONDS FOR FILE";
    $content = Get-Content -Path $tmpfile
    Write-Host "Content: $($content)"
    Remove-Item -Path $tmpfile -Force
    Set-Content -Path 'c:\programdata\bccontainerhelper\$($tmpfile.GetHashCode()).txt' -Value $content
}

removes the problem...
If I use a fixed name (i.e. the file exists), then the problem persists.
If I use a subfolder (i.e. c:\programdata\bccontainerhelper\extensions) then the problem also persists.

It's like creating a file in the folder where the file was removed flushes some kind of cache.

This:

$scriptblock = { Param($tmpfile)
    Write-Host "WAITED $((Measure-Command { while (!(Test-Path -Path $tmpfile)) { Start-Sleep -Milliseconds 100 } }).TotalSeconds) SECONDS FOR FILE";
    $content = Get-Content -Path $tmpfile
    Write-Host "Content: $($content)"
    powershell "Remove-Item -Path '$tmpfile' -Force"
}

Also removes the problem (using powershell 5 to delete the file)
and finally, this:

$scriptblock = { Param($tmpfile)
    Write-Host "WAITED $((Measure-Command { while (!(Test-Path -Path $tmpfile)) { Start-Sleep -Milliseconds 100 } }).TotalSeconds) SECONDS FOR FILE";
    $content = Get-Content -Path $tmpfile
    Write-Host "Content: $($content)"
    [System.IO.File]::Delete($tmpfile)
}

also removes the problem

But... - Run-AlCops doesn't really remove any files though - so there are probably other things that makes this fail.

Will discuss this with some people who might know what is going on.

@freddydk
Copy link
Contributor

I will have to create a repro without any kind of BcContainerHelper - a clean WindowsServerCore container - install powershell 7, repro the issue and file a bug here: https://github.com/PowerShell/PowerShell

@freddydk
Copy link
Contributor

PowerShell/PowerShell#23982

@MODUSCarstenScholling
Copy link
Contributor Author

Thank you very much for that much help and assistance. A really special issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants