Using .NET 4.8 themes in .NET8 app

Posted by: wknauf on 15 January 2025, 7:55 am EST

    • Post Options:
    • Link

    Posted 15 January 2025, 7:55 am EST

    Up to now it worked without problems to load the old themes into a .NET8 C1.Win.Themes.C1ThemeController. But with .493, this fails:

    Exception Type: C1.Win.Themes.Serialization.SerializerException
    Exception Message: Type [Enum-C1.Win.C1Themes.TabStyle] not found.
    StackTrace:
       at C1.Win.Themes.Serialization.Serializer.ReadObject(Type objType)
       at C1.Win.Themes.Serialization.Serializer.ReadObject()
       at C1.Win.Themes.ThemeItemCollection.C1.Win.Themes.Serialization.ISerializable.ReadProp(Serializer a, String b, Type c, String d)
       at C1.Win.Themes.Serialization.Serializer.d(ISerializable a)
       at C1.Win.Themes.Serialization.Serializer.ReadObject(ISerializable obj)
       ...
       at C1.Win.Themes.Serialization.Serializer.Read(ISerializable obj, Stream stream)
       at C1.Win.Themes.C1Theme.Load(Stream stream, C1ThemeFormat format)
       at C1.Win.Themes.C1ThemeController.RegisterTheme(Stream stream, C1ThemeFormat format)
       at C1.Win.Themes.C1ThemeController.RegisterTheme(String fileName)
    

    See attached sample (“Old\BeigeOne.c1themez” is a theme from an older C1 version - probably beginning of 2024, “New\BeigeOne.c1themez” is from .693 and fails to load).

    LegacyThemes.zip

    I tracked it down to this snippet in the theme files:

    <Enum-C1.Win.C1Themes.TabStyle Name="TabStyle">
      <AllowedValues>Classic,Sloping,Rounded,Rectangle,Office2007,Office2010,Office365</AllowedValues>
    </Enum-C1.Win.C1Themes.TabStyle>

    It works if I change it to this:

    <Enum-C1.Win.C1Themes.TabShape Name="TabShape">
      <AllowedValues>Sloping,Rounded,Rectangle,Office365</AllowedValues>
    </Enum-C1.Win.C1Themes.TabShape>


    (see file “New_493\BeigeOne_Workaround.c1themez”)

    Could you confirm that this is a valid workaround and that I picked the corresponding enum in the .NET8 version? If yes I could create a small powershell script to convert the c1themez files.

    Best regards

    Wolfgang

  • Posted 16 January 2025, 5:16 am EST

    Hi Wolfgang,

    Thank you for providing all the details. We could see the behavior you mentioned. The workaround also seems to be working fine in all cases. However, we are getting in touch with the development team to get their insights on whether there are any edge cases where this workaround could break. We will let you know the updates as soon as possible.

    [Internal Tracking ID: C1WIN-33548]

    Best Regards,

    Kartik

  • Posted 22 January 2025, 2:05 am EST

    Hi Wolfgang,

    As per the development team, this is a valid workaround, and you can use it without any issues. Additionally, they will discuss internally whether further handling of invalid values is required to better support this scenario. However, as it is not considered a critical issue, an ETA has not been set.

    Thanks, and Best Regards,

    Kartik

  • Posted 22 January 2025, 5:39 am EST

    If others run into the same problem: Here is a powershell script that copies the .NET 4.8 themes from the installation location to the current directory and updates them to work with .NET 8.

    Save the file to an empty directory and launch it. It supports Powershell 5 and 7.

    #Requires -Version 5
    #https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/set-strictmode
    Set-StrictMode -Version 3
    Set-PSDebug -Strict
    $ErrorActionPreference = "Stop"
    try
    {
      #Add required assemblies:
      Add-Type -assembly "System.IO.Compression"
      Add-Type -assembly "System.IO.Compression.Filesystem"
    
      #Copy themes from C1 installation dir:
      [string] $sourceDir = "C:\Program Files (x86)\MESCIUS\ComponentOne\WinForms\C1Themes\Themes"
    
      $files = Get-ChildItem -Path $sourceDir -Filter *.c1themez 
      
      [System.Text.Encoding] $encodingUtfWithBom = New-Object -TypeName System.Text.UTF8Encoding -ArgumentList $true
      for ($IndexFile = 0; $IndexFile -lt $files.Length; $IndexFile++) {
        [System.IO.FileInfo] $File = $Files[$IndexFile]
    
        [string] $FileName = $File.name
        [string] $FileTarget =  "$(Get-Location)\$FileName"
        
        Write-Host "Processing file  $FileName..."
    
        Copy-Item -Path $File.FullName -Destination $FileTarget
    
        #Open copied file:
        [System.IO.Compression.ZipArchive]$zipArchive = [System.IO.Compression.ZipFile]::Open($FileTarget, [System.IO.Compression.ZipArchiveMode]::Update)
        [System.IO.Compression.ZipArchiveEntry] $ZipEntry = $zipArchive.Entries[0]
        [System.IO.Stream] $stream = $ZipEntry.Open()
        [System.IO.StreamReader] $reader = New-Object System.IO.StreamReader($stream, $encodingUtfWithBom)
    
        [string] $FileContent = $reader.ReadToEnd()
        
        [string] $FileContentNew = $FileContent.Replace("<Enum-C1.Win.C1Themes.TabStyle Name=""TabStyle"">", "<Enum-C1.Win.C1Themes.TabShape Name=""TabShape"">")
        $FileContentNew = $FileContentNew.Replace("<AllowedValues>Classic,Sloping,Rounded,Rectangle,Office2007,Office2010,Office365</AllowedValues>", "<AllowedValues>Sloping,Rounded,Rectangle,Office365</AllowedValues>")
        $FileContentNew= $FileContentNew.Replace("</Enum-C1.Win.C1Themes.TabStyle>", "</Enum-C1.Win.C1Themes.TabShape>")
    
        if ($FileContent -ne $FileContentNew) {
          Write-Host "   Replacement done"
        }
    
        #Set the stream to position 0:
        $stream.Position = 0
        #Trim the stream - new length might be shorter:
        $stream.SetLength(0)
        [System.IO.StreamWriter] $writer = New-Object System.IO.StreamWriter($stream, $encodingUtfWithBom)
        $writer.Write($FileContentNew)
        $writer.Flush()
        $writer.Close()
        $writer.Dispose()
    
        #Close the reader not before this - underlying stream is closed otherwise, which would break the writer
        $reader.Close()
        $reader.Dispose()
    
        $zipArchive.Dispose()
      }
    
      Read-Host "Done. Press enter."
    }
    catch [Exception]
    {
      [string] $ExceptionText = ($_.Exception | Format-List -Force) | Out-String
      Write-Host "Exception of type  $($_.Exception.GetType().FullName)" -ForegroundColor Red
      Write-Host $ExceptionText -ForegroundColor Red
    
      [string] $InvocationInfoText = ($_.InvocationInfo | Format-List -Force) | Out-String
      Write-Host $InvocationInfoText 
    
      Read-Host "Press enter"
      Exit
    }
Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels