microsoft / navcontainerhelper

Official Microsoft repository for BcContainerHelper, a PowerShell module, which makes it easier to work with Business Central Containers on Docker.
MIT License
382 stars 243 forks source link

Invoke-ScriptInBcContainer has Problem with Deserialize Output #3704

Closed HeWessel closed 1 day ago

HeWessel commented 1 day ago

Describe the issue Currently we using the BC Containers with a central SQL Server and i currently facing a Problem with updating the Database. To Update our Databases we normally create a own Container with the Target BC Version and then invoke the Database Update Script from this one. Firstly i thought i have to change my Script. For further Investigation i checked the output of the BcContainerScripts and figured out that the Script was executed sucessfully but the output werent able to be parsed?

You should be able to reproduce the Error easy with the script.

Scripts used to create container and cause the issue

$Url = Get-BCArtifactUrlFromBCArtifact -BCArtifact $BCArtifact
New-BcContainer -accept_eula -containerName $databaseName -artifactUrl $url -Credential $Credentials 
try {
    Invoke-ScriptInBcContainer -containerName $databaseName -scriptblock {
        Param([string] $databaseserver,
              [string] $databasename,
              [PSCredential] $databaseCredentials) 
        if ($databaseCredentials -and ($databaseCredentials.UserName -ne ''))
        {
            $params += @{"ApplicationDatabaseCredentials" = $databaseCredentials}
        }
        Invoke-NAVApplicationDatabaseConversion -DatabaseServer $databaseserver -DatabaseName $databaseName @params -force   
    } -argumentList $databaseserver, $databasename, $databaseCredentials
}
finally {
    Remove-BcContainer $databaseName
}

Full output of scripts

BcContainerHelper version 6.0.25
Setting usePsSession = False
Setting hostHelperFolder = d:\ContainerHelper
Setting bcartifactsCacheFolder = d:\bcartifacts.cache
BC.HelperFunctions emits usage statistics telemetry to Microsoft
Running on Windows, PowerShell 5.1.17763.6292
# here the successful output from the Create-Container
Invoke-ScriptInBcContainer : Ausnahme beim Aufrufen von "Deserialize" mit 1 Argument(en):  "Schlüssel ist im angegebenen Status nicht gültig.
"
In C:\Users\builduser\Desktop\Scripte\hw\DBConvert_BC25.ps1:16 Zeichen:1
+ Invoke-ScriptInBcContainer -containerName "hwbc25" -ErrorAction Silen ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Invoke-ScriptInBcContainer], MethodInvocationException
    + FullyQualifiedErrorId : CryptographicException,Invoke-ScriptInBcContainer
...

If you need further information let me know. Greetings Hermann

freddydk commented 1 day ago

If I am to run the script above... - what are you using as databaseServer? and what are you using as artifacts? (onprem or sandbox and which version?) are you running the database in a container or on the host? What generic image are you using? I need the full output of the container generation to answer these and other questions.

But... - as far as I know, the Invoke-NavApplicationDatabaseConversion doesn't return anything - so I doubt that the problem is normal deserialization. I do however remember that you cannot return securestrings from Invoke-ScriptInBcContainer.

HeWessel commented 1 day ago

I didnt thought, it would be helpful but at the End is the complete Script.

I was also wondering what should be deserialized in this Script. We build this whole Container only to use the "Invoke-NavApplicationDatabaseConversion" to a different Database which is not located inside the Container and not even on the host. We changed to this method, so we always can use the NavAdmin Tools without taking care about new Dependencies. When i try to use the Script directly on the host i get Dependecy Error "Missing Assembly Microsoft.Bcl.AsyncInterfaces" for BC 25. I also added the two Files which were genereated from the BcContainerhelper for execute the Script in the Container. OutputBcContainerhelper.zip

Here is the complete Output Script

