├── HeadlessExample.2021
├── HeadlessExample.ini
├── App.config
├── HeadlessExample.2021.csproj
└── Program.cs
├── README.md
├── .gitignore
├── HeadlessExample.sln
├── LICENSE
└── .github
└── workflows
└── contrast_security_app.yaml
/HeadlessExample.2021/HeadlessExample.ini:
--------------------------------------------------------------------------------
1 | /** HeadlessExample.ini */
2 | call %cd%teklastructures.ini
3 |
4 | set XS_LOG_LEVEL=WARNING
5 |
6 |
7 |
--------------------------------------------------------------------------------
/HeadlessExample.2021/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HeadlessTeklaStructuresExample
2 | This example shows how to use Headless Tekla Structures to interact with model without opening TS UI.
3 |
4 | ## Licensing
5 | Currently on Flex is supported. Start TS with flex, close TS and Headless applications can be run.
--------------------------------------------------------------------------------
/HeadlessExample.2021/HeadlessExample.2021.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net48
4 | ..\BuildDrop
5 | x64
6 | Exe
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #ignore thumbnails created by windows
2 | Thumbs.db
3 |
4 | # Ignore files built by Visual Studio
5 | *.aps
6 | *.bak
7 | *.bu
8 | *.cache
9 | *.DotSettings
10 | *.idb
11 | *.ilk
12 | *.log
13 | *.metaproj
14 | *.ncb
15 | *.obj
16 | *.opensdf
17 | *.pch
18 | *.pdb
19 | *.sbr
20 | *.sdf
21 | *.sonar
22 | *.suo
23 | *.tlb
24 | *.tlh
25 | *.tmp
26 | *.user
27 | *.vspscc
28 | *.vsscc
29 | *_p.c
30 |
31 | # Developer tool generated files
32 | *My Amplifier XE Results - *
33 | *My Inspector XE Results - *
34 | *StyleCop.Cache
35 | *.orig
36 | *.rej
37 | *unittest-report*
38 |
39 | #Movies
40 | *.avi
41 | *.mkv
42 | *.mpg
43 |
44 | #Folders with generated stuff
45 | packages/
46 | obj/
47 | [Dd]ebug/
48 | [Rr]elease/
49 | [Tt]est[Rr]esult*/
50 |
51 | # Other version control
52 | .svn/
53 | *.MySCMServerInfo
54 |
55 |
56 | /BuildDrop/
57 | /.vs/
58 |
--------------------------------------------------------------------------------
/HeadlessExample.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.32126.317
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HeadlessExample.2021", "HeadlessExample.2021\HeadlessExample.2021.csproj", "{9AFC3EEF-658B-4901-938E-C5A93EF49973}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {9AFC3EEF-658B-4901-938E-C5A93EF49973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {9AFC3EEF-658B-4901-938E-C5A93EF49973}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {9AFC3EEF-658B-4901-938E-C5A93EF49973}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {9AFC3EEF-658B-4901-938E-C5A93EF49973}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {E9BBD204-26CA-43B1-AD3E-E8B89D310222}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2018, Tekla Structures
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/.github/workflows/contrast_security_app.yaml:
--------------------------------------------------------------------------------
1 | # DISCLAIMER: This workflow file has been auto-generated and committed to the repo by the GitHub App from Contrast Security.
2 | # Manual edits to this file could cause the integration to produce unexpected behavior or break.
3 | # Version: 1.0.0
4 | # Last updated: 2024-02-13T15:58:06.296050105Z
5 | name: Contrast Security App Workflow
6 | on:
7 | workflow_dispatch:
8 | push:
9 | branches:
10 | - master
11 | pull_request:
12 | types: [opened, synchronize, reopened]
13 | branches:
14 | - master
15 | jobs:
16 | fingerprint_repo:
17 | if: ${{ github.actor != 'dependabot[bot]' }}
18 | runs-on: ubuntu-22.04
19 | steps:
20 | - name: Clone repository
21 | uses: actions/checkout@v3
22 | - name: Run Contrast SCA Fingerprint
23 | id: fingerprint
24 | uses: 'Contrast-Security-OSS/contrast-sca-action@v2'
25 | with:
26 | apiKey: ${{ secrets.CONTRAST_GITHUB_APP_API_KEY }}
27 | authHeader: ${{ secrets.CONTRAST_GITHUB_APP_AUTH_HEADER }}
28 | orgId: ${{ vars.CONTRAST_GITHUB_APP_ORG_ID }}
29 | apiUrl: ${{ vars.CONTRAST_GITHUB_APP_TS_URL }}
30 | repoUrl: ${{ github.server_url }}/${{ github.repository }}
31 | repoName: ${{ github.repository }}
32 | externalId: ${{ vars.CONTRAST_GITHUB_APP_ID }}
33 | command: fingerprint
34 | outputs:
35 | fingerprint: ${{ steps.fingerprint.outputs.fingerprint }}
36 | analyze_dependencies:
37 | if: ${{ needs.fingerprint_repo.outputs.fingerprint != '' }}
38 | needs: fingerprint_repo
39 | runs-on: ubuntu-22.04
40 | strategy:
41 | fail-fast: false
42 | matrix:
43 | manifest:
44 | - ${{ fromJson(needs.fingerprint_repo.outputs.fingerprint) }}
45 | steps:
46 | - name: Clone repository
47 | uses: actions/checkout@v3
48 | - name: Run Contrast SCA Audit
49 | uses: 'Contrast-Security-OSS/contrast-sca-action@v2'
50 | with:
51 | apiKey: ${{ secrets.CONTRAST_GITHUB_APP_API_KEY }}
52 | authHeader: ${{ secrets.CONTRAST_GITHUB_APP_AUTH_HEADER }}
53 | orgId: ${{ vars.CONTRAST_GITHUB_APP_ORG_ID }}
54 | apiUrl: ${{ vars.CONTRAST_GITHUB_APP_TS_URL }}
55 | filePath: ${{ matrix.manifest.filePath }}
56 | repositoryId: ${{ matrix.manifest.repositoryId }}
57 | projectGroupId: ${{ matrix.manifest.projectGroupId }}
58 |
--------------------------------------------------------------------------------
/HeadlessExample.2021/Program.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | //
4 | // --------------------------------------------------------------------------------------------------------------------
5 | namespace HeadlessExample
6 | {
7 | using System;
8 | using System.IO;
9 | using System.Reflection;
10 |
11 | using Tekla.Structures.Model;
12 | using Tekla.Structures.Service;
13 |
14 | class Program
15 | {
16 | ///
17 | /// Main entry point
18 | ///
19 | /// additional version field: Ex: HeadlessExample.2021.exe 2021.0 for running example against 2021 version of ts
20 | static void Main(string[] args)
21 | {
22 | // default ts to use. change to 2021 as example.
23 | var tsVersion = "2022.0";
24 | if (args.Length != 0)
25 | {
26 | tsVersion = args[0];
27 | }
28 |
29 | var binDir = $@"C:\Program Files\Tekla Structures\{tsVersion}\bin";
30 | if (tsVersion.Equals("2021.0"))
31 | {
32 | // backwards compitbility
33 | binDir = $@"C:\Program Files\Tekla Structures\{tsVersion}\nt\bin";
34 | }
35 |
36 | ConfigureHeadlessIniFiles(binDir);
37 |
38 | AppDomain.CurrentDomain.AssemblyResolve += (s, a) => CurrentDomainAssemblyResolve(a, binDir);
39 | // TeklaStructuresService needs to know the location of the TS binaries.
40 | // additionally we need to set a resolver to load dlls from binary folder
41 | using (var service = new TeklaStructuresService(
42 | new DirectoryInfo(binDir),
43 | "ENGLISH",
44 | new FileInfo($@"C:\ProgramData\Trimble\Tekla Structures\{tsVersion}\Environments\default\env_Default_environment.ini"),
45 | new FileInfo($@"C:\ProgramData\Trimble\Tekla Structures\{tsVersion}\Environments\default\role_Steel_Detailer.ini")))
46 | {
47 | // change for model path
48 | var modelPath = @"C:\TeklaStructuresModels\New model";
49 | // see Initialize for role, license and identity
50 | service.Initialize(new DirectoryInfo(modelPath));
51 |
52 | //!IMPORTANT NOTICE!
53 | //!IMPORTANT NOTICE!
54 | //!IMPORTANT NOTICE!
55 | //You cannot run the above code when in debugger.
56 | //You can add a ReadKey here, so you can attach debugger to be able to debug your own code.
57 | //Console.ReadKey();
58 |
59 | // at this point we can call TeklaOpen api to do TS operations
60 | Console.WriteLine("ProjectInfo.Name : " + new Model().GetProjectInfo().Name);
61 | Console.WriteLine("ProjectInfo.Description : " + new Model().GetProjectInfo().Description);
62 | } // service must be disposed so that a clean exit is done. Once disposed, it cannot be used again during the process lifetime.
63 | }
64 |
65 | ///
66 | /// Helpers function to set need patching for licensing or any other things required
67 | ///
68 | ///
69 | private static void ConfigureHeadlessIniFiles(string binDir)
70 | {
71 | var licenseServer = "27001@yourserver";
72 | var runPath = @"C:\TeklaStructuresModels\RunPath";
73 | var overrideIniFile = Path.Combine(runPath, "TeklaStructures.ini");
74 | Directory.CreateDirectory(runPath);
75 | // Always make a copy of a main the ini file so we dont break TS installation.
76 | File.Copy(Path.Combine(binDir, "TeklaStructures.ini"), overrideIniFile, true);
77 | File.AppendAllText(overrideIniFile, $"\r\nset XS_LICENSE_SERVER_HOST={licenseServer}\r\n");
78 | File.AppendAllText(overrideIniFile, $"set XS_DEFAULT_LICENSE=Full\r\n");
79 |
80 | var envVar = Environment.GetEnvironmentVariable("TS_OVERRIDE_INI_FILE");
81 | if (envVar == null || !envVar.Equals(overrideIniFile))
82 | {
83 | throw new ArgumentException($"Please set TS_OVERRIDE_INI_FILE, before exec the program: set TS_OVERRIDE_INI_FILE={overrideIniFile}");
84 | }
85 | }
86 |
87 | ///
88 | /// assembly resolver - for loading dlls from bin without copying dlls into exectution path
89 | ///
90 | /// event args
91 | /// ts binary folder
92 | /// assembly to load
93 | private static System.Reflection.Assembly CurrentDomainAssemblyResolve(ResolveEventArgs args, string binDir)
94 | {
95 | var requestedAssembly = new AssemblyName(args.Name);
96 |
97 | if (File.Exists(Path.Combine(binDir, requestedAssembly.Name + ".dll")))
98 | {
99 | return System.Reflection.Assembly.LoadFile(Path.Combine(binDir, requestedAssembly.Name + ".dll"));
100 | }
101 |
102 | return null;
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------