Gacless Tekla Structures 2024 - Developer Impact

Updated: 20 Mar 2024

GAC (Global assembly Cache) in Tekla Structures 2024

Historically GAC (Global Assembly Cache - .NET Framework | Microsoft Learn) has been used as the means to ensure Tekla Structures extensions can "talk" with the main Tekla Structures process.

Extensions are divided into two main categories:

  • Extensions running inside Tekla Structures process (plug-ins) - GAC is not used because the main process controls what assemblies are loaded according to the application config file (teklastructures.exe.config) found in the same location as the application executable.
  • Extensions running in a separate process (applications) - GAC and Remoting were the possible solutions for the proper interoperability between the two processes.

In practice, GAC acts as a repository of assemblies that are always used in all conditions by all the processes that use them. Only one version will be loaded and shared by different processes. This ensures types are consistent and prevents interop issues.

GAC shortcomings and issues

This is the list of troubles the GAC version of Tekla Structures has caused during the years:

  • Admin usage, even if not apparent because users typically use installers. They require admin access to the machine to use the product. Which for some users might not be possible.
  • Installers have a bad/good habit of locking GAC assemblies. This ensures we don't remove stuff that breaks the application functionality. However, it is difficult to update the software in a reliable way, because most of the time GAC assemblies are left behind when the application is uninstalled.
  • Because of the previous bullet, having Official Builds or UFP builds is not fully supported. This problem is minimized by forcing the most recent DLL to be in the GAC. However this is not bulletproof solution, and over and over and over again issues have been raised about builds being broken.
  • GAC is a .NET framework concept, it has never been ported to .NET 5, 6, 7, 8 which supersede the .NET framework as the official way of developing .NET applications.

Gacless mode

The new introduced way to handle GAC pretty much mimics a GAC operation. Loading the assemblies from a GAC folder found in c:\windows\ (which requires admin access and additional logic in the installer to decide the version that gets deployed there) is not happening, instead, we let Tekla Structures at runtime define where those assemblies are found. With this method, we can then solve the following issues:

  • No admin mode is required. We will be able to explore different deployment methods that don't require a system admin.
  • Each Tekla Structures will run independently from other ones and will not share any assemblies with others, so each can be upgraded without affecting the other.
  • We paved the way to .NET 6.0 .NET 7.0 which suppressed the current and old .net 4.8.1 framework
  • Simplify developer experience

Tekla Structures runtime and TSEP - The loading/patching process

As mentioned above, this change will not have any impact in the plugins that run in the Tekla Structures process.

It will however have an impact on any extension that runs as a standalone process. To avoid breaking those tools Tekla Structures and TSEP system will apply a patch each exe.config to force the above codebase elements into each assembly Tekla Structures controls. 

This change in principle should be enough to ensure the extension will remain fully working. Problems should be reported on the Discussion Forum as usual.

How it is implemented - Patching rules on app config files

The implementation relies on <codeBase> Element - .NET Framework | Microsoft Learn. It tells the runtime where we can find the assembly to load. What we do is we patch the relevant app.config elements with the following 

<dependentAssembly>
  <assemblyIdentity name="Tekla.Structures" publicKeyToken="2f04dbe497b71114" culture="neutral" />
  <bindingRedirect oldVersion="0.0.0.0-2099.1.0.0" newVersion="2024.0.0.0" />
  <codeBase href="file:///c:/Program Files/TeklaStructures/2024/bin/Tekla.Structures.dll" version="2024.0.0.0" />
</dependentAssembly>

when Tekla Structures starts codebase will point to the dll inside the binary folder. The following rules apply to all patching with TSEP and Tekla Structures:

  • only assemblies that are considered GAC (assemblies that can only have one loaded in the application), will be patched into the configuration files.
  • versions will be adjusted according to the Tekla version.
  • Codebase elements will direct the loading to the assemblies found in the bin folder.
  • if an exe doesn't provide a config file one will be created by Tekla Structures and TSEP, applying the above rules.
  • Any other bindings will remain untouched, so you can also bring your own logic to the application.

Patched locations

Tekla Structures will patch the following locations when it starts

  • Default extensions folder:  XS_EXTENSION_DIRECTORY : %XSDATADIR%\environments\common\extensions
  • Firm folder: XS_FIRM
  • Project Folder: XS_PROJECT
  • Macros folders: XS_MACRO_DIRECTORY
  • Selected Environment: pointed by the selected env.ini file. All exes found under the env will be patched
  • TSEP system if used will patch any exe that is delivered to any folder, regardless if they are found or not in the above folders

Impact on Extension Developers

Running your deployed extension 

TSEP system and Tekla Structures at start time will patch the relevant config or generate new ones if they have not been provided. We will apply the relevant patches to ensure everything works. This is valid for the patched locations above!

Running an extension outside the official locations

This is still possible, users can create macros that will start external processes that we don't control. Depending on the location users can use the following API to patch their applications, that way applications can run with Tekla Structures. In a Tekla Structures macro add the following:

var yourApplicationToRun = <LOCATIONTOAPP.EXE>;
DotNetKit.AppConfigHelpers.NormalizeAppConfigForApplicationExe(yourApplicationToRun);

// run your app
Process.Start(yourApplicationToRun);
  • this will work only if user has write access to location, so if you are planning to call applications from "C:\Program Files" for example, the patching must be done at installation which might bring more complications. In such cases, the only solution is to create the app configs manually before the installers are created. We don't recommend this to users.

Developing your extension

We recommend always the following guidelines for extensions development, these guidelines minimize the risk of regressions when a new release is done. It also reduces the maintenance effort for each extension. 

  • Use TSEP system or any packaging system recommended to deliver extensions.
  • Use Nuget official libraries from Tekla Open API libraries.
  • Target to the oldest supported API that works for the extension, Tekla Open API libraries are backwards compatible.
  • Avoid using internal APIs, they usually break from version to version. It is preferable to open support requests for those APIs to be made public and backwards compatibility enforced.
  • Deploying external dependencies with your extension. Even if Tekla Structures already contains those and your app uses a different version, Tekla Structures will still be able to load the version deployed with the extension to ensure your app runs.
  • Don't deploy GAC assemblies, that's a waste of space and it only slows down installation and updates.
  • Upgrade your extension only if you need to use new Tekla Open API version, these always remain backwards compatible.
  • Create automated tests to ensure your extensions works.
  • Migrate your projects to .NET SDK format (.NET project SDK overview | Microsoft Learn) and keep inline with Microsoft recommendations.
  • Use WPF technology for the UI of your extensions, to align your extension style with rest of the Tekla Structures application.

Debugging and running Tests for your extension

The Gacless changes will actually simplify the development experience for users. Earlier, compiling a extensions and debugging it in different Tekla versions required installing new Nuget packages, changing output paths with a lot of manual work and a lot of error-prone processes. Now this can be achieved with the following three steps

  1. Define the <TeklaStructuresInstallationPath><INSTALLATIONBINFOLDER></TeklaStructuresInstallationPath>, you can add a new property to every project by defining it in a single file called Directory.Build.props in the root folder that contains your source.  See the next section for Recommendations
  2. Or Define <TeklaVersion>TeklaVersion</TeklaVersion> in the same Directory.build.pros. Version is for example 2024.0, and maps to the registry where Tekla Structures is said to be installed!
  3. Install TSAppConfigPatcherTask nuget package (2.1.0 or above) on your application executable or unit tests from Nuget.org
  4. Build and press F5, if Tekla Structures is running it will work without any further setup

PS: you can only define either TeklaStructuresInstallationPath or TeklaVersion

Recommendations for placing TeklaStructuresInstallationPath or TeklaVersion

The parameter should point to for example C:\Program Files\Tekla Structures\2024.0\bin, or whatever place TeklaStructures.exe is located. 

We recommend reading: Customize your build by folder or solution - MSBuild | Microsoft Learn to understand the concept of Directory.build.props

 

Recommendation 1 - simple but will affect your git changes if you need to change the target path 

Create Directory.build.props inside the root of the repository tool and add the parameter there!

ExtensionFolder\Directory.Build.Props

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
  <PropertyGroup>
    <TeklaStructuresInstallationPath Condition="'$(Configuration)' == 'Debug'">C:\Program Files\Tekla Structures\$(VERSION)\bin</TeklaStructuresInstallationPath>
  </PropertyGroup>
</Project>

or

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
  <PropertyGroup>
    <TeklaVersion Condition="'$(Configuration)' == 'Debug'">$(VERSION)</TeklaVersion>
  </PropertyGroup>
</Project>

$(VERSION) - replace with relevant Tekla Structures version folder, example 2024.0

 

Recommendation 2 - gives you more flexibility over multiple extension development for different Tekla Structures versions

Create following folder tree structure:

ROOT_DEV_2024 - refers to a local folder for example c:\Users\youruser\Source\2024

    $(ROOT_DEV_2024)\Directory.Build.Props

    $(ROOT_DEV_2024)\ExtensionsA

    $(ROOT_DEV_2024)\ExtensionsB

    $(ROOT_DEV_OTHER_VERSION)\Directory.Build.Props

    $(ROOT_DEV_OTHER_VERSION)\ExtensionsA

    $(ROOT_DEV_OTHER_VERSION)\ExtensionsB

Now when open a solution in Microsoft Visual Studio for any of the extensions, TeklaStructuresInstallationPath  will  be picked up!

In case your extensions already include a Directory.Build.props, you can import conditionally the parent props file like this

<Import Project="$(MSBuildThisFileDirectory)../Directory.Build.props" Condition="Exists('$(MSBuildThisFileDirectory)../Directory.Build.props')" />

 

Recommendation 3 - One file to control it all, you need to pay more attention

Using the new .NET SDK format, brings a lot of advantages over the previous format. One of the nicest features is that it actually updates if you modify any of the props files that apply different compilation settings. Therefore the folder structure in recommendation 2 above could be simply like this

    $(ROOT_DEV_ALL)\Directory.Build.Props

    $(ROOT_DEV_ALL)\ExtensionsA

    $(ROOT_DEV_ALL)\ExtensionsB

Open the Directory.Build.Props and modify it directly to target a different Tekla Structures version, build your extensions and just run. It will run against the chosen target.

Git can be used in the extensions itself, but its recommended that the directory.build pros be kept outside git so that you don't get bothered with changes in this file.

Unit tests and integration tests

You will be able to run unit and integration tests that connect to Tekla Structures by installing the PatcherTask, once installed, the building will generate the correct config files and you should be able to use the test explorer in Microsoft Visual Studio normally without copying dlls to any external locations.

Warnings when compiling after applying TSAppConfigpatherTask

5>E:\VsInstall2022\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets(2382,5): warning MSB3277: Found conflicts between different versions of "Tekla.Structures.Model" that could not be resolved.
5>E:\VsInstall2022\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets(2382,5): warning MSB3277: There was a conflict between "Tekla.Structures.Model, Version=2023.0.0.0, Culture=neutral, PublicKeyToken=2f04dbe497b71114" and "Tekla.Structures.Model, Version=2024.0.0.0, Culture=neutral, PublicKeyToken=2f04dbe497b71114".
5>E:\VsInstall2022\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets(2382,5): warning MSB3277:     "Tekla.Structures.Model, Version=2023.0.0.0, Culture=neutral, PublicKeyToken=2f04dbe497b71114" was chosen because it was primary and "Tekla.Structures.Model, Version=2024.0.0.0, Culture=neutral, PublicKeyToken=2f04dbe497b71114" was not.
5>E:\VsInstall2022\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets(2382,5): warning MSB3277:     References which depend on "Tekla.Structures.Model, Version=2023.0.0.0, Culture=neutral, PublicKeyToken=2f04dbe497b71114" [C:\Users\jocs\.nuget\packages\tekla.structures.model\2023.0.1\lib\net40\Tekla.Structures.Model.dll].
5>E:\VsInstall2022\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets(2382,5): warning MSB3277:         C:\Users\jocs\.nuget\packages\tekla.structures.model\2023.0.1\lib\net40\Tekla.Structures.Model.dll

In practice, those could be solved by using the nuget for the application you are deploying or patching all the dlls in the solution in the same way. However, dll patching is not really required since Tekla Structures controls the dlls to load, and exes and test dlls are needed. therefore the task skips all dll projects that are not unit tests. So we accept these warnings as development warnings that don't interfere.

However, we recommend the patching during development be done only in the Debug configuration, and leaving the Release configuration fully clean without Warnings so you can concentrate on warnings that are supposed to be fixed.

Was this helpful?
The feedback you give here is not visible to other users. We use your comments to improve the content.