BcContainerHelper version 6.0.25
Setting usePsSession = False
Setting hostHelperFolder = d:\ContainerHelper
Setting bcartifactsCacheFolder = d:\bcartifacts.cache
BC.HelperFunctions emits usage statistics telemetry to Microsoft
Running on Windows, PowerShell 5.1.17763.6292
BcContainerHelper is version 6.0.25
BcContainerHelper is running as administrator
HyperV is Disabled
Host is Microsoft Windows Server 2019 Standard - 10.0.17763.6293
UsePsSession is False
UsePwshForBc24 is True
UseWinRmSession is allow
UseSslForWinRmSession is True
Docker Client Version is 25.0.4
Docker Server Version is 25.0.4
Removing Desktop shortcuts
Removing d:\ContainerHelper\Extensions\dockerhwss
Fetching all docker images
Fetching all docker volumes
Using image mcr.microsoft.com/businesscentral:ltsc2019
Creating Container dockerhwss
Style: onprem
Multitenant: No
Version: 25.0.23364.24652
Platform: 25.0.24618.0
Generic Tag: 1.0.2.46
Container OS Version: 10.0.17763.6293 (ltsc2019)
Host OS Version: 10.0.17763.6293 (ltsc2019)
Using process isolation
Using locale en-US
Disabling the standard eventlog dump to container log every 2 seconds (use -dumpEventLog to enable)
Additional Parameters:
--expose 5986
Files in d:\ContainerHelper\Extensions\dockerhwss\my:
- AdditionalOutput.ps1
- AdditionalSetup.ps1
- HelperFunctions.ps1
- MainLoop.ps1
- SetupVariables.ps1
- updatecontainerhosts.ps1
Creating container dockerhwss from image mcr.microsoft.com/businesscentral:ltsc2019
161563a14486a78c5a821ff33df8cebe707cdc530b6b9368cb313864173d6adf
Waiting for container dockerhwss to be ready
Using artifactUrl https://bcartifacts-exdbf9fwegejdqak.b02.azurefd.net/onprem/25.0.23364.24652/w1
Using installer from C:\Run\240
Installing Business Central: multitenant=False, installOnly=False, filesOnly=False, includeTestToolkit=False, includeTestLibrariesOnly=False, includeTestFrameworkOnly=False, includePerformanceToolkit=False, appArt
ifactPath=c:\dl\onprem\25.0.23364.24652\w1, platformArtifactPath=c:\dl\onprem\25.0.23364.24652\platform, databasePath=c:\dl\onprem\25.0.23364.24652\w1\database\Demo Database BC (25-0).bak, licenseFilePath=c:\dl\on
prem\25.0.23364.24652\w1\database\Cronus.bclicense, rebootContainer=True
Installing from artifacts
Starting Local SQL Server
Starting Internet Information Server
Copying Service Tier Files
c:\dl\onprem\25.0.23364.24652\platform\ServiceTier\Program Files
c:\dl\onprem\25.0.23364.24652\platform\ServiceTier\System64Folder
Copying Web Client Files
c:\dl\onprem\25.0.23364.24652\platform\WebClient\Microsoft Dynamics NAV
Copying ModernDev Files
c:\dl\onprem\25.0.23364.24652\platform
c:\dl\onprem\25.0.23364.24652\platform\ModernDev\program files\Microsoft Dynamics NAV
Copying additional files
Copying ConfigurationPackages
C:\dl\onprem\25.0.23364.24652\platform\ConfigurationPackages
Copying Test Assemblies
C:\dl\onprem\25.0.23364.24652\platform\Test Assemblies
Copying Applications
C:\dl\onprem\25.0.23364.24652\platform\Applications
Copying dependencies
Importing PowerShell Modules
Restoring CRONUS Demo Database
Setting CompatibilityLevel for CRONUS on localhost\SQLEXPRESS
Modifying Business Central Service Tier Config File for Docker
Creating Business Central Service Tier
Installing SIP crypto provider: 'C:\Windows\System32\NavSip.dll'
Starting Business Central Service Tier
Importing license file
Stopping Business Central Service Tier
Installation took 183 seconds
Installation complete
Initializing...
Setting host.containerhelper.internal to 172.25.240.1 in container hosts file
Starting Container
Hostname is dockerhwss
PublicDnsName is dockerhwss
Using Windows Authentication
Modifying Service Tier Config File with Instance Specific Settings
Starting Service Tier
Registering event sources
Creating DotNetCore Web Server Instance
Using application pool name: BC
Using default container name: NavWebApplicationContainer
Copy files to WWW root C:\inetpub\wwwroot\BC
Create the application pool BC
Create website: NavWebApplicationContainer without SSL
Update configuration: navsettings.json
Done Configuring Web Client
Creating http download site
Creating Windows user DockerUser
Setting SA Password and enabling SA
Creating SUPER user
Enable PSRemoting and setup user for winrm
Creating self-signed certificate for winrm
Container IP Address: 172.25.246.208
Container Hostname  : dockerhwss
Container Dns Name  : dockerhwss
Web Client          : http://dockerhwss/BC/
Dev. Server         : http://dockerhwss
Dev. ServerInstance : BC

