Let’s Encrypt PowerShell script fails reading M... | MDaemon Technologies Community Forum

Let’s Encrypt PowerShell script fails reading MDaemon.ini - Add-Type / GetPrivateProfileString BadImageFormatException


  • Hi all,

    We had an issue where MDaemon stopped updating its Let’s Encrypt SSL certificate automatically.

    The failure was not DNS, ACME validation, or the certificate itself. The script was failing before renewal because it could not read valid MDaemon .ini values.

    The key error was:

    Add-Type : Could not load file or assembly ...
    BadImageFormatException

    This occurred inside the script’s Get-PrivateProfileString helper, which uses Add-Type and the Windows API GetPrivateProfileString call to read INI values.

    After that failed, values such as the PEM path and state path came back empty/null, leading to later errors such as:

    Cannot bind argument to parameter 'Path' because it is null
    Cannot bind argument to parameter 'Path' because it is an empty string

    In our case, the MDaemon registry values and INI file were valid. For example:

    D:\MDaemon\App\MDaemon.ini
    PEM=D:\MDaemon\PEM\

    PowerShell was confirmed as 64-bit:

    [Environment]::Is64BitProcess
    True
    
    $PSHOME
    C:\Windows\System32\WindowsPowerShell\v1.0

    As a workaround, we replaced the Get-PrivateProfileString function with a pure PowerShell INI parser instead of using Add-Type. After that, the script correctly read the MDaemon paths, renewed the Let’s Encrypt certificate, and applied/uploaded the SSL successfully.

    This looks like a robustness issue in the Let’s Encrypt PowerShell script: if the Add-Type based INI reader fails, the script reports downstream path/null errors even though the MDaemon configuration is valid.

    Has anyone else seen this with recent Windows/PowerShell environments, or is there an updated MDaemon Let’s Encrypt script that avoids this Add-Type/GetPrivateProfileString issue?



  • In the past when we have tried a powershell INI parser, we ran into issues reading and writing to the INI file which caused issues, which is why we are using GetPrivateProfileString.

    I don't recall ever seeing this error.  A quick run through an AI engine indicates it is most likely a problem in the environment.

    What version of MDaemon are you using?

    What operating system are you using?

    What version of .NET framework 4.x is installed?

    What version of Powershell are you using?  $PSVersionTable.PSVersion

    How are you invoking the script? Are you starting the MDaemon UI and having it execute the sccript? Are you using an event in Windows Task Scheduler?  Do you have a powershell command prompt open and running it manually?  Are you using Windows Powershell ISE? If you invoke the script using a different method do you have the same issue?

    Was [Environment]::Is64BitProcess added to the script and then the output checked?  

    AI also indicates that this could be caused by a corrupt or wrong architecture dll in the working directory or TEMP directory, a damaged .net framework, or AntiVirus quarantining the temporary compiled assembly that is emitted by csc.exe.  

    Can you post the full error message that is returned from the Add-Type command?  You "should" be able to reproduce the issue by just running the following script:

      $signature = @'
      [DllImport("kernel32.dll")]
      public static extern uint GetPrivateProfileString(
         string lpAppName,
         string lpKeyName,
         string lpDefault,
         StringBuilder lpReturnedString,
         uint nSize,
         string lpFileName);
    '@
    
      # Show the environment first — these matter for diagnosing it
      "Is64BitProcess : $([Environment]::Is64BitProcess)"
      "PSVersion      : $($PSVersionTable.PSVersion)"
      "TEMP           : $env:TEMP"
      ""
    
      try {
          Add-Type -MemberDefinition $signature `
              -Name Win32Utils -Namespace GetPrivateProfileString `
              -Using System.Text -PassThru -ErrorAction Stop | Out-Null
          "SUCCESS - Add-Type compiled with no error."
      }
      catch {
          "===== FULL ERROR ====="
          $ex = $_.Exception
          while ($ex) {
              "Type    : $($ex.GetType().FullName)"
              "Message : $($ex.Message)"
              if ($ex.HResult) { "HResult : 0x{0:X8}" -f $ex.HResult }
              if ($ex -is [System.IO.FileLoadException] -or $ex -is [System.BadImageFormatException]) {
                  "FileName: $($ex.FileName)"
                  "FusionLog:`n$($ex.FusionLog)"
              }
              $ex = $ex.InnerException
              if ($ex) { "----- inner exception -----" }
          }
      }
    

    Don't dot-source the script — it is a standalone script, you don't need any MDaemon paths or parameters. Just paste and run.

    Run it twice: once in the 64-bit shell, and once in the 32-bit shell (C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe).

    Copy the entire ===== FULL ERROR ===== block from each run and post it to the groups.  Please clearly mark which output is from the 32 bit and which is from the 64 bit.


  • Manual run from 64-bit Windows PowerShell prompt:
    C:\Windows\System32\WindowsPowerShell\v1.0

    PS D:\MDaemon\LetsEncrypt> # MDaemon version
    PS D:\MDaemon\LetsEncrypt> (Get-Item "D:\MDaemon\App\MDaemon.exe").VersionInfo | Select-Object ProductVersion, FileVersion

    ProductVersion FileVersion
    -------------- -----------
    26.0.2         26.0.2


    PS D:\MDaemon\LetsEncrypt>
    PS D:\MDaemon\LetsEncrypt> # OS version
    PS D:\MDaemon\LetsEncrypt> Get-ComputerInfo | Select-Object WindowsProductName, WindowsVersion, OsBuildNumber, OsArchitecture

    WindowsProductName           WindowsVersion OsBuildNumber OsArchitecture
    ------------------           -------------- ------------- --------------
    Windows Server 2019 Standard 1809           17763         64-bit


    PS D:\MDaemon\LetsEncrypt>
    PS D:\MDaemon\LetsEncrypt> # PowerShell version
    PS D:\MDaemon\LetsEncrypt> $PSVersionTable

    Name                           Value
    ----                           -----
    PSVersion                      5.1.17763.8755
    PSEdition                      Desktop
    PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
    BuildVersion                   10.0.17763.8755
    CLRVersion                     4.0.30319.42000
    WSManStackVersion              3.0
    PSRemotingProtocolVersion      2.3
    SerializationVersion           1.1.0.1


    PS D:\MDaemon\LetsEncrypt>
    PS D:\MDaemon\LetsEncrypt> # .NET 4.x release key
    PS D:\MDaemon\LetsEncrypt> Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" |
    >> Select-Object Release, Version

    Release Version
    ------- -------
     528049 4.8.03761


    PS D:\MDaemon\LetsEncrypt>
    PS D:\MDaemon\LetsEncrypt> # PowerShell bitness
    PS D:\MDaemon\LetsEncrypt> [Environment]::Is64BitProcess
    True
    PS D:\MDaemon\LetsEncrypt> $PSHOME
    C:\Windows\System32\WindowsPowerShell\v1.0
    PS D:\MDaemon\LetsEncrypt>


Please login to reply to this topic!