Files:
http://dockerhwss:8080/ALLanguage.vsix

Container Total Physical Memory is 639.9Gb
Container Free Physical Memory is 243.3Gb

Initialization took 69 seconds
Ready for connections!
Reading CustomSettings.config from dockerhwss
Creating Desktop Shortcuts for dockerhwss
Cleanup old dotnet core assemblies
Container dockerhwss successfully created

Use:
Get-BcContainerEventLog -containerName dockerhwss to retrieve a snapshot of the event log from the container
Get-BcContainerDebugInfo -containerName dockerhwss to get debug information about the container
Enter-BcContainer -containerName dockerhwss to open a PowerShell prompt inside the container
Remove-BcContainer -containerName dockerhwss to remove the container again
docker logs dockerhwss to retrieve information about URL's again
Removing Session dockerhwss
Removing container dockerhwss
Removing Desktop shortcuts
Removing d:\ContainerHelper\Extensions\dockerhwss
Invoke-ScriptInBcContainer : Ausnahme beim Aufrufen von "Deserialize" mit 1 Argument(en):  "Schlüssel ist im angegebenen Status nicht gültig.
"
In Zeile:29 Zeichen:13
+             Invoke-ScriptInBcContainer -containerName $containername  ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Invoke-ScriptInBcContainer], MethodInvocationException
    + FullyQualifiedErrorId : CryptographicException,Invoke-ScriptInBcContainer
freddydk commented 1 day ago

It looks like the function does return some object and you obviously cannot deserialize that on the host if you don't have the DLLs with these objects installed. You can probably just add | Out-Null after your Invoke-Nav.... call. Then the invoke-script won't have anything to serialize.

HeWessel commented 1 day ago

so the Output of the Invoke-Nav call has changed from BC 24 to BC 25? so i handle the whole Error inside the Script and just let the Output null for the whole Invoke-ScriptinBcContainer. Thanks for your fast Support and have a good Start intho this Week

freddydk commented 1 day ago

so the Output of the Invoke-Nav call has changed from BC 24 to BC 25?

Have no idea - but very likely a new version of the class

freddydk commented 1 day ago

so i handle the whole Error inside the Script and just let the Output null for the whole Invoke-ScriptinBcContainer.

Error? If the function is failing, it should raise an execption which should be forwarded to the host...

But else - return a string or a Json string from the invoke to the host - that always works.

HeWessel commented 1 day ago

so i handle the whole Error inside the Script and just let the Output null for the whole Invoke-ScriptinBcContainer.

Error? If the function is failing, it should raise an execption which should be forwarded to the host...

But else - return a string or a Json string from the invoke to the host - that always works.

Error is the false Word. I just mean the complete Output. But thats a good idea to format all in just a String and return to the host. Thanks