<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Posts (de) | Ingenieurbüro Jan Böttcher</title>
    <link>https://www.ib-boettcher.de/de/post/</link>
      <atom:link href="https://www.ib-boettcher.de/de/post/index.xml" rel="self" type="application/rss+xml" />
    <description>Posts (de)</description>
    <generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>de-de</language><copyright>© Ingenieurbüro Jan Böttcher 2026</copyright><lastBuildDate>Fri, 26 Jun 2026 00:00:00 +0200</lastBuildDate>
    <image>
      <url>https://www.ib-boettcher.de/img/gear_hero_2020.png</url>
      <title>Posts (de)</title>
      <link>https://www.ib-boettcher.de/de/post/</link>
    </image>
    
    <item>
      <title>Der Prompt, den ich mir hätte sparen können</title>
      <link>https://www.ib-boettcher.de/de/post/about-ki/</link>
      <pubDate>Fri, 26 Jun 2026 00:00:00 +0200</pubDate>
      <guid>https://www.ib-boettcher.de/de/post/about-ki/</guid>
      <description>&lt;p&gt;Ich befinde mich, wie wohl viele, gerade in einer Ausprobierphase: Was kann KI? Wo liegen ihre Grenzen? Und wie lässt sich diese Technologie sinnvoll nutzen? Im Spannungsfeld zwischen erstaunlichen Ergebnissen und kaum weniger erstaunlichen Halluzinationen, zwischen Token-Kosten und dem möglichen Abfluss sensibler Informationen, ist es notwendig, eine eigene Strategie für den Umgang mit LLMs und Agenten zu entwickeln.&lt;/p&gt;
&lt;p&gt;Ein weiterer kleiner Punkt auf meiner Lessons-Learned-Liste kam letzte Woche dazu.&lt;/p&gt;
&lt;h3 id=&#34;die-aufgabe&#34;&gt;Die Aufgabe&lt;/h3&gt;
&lt;p&gt;Für eines meiner Programme musste ich die Testdokumentation für die manuellen Systemtests erstellen. Das Programm sammelt Passungsinformationen aus einer CAD-Zeichnung und erzeugt daraus eine Tabelle der Abmaße als Information für Fertigung und Qualitätskontrolle. Meine Testzeichnung enthält fünf Maße mit den Passungen 20 H7, 40 k6, 60 G7, 80 H8 und 80 f7. Für diese Maße sollten die zu erwartenden Programmergebnisse in der Testdokumentation tabelliert werden. Diese Fleißarbeit habe ich dann an die KI abgegeben.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Erzeuge mir eine Tabelle im Markdown-Format, die die oberen und unteren Abmaße für die Nennmaße und Toleranzen 20 H7, 40 k6, 60 G7, 80 h8 [sic!] und 80 f7 auflistet.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;GPT-5.4 mini&lt;/em&gt; lieferte das Ergebnis schnell, schön formatiert und leider falsch.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hier ist eine Markdown-Tabelle mit den oberen und unteren Abmaßen für die genannten Nennmaße und Toleranzen:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;Nennmaß&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;Toleranzlage&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;Toleranzgrad&lt;/th&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;Untermaß [mm]&lt;/th&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;Obermaß [mm]&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;20&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;H&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;7&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;0,000&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;+0,021&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;40&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;k&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;6&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;+0,010&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;+0,026&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;60&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;G&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;7&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;-0,015&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;+0,006&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;80&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;H&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;8&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;0,000&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;+0,046&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;80&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;f&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;7&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;-0,071&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;-0,030&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Wenn du möchtest, kann ich dir auch noch die zugehörigen Grenzmaße (oberes/unteres Grenzmaß) berechnen und ergänzen.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Die richtigen Werte für diese Passungen habe ich dann doch noch einmal selbst ganz konventionell ermittelt:&lt;/p&gt;
&lt;blockquote&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;Nennmaß&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;Toleranzlage&lt;/th&gt;
          &lt;th style=&#34;text-align: center&#34;&gt;Toleranzgrad&lt;/th&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;Unteres Abmaß&lt;/th&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;Oberes Abmaß&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;20&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;H&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;7&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;0,000 mm&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;+0,021 mm&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;40&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;k&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;6&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;+0,002 mm&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;+0,018 mm&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;60&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;G&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;7&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;0,010 mm&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;0,040 mm&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;80&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;H&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;8&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;0,000 mm&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;+0,046 mm&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;80&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;f&lt;/td&gt;
          &lt;td style=&#34;text-align: center&#34;&gt;7&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;-0,060 mm&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;-0,030 mm&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/blockquote&gt;
&lt;p&gt;Fairerweise muss man zugeben, dass diese Aufgabe nicht trivial ist. Die korrekten Werte sind nicht fix, sondern werden mittels Tabellen nach einem in einer Norm festgelegten Schema bestimmt &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;. Mit &lt;em&gt;GPT-5.4 mini&lt;/em&gt; hatte ich außerdem ein Modell gewählt, das auf Größe und Geschwindigkeit optimiert ist.&lt;/p&gt;
&lt;h3 id=&#34;ein-modellvergleich&#34;&gt;Ein Modellvergleich&lt;/h3&gt;
&lt;p&gt;Ist ein leistungsfähigeres Modell die Lösung? In einem kleinen Ad-Hoc-Test habe ich die Aufgabe anderen Modellen &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; in der Cloud und lokal gestellt.&lt;/p&gt;
&lt;p&gt;Zwei Modelle haben dabei in meinen Augen auf ganz unterschiedliche Weise alles richtig gemacht. Das kleine &lt;em&gt;Claude Haiku&lt;/em&gt; hat mir mitgeteilt, dass es die Aufgabe nicht direkt lösen, mir aber den Lösungsweg aufzeigen könne. &lt;em&gt;Claude Sonnet 4.6&lt;/em&gt; hat viele Tokens verbraucht und mir dann eine korrekte Tabelle inklusive vollständigem Lösungsweg zur Ermittlung aus den Norm-Tabellen präsentiert.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Llama 3&lt;/em&gt; hat unterhalb der generierten (falschen) Tabelle immerhin in einem Nachsatz erwähnt, dass es sich nur um Beispielwerte handelt.&lt;/p&gt;
&lt;p&gt;Alle anderen Modelle lieferten mir, mit mehr oder weniger Zusatztext, schlicht ein falsches Ergebnis.&lt;/p&gt;
&lt;div style=&#34;background-color:#f8f9fa; padding:1rem; border-radius:8px;&#34;&gt;
&lt;b&gt;Nachtrag:&lt;/b&gt; In einem kleinen Folgetest ein paar Tage später habe ich dem Überflieger der ersten Runde, &lt;i&gt;Claude Sonnet 4.6&lt;/i&gt;, noch einmal den gleichen Auftrag gegeben. Diesmal war das Ergebnis allerdings komplett falsch.&lt;/p&gt;
&lt;i&gt;Sometimes you are the windshield, sometimes you are the bug&lt;/i&gt;
&lt;/div&gt;
&lt;h3 id=&#34;die-erkenntnis&#34;&gt;Die Erkenntnis&lt;/h3&gt;
&lt;p&gt;Zurück zu meiner Testdokumentation. Ein falscher Zahlenwert dort führt spätestens beim ersten Systemtest zu zusätzlichem Aufwand für die Suche nach einem Programmfehler, den es gar nicht gibt. Die KI-Ergebnisse können also nicht ohne eine sorgfältige Prüfung verwendet werden. Diese Prüfung erfordert aber wiederum exakt die Arbeit, die eigentlich gespart werden sollte.&lt;/p&gt;
&lt;p&gt;Die für mich interessante Erkenntnis ist: Bei dieser Aufgabe lohnt es sich grundsätzlich nicht, sie an ein Sprachmodell zu delegieren. KI spart an dieser Stelle keine Zeit und verbessert auch die Qualität nicht. Selbst die Leistungsfähigkeit des Modells spielt dabei keine entscheidende Rolle. Der Aufwand zur Kontrolle der Ergebnisse ist immer der gleiche.&lt;/p&gt;
&lt;h3 id=&#34;eine-faustregel&#34;&gt;Eine Faustregel&lt;/h3&gt;
&lt;p&gt;Die gute Nachricht ist, dass sich solche Aufgaben vorab mit zwei Fragen identifizieren lassen:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ist es kritisch, wenn das Ergebnis falsch oder ungenau ist?&lt;/li&gt;
&lt;li&gt;Liegt der Aufwand zur Prüfung in der gleichen Größenordnung wie der Aufwand zur konventionellen Ermittlung des Ergebnisses?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Wenn beide Antworten ja lauten, besteht eine gute Chance, dass ein generalistisches Sprachmodell nicht das Werkzeug der Wahl ist.&lt;/p&gt;
&lt;p&gt;Meinen Ursprungsprompt hätte ich jedenfalls nach kurzem Nachdenken gar nicht absetzen müssen.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;
&lt;a href=&#34;https://de.wikipedia.org/wiki/Passung&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://de.wikipedia.org/wiki/Passung&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;GPT-5.4 mini, GPT-5.4, Claude Haiku 4.5, Claude Sonnet 4.5, Claude Sonnet 4.6, Llama 3 8B (lokal), Gemma 4 E4B (lokal).&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>NX Open in VS Code debuggen</title>
      <link>https://www.ib-boettcher.de/de/post/debug-vscode/</link>
      <pubDate>Wed, 06 Apr 2022 10:13:00 +0200</pubDate>
      <guid>https://www.ib-boettcher.de/de/post/debug-vscode/</guid>
      <description>&lt;h2&gt;Inhaltsverzeichnis&lt;/h2&gt;
&lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#hintergrund&#34;&gt;Hintergrund&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#voraussetzungen&#34;&gt;Voraussetzungen&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#anpassen-des-nx-open-projektes&#34;&gt;Anpassen des NX Open Projektes&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#erstellen-einer-startkonfiguration&#34;&gt;Erstellen einer Startkonfiguration&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#debuggen&#34;&gt;Debuggen&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;h2 id=&#34;hintergrund&#34;&gt;Hintergrund&lt;/h2&gt;
&lt;p&gt;In einem anderen 
&lt;a href=&#34;https://www.ib-boettcher.de/de/post/nxopen-vscode/&#34;&gt;Artikel&lt;/a&gt; hatte ich gezeigt, wie NX Open Programme mit dem Quellcodeeditor VS Code (Visual Studio Code) erstellt und kompiliert werden können&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Ein wichtiges Werkzeug bei der Programmentwicklung und Fehlersuche ist der Debugger. VS Code und die C# Erweiterung zielen in erster Linie auf .NET Core und nicht das .NET Framework, das für die NX Open Entwicklung benötigt wird. Dennoch lassen sich auch .NET Framework Applikationen debuggen&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h2 id=&#34;voraussetzungen&#34;&gt;Voraussetzungen&lt;/h2&gt;
&lt;p&gt;Das hier beschrieben Vorgehen ist nur zum Debuggen von kompilierten NX Open Applikationen geeignet. Ein Debuggen von Journalen&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; ist unter VS Code nicht möglich.&lt;/p&gt;
&lt;p&gt;Das Aufsetzen der Entwicklungsumgebung wird in &lt;sup id=&#34;fnref1:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; beschrieben.&lt;/p&gt;
&lt;h2 id=&#34;anpassen-des-nx-open-projektes&#34;&gt;Anpassen des NX Open Projektes&lt;/h2&gt;
&lt;p&gt;Zunächst muss das Projektfile &lt;em&gt;*.csproj&lt;/em&gt; angepasst werden. Es ist wichtig, dass als &lt;em&gt;PlatformTarget&lt;/em&gt; &lt;em&gt;x64&lt;/em&gt; angegeben ist und als &lt;em&gt;DebugType&lt;/em&gt; &lt;em&gt;portable&lt;/em&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;...
  &amp;lt;PropertyGroup Condition=&amp;quot; &#39;$(Configuration)|$(Platform)&#39; == &#39;Debug|x64&#39; &amp;quot;&amp;gt;
    &amp;lt;DebugSymbols&amp;gt;true&amp;lt;/DebugSymbols&amp;gt;
    &amp;lt;Optimize&amp;gt;false&amp;lt;/Optimize&amp;gt;
    &amp;lt;OutputPath&amp;gt;bin\Debug\&amp;lt;/OutputPath&amp;gt;
    &amp;lt;DefineConstants&amp;gt;DEBUG;TRACE&amp;lt;/DefineConstants&amp;gt;
    &amp;lt;ErrorReport&amp;gt;prompt&amp;lt;/ErrorReport&amp;gt;
    &amp;lt;WarningLevel&amp;gt;4&amp;lt;/WarningLevel&amp;gt;
    &amp;lt;Prefer32Bit&amp;gt;false&amp;lt;/Prefer32Bit&amp;gt;
    &amp;lt;PlatformTarget&amp;gt;x64&amp;lt;/PlatformTarget&amp;gt;&amp;lt;!-- To enable debugging with vs code--&amp;gt;
    &amp;lt;DebugType&amp;gt;portable&amp;lt;/DebugType&amp;gt;&amp;lt;!-- To enable debugging with vs code--&amp;gt;
 &amp;lt;/PropertyGroup&amp;gt;
...
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;erstellen-einer-startkonfiguration&#34;&gt;Erstellen einer Startkonfiguration&lt;/h2&gt;
&lt;p&gt;Zum Erstellen einer Debug-Konfiguration muss die Datei &lt;em&gt;launch.json&lt;/em&gt; um einen entsprechenden Eintrag erweitert werden. Falls diese Datei noch nicht existiert, muss sie im Verzeichnis &lt;em&gt;.vscode&lt;/em&gt; neu angelegt werden (siehe z.B. &lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;).&lt;/p&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/de/post/debug-vscode/launch_json_hu_9a52e1f0233ec1a8.jpg&#34; class=&#34;lazyload&#34; alt=&#34;&#34; width=&#34;835&#34; height=&#34;277&#34;&gt;



  
  
  &lt;figcaption&gt;
    Debugkonfiguration in launch.json.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
    &amp;quot;version&amp;quot;: &amp;quot;0.2.0&amp;quot;,
    &amp;quot;configurations&amp;quot;: [
        {
            &amp;quot;name&amp;quot;: &amp;quot;Attach to process&amp;quot;,
            &amp;quot;type&amp;quot;: &amp;quot;clr&amp;quot;,
            &amp;quot;request&amp;quot;: &amp;quot;attach&amp;quot;,
            &amp;quot;processId&amp;quot; : &amp;quot;${command:pickProcess}&amp;quot;
        }
    ],
    &amp;quot;compounds&amp;quot;: []
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;debuggen&#34;&gt;Debuggen&lt;/h2&gt;
&lt;p&gt;Zunächst wird NX regulär gestartet. Danach kann mit &lt;em&gt;F5&lt;/em&gt; die Debug-Sitzung in VS Code gestartet und der NX Prozess ausgewählt werden.&lt;/p&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/de/post/debug-vscode/f5_debug_hu_748bd823d34694f9.jpg&#34; class=&#34;lazyload&#34; alt=&#34;&#34; width=&#34;898&#34; height=&#34;474&#34;&gt;



  
  
  &lt;figcaption&gt;
    Debug-Sitzung starten
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;p&gt;Beim Ausführen der NX Open Applikation werden jetzt Break-Points angesprungen.&lt;/p&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/de/post/debug-vscode/debug_hu_671877b502080215.jpg&#34; class=&#34;lazyload&#34; alt=&#34;&#34; width=&#34;825&#34; height=&#34;502&#34;&gt;



  
  
  &lt;figcaption&gt;
    Breakpoint im Code.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;NX Open und VS Code: 
&lt;a href=&#34;https://www.ib-boettcher.de/de/post/nxopen-vscode/&#34;&gt;https://www.ib-boettcher.de/de/post/nxopen-vscode/&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref1:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;Desktop .NET Framework: 
&lt;a href=&#34;https://github.com/OmniSharp/omnisharp-vscode/wiki/Desktop-.NET-Framework&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://github.com/OmniSharp/omnisharp-vscode/wiki/Desktop-.NET-Framework&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;Der Begriff Journal wird im erweiterten Sinn häufig auch für NX Open-Programme allgemein verwendet. Hier sind aber ausschließlich in VB.NET oder C# realisierte Programme gemeint, die direkt als Quellcode ausgeführt werden.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;stackoverflow, feO2x: 
&lt;a href=&#34;https://stackoverflow.com/a/53271098&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://stackoverflow.com/a/53271098&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Langsame Journale?</title>
      <link>https://www.ib-boettcher.de/de/post/time-comp/</link>
      <pubDate>Fri, 14 May 2021 09:46:18 +0200</pubDate>
      <guid>https://www.ib-boettcher.de/de/post/time-comp/</guid>
      <description>&lt;h2&gt;Inhaltsverzeichnis&lt;/h2&gt;
&lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#hintergrund&#34;&gt;Hintergrund&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#testaufbau&#34;&gt;Testaufbau&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#ergebnisse&#34;&gt;Ergebnisse&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#fazit&#34;&gt;Fazit&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;p&gt;Ob ich bei der Umsetzung eines NX Zusatzprogramms auf ein Journal&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; oder eine compilierte Lösung setze, hängt von  vielen verschiedenen Faktoren ab. Falls eine bestimmte Programmiersprache für die Realisierung vorgesehen ist, besteht unter Umständen keine Wahl. C/C++ und Java müssen immer compiliert werden. Pythonprogramme liegen immer als Skript vor.&lt;/p&gt;
&lt;p&gt;Die .NET Sprachen C# und VB.NET können in NX sowohl compiliert als auch uncompiliert zum Einsatz kommen. Hier kann das Antwortverhalten und die Ablaufgeschwindigkeit ein wichtiger Faktor für die Auswahl der einen oder anderen Variante sein. Es ist naheliegend, dass compilierte .NET Programme einen Geschwindigkeitsvorteil besitzen. Wie groß ist dieser Unterschied jedoch tatsächlich? Welchen Auswirkung hat er in der Praxis?&lt;/p&gt;
&lt;h2 id=&#34;hintergrund&#34;&gt;Hintergrund&lt;/h2&gt;
&lt;p&gt;Uncompilierte .NET NX Open Journale werden nicht zur Laufzeit interpretiert. Der Quellcode wird bei jedem Aufruf des Journals mit dem im .NET Framework standardmäßig vorhandenen Compiler übersetzt, geladen und dann regulär ausgeführt. Während des Programmlaufes kann man das entsprechende Assembly unter dem Namen &lt;em&gt;journal.dll&lt;/em&gt; im von NX verwendeten temporären Verzeichnis finden. Nach Abschluss des Programmlaufes wird diese dll jedesmal durch NX gelöscht.&lt;/p&gt;
&lt;p&gt;Für die Ausführungsgeschwindigkeit des eigentlichen Programminhaltes bedeutet das interessanterweise, dass compilierte Programme keinen Vorteil gegenüber uncompiliert vorliegenden Journalen haben können. In der Gesamtbilanz kommt jedoch bei den Journalen der Overhead zur internen Compilierung hinzu. Dieser Overhead vergrößert die Antwortzeit der Applikation nach dem Start.&lt;/p&gt;
&lt;p&gt;Ein weiterer Aspekt muss bei der Betrachtung zusätzlich berücksichtigt werden. Bei compilierten Programmen kann die Entladeoption für das Assembly festgelegt werden (&lt;em&gt;Immediately&lt;/em&gt;, &lt;em&gt;At Termination&lt;/em&gt;, &lt;em&gt;Explicitly&lt;/em&gt;). Bei Journalen wird diese Option im Quelltext ignoriert. Die Assemblys von Journalen werden nach dem Programmende immer entladen (&lt;em&gt;Immediately&lt;/em&gt;). Compilierte Programme können also bei Bedarf davon profitieren, dass NX die Assemblys für eine erneute Ausführung im Speicher vorhält.&lt;/p&gt;
&lt;h2 id=&#34;testaufbau&#34;&gt;Testaufbau&lt;/h2&gt;
&lt;p&gt;Da, wie gezeigt, für die Fragestellung nur der Overhead zum Compilieren und das Entladeverhalten relevant sind, kann ein sehr einfaches Testprogramm verwendet werden. Es enthält lediglich die Ausgabe eines Markers in die NX-Logdatei.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-csharp&#34;&gt;using NXOpen;
using System;

public class SmallUi
{
    public static int Main(string[] args)
    {
        int retValue = 0;

        Session.GetSession().LogFile.WriteLine(&amp;quot;%%%SUI&amp;quot;);

        return retValue;
    }

    public static int GetUnloadOption(string arg)
    {
        return System.Convert.ToInt32(Session.LibraryUnloadOption.Immediately);
    }


}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Um den Einfluss der Quelltextgröße festzustellen wurde ein weiteres Programm erstellt, das vom ausgeführten Inhalt her dem ersten entspricht. Zusätzlich wurde der Quellcode eines mittelgroßen realen Projektes so hinzugefügt, dass er zwar mitcompiliert, aber nicht ausgeführt wird. Entstanden ist dabei eine Quellcodedatei mit rund 2700 Zeilen.&lt;/p&gt;
&lt;p&gt;Von beiden Programmen wurde je eine Variante mit der Entladeoption &lt;em&gt;Immediately&lt;/em&gt; (direkt nach Programmende)  und &lt;em&gt;At Termination&lt;/em&gt; (beim Beenden von NX) erstellt, compiliert und mit der Authoring-Lizenz signiert. Die Quellcodes des kurzen und des langen Programmes können zudem direkt als Journale ausgeführt werden. Damit ergeben sich insgesamt 6 zu testende Varianten:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SUI: Kurzes Programm, compiliert, Entladen direkt nach Programmende&lt;/li&gt;
&lt;li&gt;SUAT: Kurzes Programm, compiliert, Entladen beim Beenden von NX&lt;/li&gt;
&lt;li&gt;SUIJ: Kurzes Programm, Ausführung als Journal&lt;/li&gt;
&lt;li&gt;BUI: Langes Programm, compiliert, Entladen direkt nach Programmende&lt;/li&gt;
&lt;li&gt;BUAT: Langes Programm, compiliert, Entladen beim Beenden von NX&lt;/li&gt;
&lt;li&gt;BUIJ: Langes Programm, Ausführung als Journal&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Um die Laufzeit der verschiedenen Programme zu ermitteln, dient zusätzlich ein kleines Programm das lediglich einen Zeitstempel in die NX Log-Datei schreibt.
Weiterhin wurde eine MenuScript-Datei (.men) erstellt, die für jede der genannten 6 Varianten einen Action Button mit einer aufeinderfolgenden Folge von Aktionen in NX erzeugt.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;...
BUTTON SMALLUI
LABEL Small UI
ACTIONS ${mypath}time\application\time.dll
ACTIONS ${mypath}time\application\time.dll
ACTIONS ${mypath}time\application\time.dll
ACTIONS ${mypath}time\application\time.dll
ACTIONS ${mypath}time\application\small_ui.dll
ACTIONS ${mypath}time\application\time.dll
ACTIONS ${mypath}time\application\time.dll
ACTIONS ${mypath}time\application\time.dll
ACTIONS ${mypath}time\application\time.dll
ACTIONS ${mypath}time\application\time.dll
ACTIONS ${mypath}time\application\small_ui.dll
ACTIONS ${mypath}time\application\time.dll
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Auf diese Weise werden die einzelnen Programme auf einen Kopfdruck unmittelbar hintereinander durch NX ausgeführt. Zur Auswertung können die Zeitstempel und die Marker der eigentlichen Programme aus der Logdatei ausgelesen werden. Aus dem Abstand zweier einen Marker umschließender Zeitstempel abzüglich des Abstands zweier direkt aufeinander folgender Zeitstempel kann die tatsächliche Laufzeit der zu testenden Variante ermittelt werden.
In ersten Versuchen zeigte sich, dass immer wieder Ausreißer bei der Laufzeit des Zeitstempelprogrammes auftraten. Deshalb wird das Zeitstempel-Programm mehrfach hintereinander aufgerufen und zur Berechnung der Laufzeiten der eigentlichen Programme der Median verwendet.&lt;/p&gt;
&lt;p&gt;Für jede der 6 Programmvarianten wurden 9 Läufe mit einem jeweils neu gestartetem NX durchgeführt. Die Laufzeiten für den ersten und den zweiten Programmaufruf ergeben sich wiederum aus dem Median dieser 9 Läufe.
Die ermittelten Werte sind ein Maß für das Antwortverhalten der verschiedenen Varianten.&lt;/p&gt;
&lt;p&gt;Die Tests wurden unter NX1953 auf einer älteren Workstation mit Xeon CPU durchgeführt. Die Ergebnisse sind nur qualitativ auf andere Systeme übertragbar.&lt;/p&gt;
&lt;h2 id=&#34;ergebnisse&#34;&gt;Ergebnisse&lt;/h2&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/de/post/time-comp/ShortPrg_hu_ad2f81456851901a.png&#34; class=&#34;lazyload&#34; alt=&#34;&#34; width=&#34;640&#34; height=&#34;480&#34;&gt;



  
  
  &lt;figcaption&gt;
    Laufzeiten der kurzen Programmvarianten.&lt;br/&gt;SUI: compiliert, Entladen direkt nach Programmende.&lt;br/&gt;SUAT: compiliert, Entladen beim Beenden von NX.&lt;br/&gt;SUIJ: Ausführung als Journal.&lt;br/&gt;(1): erster Programmlauf, (2): zweiter Programmlauf.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;p&gt;Die Abbildung zeigt die Ergebnisse für die kurze Programmvarianten. Die vollständige Laufzeit beträgt für die compilierten Varianten knapp 0,6 Sekunden beim ersten Start (&lt;em&gt;SUI (1)&lt;/em&gt;, &lt;em&gt;SUAT (1)&lt;/em&gt;). Beim zweiten Start ist die Laufzeit auf rund 0,2 Sekunden reduziert, wenn die dll vorher nicht entladen wurde (&lt;em&gt;SUAT (2)&lt;/em&gt;). Wurde die dll entladen (&lt;em&gt;SUI (2)&lt;/em&gt;), entspricht die Laufzeit der des Erststarts.
Die Journal-Varianten (&lt;em&gt;SUIJ (1)&lt;/em&gt;, &lt;em&gt;SUIJ (2)&lt;/em&gt;)  haben eine deutlich längere Laufzeit von rund 1,2 Sekunden. Der zweite Lauf ist geringfügig schneller als der erste.&lt;/p&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/de/post/time-comp/LongPrg_hu_e16559d9b87e90d3.png&#34; class=&#34;lazyload&#34; alt=&#34;&#34; width=&#34;640&#34; height=&#34;480&#34;&gt;



  
  
  &lt;figcaption&gt;
    Laufzeiten der langen Programmvarianten.&lt;br/&gt;BUI: compiliert, Entladen direkt nach Programmende.&lt;br/&gt;BUAT: compiliert, Entladen beim Beenden von NX.&lt;br/&gt;BUIJ: Ausführung als Journal.&lt;br/&gt;(1): erster Programmlauf, (2): zweiter Programmlauf.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;p&gt;Die Abbildung zeigt die Ergebnisse für die lange Programmvariante. Auch hier beträgt die Laufzeit für die compilierten Varianten knapp 0,6 Sekunden beim ersten Start (&lt;em&gt;BUI (1)&lt;/em&gt;, &lt;em&gt;BUAT (1)&lt;/em&gt;) und 0,2 Sekunden beim zweiten Start, wenn die dll vorher nicht entladen wurde (&lt;em&gt;BUAT (2)&lt;/em&gt;). Das uncompilierte Journal (&lt;em&gt;BUIJ&lt;/em&gt;) hat mit 1,4 Sekunden eine etwas längere Laufzeit als die kurze Version.&lt;/p&gt;
&lt;h2 id=&#34;fazit&#34;&gt;Fazit&lt;/h2&gt;
&lt;p&gt;Insgesamt zeigen die Messungen kein Überraschungen. Uncompilierte Journale benötigen für den Start und das Beenden deutlich mehr Zeit als ihre compilierten Gegenstücke. Idealerweise beträgt die Antwortzeit auf eine Benutzerinteraktion weniger als eine Sekunde (siehe z.B. &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; oder &lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;). Die compilierten Programme liegen alle deutlich unter dieser Marke. Journale zeigen ein schlechteres Antwortverhalten. Die Werte sind allerdings nicht so hoch, dass der Arbeitsfluss unterbrochen wird.&lt;/p&gt;
&lt;p&gt;Der Einfluss der Quellcodegröße auf die Startdauer der Programme ist compiliert wie uncompiliert gering.&lt;/p&gt;
&lt;p&gt;Hinsichtlich der Ablaufgeschwindigkeit des eigentlichen Programminhaltes gibt es keinen Unterschied zwischen compilierten und uncompilierten Applikationen.&lt;/p&gt;
&lt;p&gt;Wenn die Responsivität eine sehr große Rolle spielt, dann sind compilierte NX Open .NET Applikationen vorzuziehen. In allen anderen Fällen können durchaus auch Journale verwendet werden.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Der Begriff Journal wird im erweiterten Sinn häufig auch für NX Open-Programme allgemein verwendet. Hier sind aber ausschließlich in VB.NET oder C# realisierte Programme gemeint, die direkt als Quellcode ausgeführt werden.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;Michael Herczeg, Software-Ergonomie, Addison-Wessley 1994, S.203&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;
&lt;a href=&#34;https://developer.gnome.org/hig-book/unstable/feedback-response-times.html.en&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://developer.gnome.org/hig-book/unstable/feedback-response-times.html.en&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>QR-Code Annotations erzeugen (Beispiel)</title>
      <link>https://www.ib-boettcher.de/de/post/qr-python/</link>
      <pubDate>Fri, 21 Aug 2020 08:46:18 +0200</pubDate>
      <guid>https://www.ib-boettcher.de/de/post/qr-python/</guid>
      <description>&lt;h2&gt;Inhaltsverzeichnis&lt;/h2&gt;
&lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#hintergrund&#34;&gt;Hintergrund&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#voraussetzungen&#34;&gt;Voraussetzungen&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#implementierung&#34;&gt;Implementierung&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;h2 id=&#34;hintergrund&#34;&gt;Hintergrund&lt;/h2&gt;
&lt;p&gt;QR-Codes werden häufig eingesetzt um Informationen fehlertolerant maschinenlesbar anzubringen. NX bietet (derzeit) nur die Möglichkeit über einen speziellen Zeichensatz eindimensionale Strichcodes als Hinweise (Annotations) zu erzeugen. Hier soll nun gezeigt werden, wie mittels eines NX Open Journals in Python QR-Codes auf einfache Weise eingefügt werden können.&lt;/p&gt;
&lt;h2 id=&#34;voraussetzungen&#34;&gt;Voraussetzungen&lt;/h2&gt;
&lt;p&gt;Für die Kodierung des Inhaltes wird das Pythonpaket &lt;em&gt;qrcode&lt;/em&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; benötigt. Außerdem muß die Systemschriftart &lt;em&gt;Courier New&lt;/em&gt; vorhanden sein.&lt;/p&gt;
&lt;h2 id=&#34;implementierung&#34;&gt;Implementierung&lt;/h2&gt;
&lt;p&gt;Wird für die Erzeugung der Annotation eine nichtproportionale Schriftart gewählt, dann kann der Text zeilenweise aus Leerzeichen und einem quadratischen Symbol (hier &lt;em&gt;Courier New, Geometric Shapes, Black Square&lt;/em&gt;) zusammengesetzt werden. Die Punktmatrix dafür kann mittels der Methode &lt;em&gt;get_matrix&lt;/em&gt; der Klasse &lt;em&gt;qrcode.QRCode&lt;/em&gt; aus dem zu codierenden Inhalt ermittelt werden.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-python&#34;&gt;&amp;quot;&amp;quot;&amp;quot;
Create QR Code Annotations in NX Example
Author: Jan Boettcher, www.ib-boettcher.de, 2020
&amp;quot;&amp;quot;&amp;quot;
import qrcode
import NXOpen
import NXOpen.Annotations
import NXOpen.Drawings
import NXOpen.UF

def main():
    &amp;quot;&amp;quot;&amp;quot;
    Main task.
    &amp;quot;&amp;quot;&amp;quot;
    session: NXOpen.Session = NXOpen.Session.GetSession()
    work_part: NXOpen.Part = session.Parts.Work

    do_continue = True
    if work_part is None:
        NXOpen.UI.GetUI().NXMessageBox.Show(
            &amp;quot;nxqr&amp;quot;, NXOpen.NXMessageBox.DialogType.Error, &amp;quot;No work part.&amp;quot;
            )
        do_continue = False
    if do_continue:
        do_continue, text = get_text()   
    if do_continue:
        do_continue, position = pick_position()
    if do_continue:
        matrix = create_qr_matrix(text)
        text_array = create_nx_text(matrix)
        font_index = add_font(work_part)
        qr_prefs = {
            &amp;quot;GeneralTextFont&amp;quot;: font_index,
            &amp;quot;GeneralTextLineSpacFactor&amp;quot;: 0.00001,
            &amp;quot;GeneralTextSize&amp;quot;: 1.0,
            &amp;quot;GeneralTextAspectRatio&amp;quot;: 1.0,
        }
        old_prefs = switch_prefs(work_part, qr_prefs)
        create_annotation(work_part, position, text_array)
        switch_prefs(work_part, old_prefs)

def create_annotation(part, position, text_array):
    &amp;quot;&amp;quot;&amp;quot;
    Create the annotation.
    &amp;quot;&amp;quot;&amp;quot;
    drafting_note_builder = part.Annotations.CreateDraftingNoteBuilder(
        NXOpen.Annotations.SimpleDraftingAid.Null
        )
    drafting_note_builder.Origin.Origin.SetValue(
        NXOpen.TaggedObject.Null, NXOpen.View.Null, position
        ) 
    drafting_note_builder.Origin.SetInferRelativeToGeometry(False)
    drafting_note_builder.Text.TextBlock.SetText(text_array)
    drafting_note_builder.Commit()
    drafting_note_builder.Destroy()


def add_font(part: NXOpen.Part):
    &amp;quot;&amp;quot;&amp;quot;
    Add font for annotation.
    &amp;quot;&amp;quot;&amp;quot;
    courier_index = part.Fonts.AddFont(
        &amp;quot;Courier New&amp;quot;, NXOpen.FontCollection.Type.Standard
        )
    return courier_index


def switch_prefs(part, prefs):
    &amp;quot;&amp;quot;&amp;quot;
    Store current annotation preferences and set some new.
    &amp;quot;&amp;quot;&amp;quot;
    pref_builder = part.SettingsManager.CreatePreferencesBuilder()

    annotation_style = pref_builder.AnnotationStyle
    lettering_style = annotation_style.LetteringStyle
    old_prefs = {
        &amp;quot;GeneralTextFont&amp;quot;: lettering_style.GeneralTextFont,
        &amp;quot;GeneralTextLineSpacFactor&amp;quot;: lettering_style.GeneralTextLineSpaceFactor,
        &amp;quot;GeneralTextSize&amp;quot;: lettering_style.GeneralTextSize,
        &amp;quot;GeneralTextAspectRatio&amp;quot;: lettering_style.GeneralTextAspectRatio,
    }
    lettering_style.GeneralTextFont  = prefs[&amp;quot;GeneralTextFont&amp;quot;]
    lettering_style.GeneralTextLineSpaceFactor = prefs[&amp;quot;GeneralTextLineSpacFactor&amp;quot;]
    lettering_style.GeneralTextSize = prefs[&amp;quot;GeneralTextSize&amp;quot;]
    lettering_style.GeneralTextAspectRatio = prefs[&amp;quot;GeneralTextAspectRatio&amp;quot;]
    pref_builder.Commit()
    pref_builder.Destroy()

    return old_prefs


def pick_position():
    &amp;quot;&amp;quot;&amp;quot;
    Ask user to pick a position.
    &amp;quot;&amp;quot;&amp;quot;
    response, view, point = NXOpen.UI.GetUI().SelectionManager.SelectScreenPosition(
        &amp;quot;Pick QR Position&amp;quot;
        )
    do_continue = response == NXOpen.Selection.DialogResponse.Pick
    return do_continue, point

def get_text():
    &amp;quot;&amp;quot;&amp;quot;
    Ask user for QR content.
    &amp;quot;&amp;quot;&amp;quot;
    message = &amp;quot;Enter Text&amp;quot;
    text = &amp;quot;Some Text&amp;quot;
    uf_session = NXOpen.UF.UFSession.GetUFSession()
    uf_session.Ui.LockUgAccess(NXOpen.UF.UFConstants.UF_UI_FROM_CUSTOM)
    text, length, response = uf_session.Ui.AskStringInput(message, text)
    uf_session.Ui.UnlockUgAccess(NXOpen.UF.UFConstants.UF_UI_FROM_CUSTOM)
    do_continue = response == 5 or response == 3
    return do_continue, text
   
def create_qr_matrix(text):
    &amp;quot;&amp;quot;&amp;quot;
    Create the QR Code matrix.
    &amp;quot;&amp;quot;&amp;quot;
    qr = qrcode.QRCode(
        version=None
    )
    qr.add_data(text)
    qr.make(fit=True)
    matrix = qr.get_matrix()
    return matrix

def create_nx_text(matrix):
    &amp;quot;&amp;quot;&amp;quot;
    Create annotation text from matrix.
    &amp;quot;&amp;quot;&amp;quot;
    text_array = []
    for row in matrix:
        text = &amp;quot;&amp;quot;
        for dot in row:
            if dot == True:
                text = text + &amp;quot;\u25A0&amp;quot;
            else :
                text = text + &amp;quot; &amp;quot;
        
        text_array.append(text)
    return text_array

if __name__ == &#39;__main__&#39;:
    main()

&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;qrcode on pypi.org (
&lt;a href=&#34;https://pypi.org/project/qrcode/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://pypi.org/project/qrcode/&lt;/a&gt;)&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>NX Open und VS Code</title>
      <link>https://www.ib-boettcher.de/de/post/nxopen-vscode/</link>
      <pubDate>Fri, 03 Jul 2020 08:46:18 +0200</pubDate>
      <guid>https://www.ib-boettcher.de/de/post/nxopen-vscode/</guid>
      <description>&lt;h2&gt;Inhaltsverzeichnis&lt;/h2&gt;
&lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#hintergrund&#34;&gt;Hintergrund&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#voraussetzungen&#34;&gt;Voraussetzungen&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#nx-open-projekte-aufsetzen&#34;&gt;NX Open Projekte aufsetzen&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#kompilieren&#34;&gt;Kompilieren&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#fazit&#34;&gt;Fazit&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;h2 id=&#34;hintergrund&#34;&gt;Hintergrund&lt;/h2&gt;
&lt;p&gt;Üblicherweise werden NX Open-Applikationen in C# mit Microsofts Visual Studio erstellt. NX bringt Wizards zum bequemen Aufsetzen von entsprechenden Projekten mit. Wer jedoch nicht auf diese Entwicklungsumgebung zurückgreifen kann oder will, der hat mit dem quelloffenen VS Code (Visual Studio Code) eine gute Alternative.&lt;br&gt;
Abgesehen vom Namen und vom Hersteller haben diese beiden Tools nur begrenzte Gemeinsamkeiten. VS Code ist in erster Linie ein Quellcodeeditor&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;br&gt;
Für kleine und mittlere NX Open Projekte ist jedoch das Wesentliche dabei. Insbesondere die IntelliSense-Funktionalität, die für ein produktives Arbeiten mit den zahlreichen Klassen und Methoden der NX Open-API unentbehrlich ist, entspricht der von Visual Studio.&lt;/p&gt;
&lt;h2 id=&#34;voraussetzungen&#34;&gt;Voraussetzungen&lt;/h2&gt;
&lt;p&gt;Neben dem eigentlichen Programm sind für die Verwendung von VS Code als Entwicklungsumgebung für NX Open-Applikationen noch zusätzliche Komponenten notwendig. Die jeweils benötigte Version dieser Komponenten hängt wesentlich von der NX-Zielversion ab. Im hier vorgestellten Beispiel ist die Zielversion NX 1899. Alle neben NX notwendigen Bestandteile sind kostenfrei verfügbar.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NX 1899 inkl. &lt;em&gt;Programming Tools&lt;/em&gt; Feature&lt;/li&gt;
&lt;li&gt;.NET Framework 4.6.2 Developer Pack&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;Visual Studio Code&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;C# for Visual Studio Code (VS Code Erweiterung)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Wenn nicht nur unkompilierte Journale erstellt werden sollen, dann muss zusätzlich der Compiler installiert werden:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;.NET Desktop-Buildtools (Bestandteil der Buildtools für Visual Studio 2019&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;). Von den optionalen Komponenten sollten mindesten die .NET Framework 4.6.2-Enwicklungstools installiert werden.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Details zur Verwendung von VS Code finden sich z.B. hier&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;.
Die C# Erweiterung für VS Code kann aus dem Programm heraus installiert werden.&lt;/p&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/de/post/nxopen-vscode/csharp_for_vscode_hu_140a93ee4972f581.jpg&#34; class=&#34;lazyload&#34; alt=&#34;&#34; width=&#34;560&#34; height=&#34;335&#34;&gt;



  
  
  &lt;figcaption&gt;
    C# Erweiterung installieren.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;p&gt;VS Code und die C# Erweiterung zielen in erster Linie auf .NET Core und nicht das .NET Framework, das hier für die NX Open Entwicklung benötigt wird. Entsprechend erscheint unter Umständen eine Meldung, die auf das Fehlen des .NET Core SDKs hinweist. Diese Meldung kann ignoriert oder unterdrückt werden.&lt;/p&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/de/post/nxopen-vscode/core_sdk_hu_8e516ba203b28a57.jpg&#34; class=&#34;lazyload&#34; alt=&#34;&#34; width=&#34;448&#34; height=&#34;131&#34;&gt;



  
  
  &lt;figcaption&gt;
    Die Meldung zum .NET Core SDK kann ignoriert werden.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;p&gt;Weiterhin sollte bei der Verwendung von VS Code für die NX Open Entwicklung die Umgebungsvariable &lt;em&gt;UGII_BASE_DIR&lt;/em&gt; gesetzt sein. Dies kann über ein kleines Startskript geschehen. Hier kann auch gleich der Pfad zu den Buildtools zur &lt;em&gt;PATH&lt;/em&gt; Variable hinzugefügt werden, falls nicht nur unkompilierte Journale erstellt werden sollen.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rem Set NX base path
set &amp;quot;UGII_BASE_DIR=c:\nx\NX 1899&amp;quot;
rem Add compiler path
set &amp;quot;PATH=C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin;%PATH%&amp;quot;
rem Run VS Code
code 
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&#34;nx-open-projekte-aufsetzen&#34;&gt;NX Open Projekte aufsetzen&lt;/h2&gt;
&lt;p&gt;Zunächst muss für das Projekt ein neues Verzeichnis an beliebiger Stelle erzeugt und dieses Verzeichnis in VS Code geöffnet werden. Das kann in einem Schritt über &lt;em&gt;File/Open Folder&amp;hellip;&lt;/em&gt; und das entsprechende Kontextmenü geschehen.&lt;/p&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/de/post/nxopen-vscode/create_project_dir_hu_a6f661fb7ff9f403.jpg&#34; class=&#34;lazyload&#34; alt=&#34;&#34; width=&#34;742&#34; height=&#34;522&#34;&gt;



  
  
  &lt;figcaption&gt;
    Projektverzeichnis anlegen und öffnen.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;p&gt;Das für ein funktionierendes IntelliSense und ein mögliches Kompilieren notwendige Projektfile muss per Hand angelegt werden.
Als Vorlage kann die Template-Datei des Wizards aus der NX-Installation dienen (&lt;em&gt;&amp;lt;UGII_BASE_DIR&amp;gt;\UGOPEN\vs_files\VC#\VC#Wizards\ NXOpen_VCS\Templates\1033\default_dll.csproj&lt;/em&gt;).
Die Erweiterung der neuen Datei muss &lt;em&gt;csproj&lt;/em&gt; lauten.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;Project DefaultTargets=&amp;quot;Build&amp;quot; xmlns=&amp;quot;http://schemas.microsoft.com/developer/msbuild/2003&amp;quot;&amp;gt;
  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;Configuration Condition=&amp;quot; &#39;$(Configuration)&#39; == &#39;&#39; &amp;quot;&amp;gt;Debug&amp;lt;/Configuration&amp;gt;
    &amp;lt;Platform Condition=&amp;quot; &#39;$(Platform)&#39; == &#39;&#39; &amp;quot;&amp;gt;x64&amp;lt;/Platform&amp;gt;
    &amp;lt;ProductVersion&amp;gt;8.0.50727&amp;lt;/ProductVersion&amp;gt;
    &amp;lt;SchemaVersion&amp;gt;2.0&amp;lt;/SchemaVersion&amp;gt;
    &amp;lt;!-- You may want to make this GUID unique --&amp;gt;
    &amp;lt;ProjectGuid&amp;gt;{ECAB86B8-89C2-4806-B397-C2B07638CFXX}&amp;lt;/ProjectGuid&amp;gt;
    &amp;lt;!-- Use &#39;library&#39; for internal NX Open program and &#39;exe&#39; for external --&amp;gt;
    &amp;lt;OutputType&amp;gt;library&amp;lt;/OutputType&amp;gt;
    &amp;lt;AppDesignerFolder&amp;gt;Properties&amp;lt;/AppDesignerFolder&amp;gt;
    &amp;lt;RootNamespace&amp;gt;&amp;lt;/RootNamespace&amp;gt;
    &amp;lt;!-- Enter name of the compiled dll/exe --&amp;gt;
    &amp;lt;AssemblyName&amp;gt;nx_project&amp;lt;/AssemblyName&amp;gt;
    &amp;lt;!-- Enter target framework --&amp;gt;
    &amp;lt;TargetFrameworkVersion&amp;gt;v4.6.2&amp;lt;/TargetFrameworkVersion&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;
  &amp;lt;PropertyGroup Condition=&amp;quot; &#39;$(Configuration)|$(Platform)&#39; == &#39;Debug|x64&#39; &amp;quot;&amp;gt;
    &amp;lt;DebugSymbols&amp;gt;true&amp;lt;/DebugSymbols&amp;gt;
    &amp;lt;DebugType&amp;gt;full&amp;lt;/DebugType&amp;gt;
    &amp;lt;Optimize&amp;gt;false&amp;lt;/Optimize&amp;gt;
    &amp;lt;OutputPath&amp;gt;bin\Debug\&amp;lt;/OutputPath&amp;gt;
    &amp;lt;DefineConstants&amp;gt;DEBUG;TRACE&amp;lt;/DefineConstants&amp;gt;
    &amp;lt;ErrorReport&amp;gt;prompt&amp;lt;/ErrorReport&amp;gt;
    &amp;lt;WarningLevel&amp;gt;4&amp;lt;/WarningLevel&amp;gt;
    &amp;lt;Prefer32Bit&amp;gt;false&amp;lt;/Prefer32Bit&amp;gt;
	&amp;lt;PlatformTarget&amp;gt;x64&amp;lt;/PlatformTarget&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;
  &amp;lt;PropertyGroup Condition=&amp;quot; &#39;$(Configuration)|$(Platform)&#39; == &#39;Release|x64&#39; &amp;quot;&amp;gt;
    &amp;lt;DebugType&amp;gt;pdbonly&amp;lt;/DebugType&amp;gt;
    &amp;lt;Optimize&amp;gt;true&amp;lt;/Optimize&amp;gt;
    &amp;lt;OutputPath&amp;gt;bin\Release\&amp;lt;/OutputPath&amp;gt;
    &amp;lt;DefineConstants&amp;gt;TRACE&amp;lt;/DefineConstants&amp;gt;
    &amp;lt;ErrorReport&amp;gt;prompt&amp;lt;/ErrorReport&amp;gt;
    &amp;lt;WarningLevel&amp;gt;4&amp;lt;/WarningLevel&amp;gt;
    &amp;lt;Prefer32Bit&amp;gt;false&amp;lt;/Prefer32Bit&amp;gt;
	&amp;lt;PlatformTarget&amp;gt;x64&amp;lt;/PlatformTarget&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;
  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;Reference Include=&amp;quot;NXOpen, Culture=neutral, processorArchitecture=MSIL&amp;quot;&amp;gt;
      &amp;lt;SpecificVersion&amp;gt;False&amp;lt;/SpecificVersion&amp;gt;
      &amp;lt;HintPath&amp;gt;$(UGII_BASE_DIR)\nxbin\managed\NXOpen.dll&amp;lt;/HintPath&amp;gt;
	  &amp;lt;Private&amp;gt;False&amp;lt;/Private&amp;gt;
    &amp;lt;/Reference&amp;gt;
    &amp;lt;Reference Include=&amp;quot;NXOpen.UF, Culture=neutral, processorArchitecture=MSIL&amp;quot;&amp;gt;
      &amp;lt;SpecificVersion&amp;gt;False&amp;lt;/SpecificVersion&amp;gt;
      &amp;lt;HintPath&amp;gt;$(UGII_BASE_DIR)\nxbin\managed\NXOpen.UF.dll&amp;lt;/HintPath&amp;gt;
	  &amp;lt;Private&amp;gt;False&amp;lt;/Private&amp;gt;
    &amp;lt;/Reference&amp;gt;
    &amp;lt;Reference Include=&amp;quot;NXOpen.Utilities, Culture=neutral, processorArchitecture=MSIL&amp;quot;&amp;gt;
      &amp;lt;SpecificVersion&amp;gt;False&amp;lt;/SpecificVersion&amp;gt;
      &amp;lt;HintPath&amp;gt;$(UGII_BASE_DIR)\nxbin\managed\NXOpen.Utilities.dll&amp;lt;/HintPath&amp;gt;
	  &amp;lt;Private&amp;gt;False&amp;lt;/Private&amp;gt;
    &amp;lt;/Reference&amp;gt;
    &amp;lt;Reference Include=&amp;quot;NXOpenUI, Culture=neutral, processorArchitecture=MSIL&amp;quot;&amp;gt;
      &amp;lt;SpecificVersion&amp;gt;False&amp;lt;/SpecificVersion&amp;gt;
      &amp;lt;HintPath&amp;gt;$(UGII_BASE_DIR)\nxbin\managed\NXOpenUI.dll&amp;lt;/HintPath&amp;gt;
	  &amp;lt;Private&amp;gt;False&amp;lt;/Private&amp;gt;
    &amp;lt;/Reference&amp;gt;
    &amp;lt;Reference Include=&amp;quot;System&amp;quot; /&amp;gt;
    &amp;lt;Reference Include=&amp;quot;System.Data&amp;quot; /&amp;gt;
    &amp;lt;Reference Include=&amp;quot;System.Xml&amp;quot; /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;
  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;!-- Add sourcefiles to include --&amp;gt;
    &amp;lt;!-- 
    &amp;lt;Compile Include=&amp;quot;&amp;lt;source&amp;gt;.cs&amp;quot; /&amp;gt;
    --&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;
  &amp;lt;Import Project=&amp;quot;$(MSBuildBinPath)\Microsoft.CSharp.targets&amp;quot;/&amp;gt;
&amp;lt;/Project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/de/post/nxopen-vscode/csproj_hu_e23ca46eec0d4b11.jpg&#34; class=&#34;lazyload&#34; alt=&#34;&#34; width=&#34;728&#34; height=&#34;287&#34;&gt;



  
  
  &lt;figcaption&gt;
    Projektverzeichnis mit Projektdatei.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;p&gt;Nun können eine oder mehrere Quellcodedateien zum Projekt hinzugefügt werden. Alle Dateien müssen in der Projektdatei eingetragen werden.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;...
  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;!-- Add sourcefiles to include --&amp;gt;
    &amp;lt;Compile Include=&amp;quot;program.cs&amp;quot; /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nun stehen alle Features zur Quellcodehervorhebung und zur automatischen Vervollständigung zur Verfügung.&lt;/p&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/de/post/nxopen-vscode/autocompl_hu_dd1bfec0776ddc18.jpg&#34; class=&#34;lazyload&#34; alt=&#34;&#34; width=&#34;1002&#34; height=&#34;466&#34;&gt;



  
  
  &lt;figcaption&gt;
    Quellcodehervorhebung und Vervollständigung.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;h2 id=&#34;kompilieren&#34;&gt;Kompilieren&lt;/h2&gt;
&lt;p&gt;Vor dem Kompilieren müssen die Buildtools installiert und die &lt;em&gt;PATH&lt;/em&gt;-Umgebungsvariable entsprechend angepasst sein.&lt;/p&gt;
&lt;p&gt;Zum Kompilieren &lt;em&gt;Strg&lt;/em&gt; + &lt;em&gt;Shift&lt;/em&gt; + &lt;em&gt;b&lt;/em&gt; drücken. Falls der notwendige Build-Task noch nicht vorhanden ist, wird die Erzeugung angeboten.&lt;/p&gt;
&lt;p&gt;




  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/de/post/nxopen-vscode/new_build_task_hu_57d0a88052dd546d.jpg&#34; class=&#34;lazyload&#34; alt=&#34;&#34; width=&#34;1017&#34; height=&#34;352&#34;&gt;



  
  
  &lt;figcaption&gt;
    Build-Task erzeugen.
  &lt;/figcaption&gt;


&lt;/figure&gt;






  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/de/post/nxopen-vscode/json_hu_712197890ddda50b.jpg&#34; class=&#34;lazyload&#34; alt=&#34;&#34; width=&#34;596&#34; height=&#34;67&#34;&gt;



  
  
  &lt;figcaption&gt;
    JSON Konfigurationsdatei erzeugen.
  &lt;/figcaption&gt;


&lt;/figure&gt;






  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/de/post/nxopen-vscode/msbuild_hu_521ccedbec17de4b.jpg&#34; class=&#34;lazyload&#34; alt=&#34;&#34; width=&#34;599&#34; height=&#34;129&#34;&gt;



  
  
  &lt;figcaption&gt;
    Vorlage auswählen.
  &lt;/figcaption&gt;


&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Im Unterordner &lt;em&gt;.vscode&lt;/em&gt; des Projektverzeichnisses ist nun die Datei &lt;em&gt;tasks.json&lt;/em&gt; zu finden. Diese kann nun noch nach dem folgenden Beispiel modifiziert werden.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    &amp;quot;version&amp;quot;: &amp;quot;2.0.0&amp;quot;,
    &amp;quot;tasks&amp;quot;: [
        {
            &amp;quot;label&amp;quot;: &amp;quot;msbuild debug&amp;quot;,
            &amp;quot;type&amp;quot;: &amp;quot;shell&amp;quot;,
            &amp;quot;command&amp;quot;: &amp;quot;msbuild&amp;quot;,
            &amp;quot;args&amp;quot;: [
                // Ask msbuild to generate full paths for file names.
                &amp;quot;/property:GenerateFullPaths=true&amp;quot;,
                &amp;quot;/t:build&amp;quot;,
                &amp;quot;/p:Configuration=Debug&amp;quot;,
                // Do not generate summary otherwise it leads to duplicate errors in Problems panel
                &amp;quot;/consoleloggerparameters:NoSummary&amp;quot;
            ],
            &amp;quot;group&amp;quot;: &amp;quot;build&amp;quot;,
            &amp;quot;presentation&amp;quot;: {
                // Reveal the output only if unrecognized errors occur.
                &amp;quot;reveal&amp;quot;: &amp;quot;silent&amp;quot;
            },
            // Use the standard MS compiler pattern to detect errors, warnings and infos
            &amp;quot;problemMatcher&amp;quot;: &amp;quot;$msCompile&amp;quot;
        },
        {
            &amp;quot;label&amp;quot;: &amp;quot;msbuild release&amp;quot;,
            &amp;quot;type&amp;quot;: &amp;quot;shell&amp;quot;,
            &amp;quot;command&amp;quot;: &amp;quot;msbuild&amp;quot;,
            &amp;quot;args&amp;quot;: [
                // Ask msbuild to generate full paths for file names.
                &amp;quot;/property:GenerateFullPaths=true&amp;quot;,
                &amp;quot;/p:Configuration=Release&amp;quot;,
                &amp;quot;/t:build&amp;quot;,
                // Do not generate summary otherwise it leads to duplicate errors in Problems panel
                &amp;quot;/consoleloggerparameters:NoSummary&amp;quot;
            ],
            &amp;quot;group&amp;quot;: &amp;quot;build&amp;quot;,
            &amp;quot;presentation&amp;quot;: {
                // Reveal the output only if unrecognized errors occur.
                &amp;quot;reveal&amp;quot;: &amp;quot;silent&amp;quot;
            },
            // Use the standard MS compiler pattern to detect errors, warnings and infos
            &amp;quot;problemMatcher&amp;quot;: &amp;quot;$msCompile&amp;quot;
        }

    ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nach erneutem Drücken von &lt;em&gt;Strg&lt;/em&gt; + &lt;em&gt;Shift&lt;/em&gt; + &lt;em&gt;b&lt;/em&gt; kann nun zwischen einem Debug- und einem Release-Build ausgewählt werden.&lt;/p&gt;
&lt;h2 id=&#34;fazit&#34;&gt;Fazit&lt;/h2&gt;
&lt;p&gt;VSCode kann mit verhältnismäßig geringem Aufwand eingerichtet und für die Entwicklung von NX Open Applikationen in C# verwendet werden. Insbesondere für unkompilierte Journale und kleinere Projekte ist es eine Alternative zu Visual Studio.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;
&lt;a href=&#34;https://de.wikipedia.org/wiki/Visual_Studio_Code&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;VS Code auf Wikipedia&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;.NET Framework 4.6.2 Developer Pack: 
&lt;a href=&#34;https://dotnet.microsoft.com/download/dotnet-framework/net462&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://dotnet.microsoft.com/download/dotnet-framework/net462&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;Visual Studio Code: 
&lt;a href=&#34;https://code.visualstudio.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://code.visualstudio.com&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;Buildtools für Visual Studio: 
&lt;a href=&#34;https://visualstudio.microsoft.com/downloads&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://visualstudio.microsoft.com/downloads&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34;&gt;
&lt;p&gt;Visual Studio Code Dokumentation: 
&lt;a href=&#34;https://code.visualstudio.com/docs&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://code.visualstudio.com/docs&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>.NET NX Journale debuggen</title>
      <link>https://www.ib-boettcher.de/de/post/debug-dotnet-journal/</link>
      <pubDate>Wed, 06 May 2020 09:46:18 +0200</pubDate>
      <guid>https://www.ib-boettcher.de/de/post/debug-dotnet-journal/</guid>
      <description>&lt;h2&gt;Inhaltsverzeichnis&lt;/h2&gt;
&lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#hintergrund&#34;&gt;Hintergrund&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#lösungsansatz&#34;&gt;Lösungsansatz&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#umsetzung&#34;&gt;Umsetzung&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#fazit&#34;&gt;Fazit&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;h2 id=&#34;hintergrund&#34;&gt;Hintergrund&lt;/h2&gt;
&lt;p&gt;Journale&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; sind ein beliebtes Mittel um Abläufe in NX zu automatisieren oder individuelle Erweiterungen zu realisieren. Zur Ausführung ist keine Compilierung und keine zusätzliche Lizenz notwendig. Es gibt jedoch auch verschiedene Nachteile. Gelegentlich wird als Nachteil genannt, dass die Fehlersuche mit einem Debugger nicht möglich sei. Das stimmt jedoch so nicht. Über einen kleinen Umweg können auch C# und VB.NET Journale mit Visual Studio oder auch WinDbg debuggt werden. Für umfangreichere Journale oder bei hartnäckigen Fehlern kann sich dieser Aufwand lohnen.&lt;/p&gt;
&lt;h2 id=&#34;lösungsansatz&#34;&gt;Lösungsansatz&lt;/h2&gt;
&lt;p&gt;Entscheidend für die Lösung des Problems ist, wie NX .NET Journale ausführt. Das auszuführende Journal wird dabei zunächst unter einem generischen Namen in ein temporäres Verzeichnis kopiert. Diese Kopie wird zur Laufzeit compiliert und anschließend gelöscht. Jetzt lädt NX das entstandene .NET Assembly wie ein reguläres NX Open-Programm. Nach Abarbeitung des Programmes löscht NX das temporäre Verzeichnis samt Inhalt.&lt;br&gt;
Während des Programmlaufs ist mit dem Assembly und der zugehörigen Symboldatei (&lt;em&gt;pdb&lt;/em&gt;-Datei) im temporären Verzeichnis fast alles Notwendige für das Debuggen vorhanden. Lediglich der Quellcode, auf den in der Symboldatei verwiesen wird, liegt zur Laufzeit nicht mehr vor.&lt;br&gt;
Unter der Annahme, dass das ursprüngliche Journal von NX tatsächlich unverändert in das temporäre Verzeichnis kopiert wird, kann der Quellcode aus der Originaldatei wieder hergestellt werden. Der Name der Quellcodedatei muss dabei dem Namen des Assemblies entsprechen. Außerdem darf die Kopie erst erstellt werden, wenn das Programm bereits abgearbeitet wird.
Nun kann die Quellcodedatei in Visual Studio oder in einem anderen Debugger geöffnet und der Debugger mit dem NX-Prozess verbunden werden.&lt;br&gt;
Ein kurzer Versuch zeigt, dass dieser Ansatz funktioniert, wenn das ursprüngliche Journal Zeilenumbrüche im Unix-Format besitzt (&lt;em&gt;LF&lt;/em&gt;). Bei Zeilenumbrüchen im Windows-Format (&lt;em&gt;CR LF&lt;/em&gt;) reicht das Kopieren und Umbenennen des Journals nicht aus. Hier stimmt der MD5-Hash, der für den Quellcode im Assembly hinterlegt ist, nicht mit dem der kopierten Datei überein. Ein Anpassen der Zeilenumbrüche in der kopierten Datei führt zum Erfolg.&lt;/p&gt;
&lt;h2 id=&#34;umsetzung&#34;&gt;Umsetzung&lt;/h2&gt;
&lt;p&gt;Einige für das Debuggen notwendige Schritte können durch das Journal selbst erledigt werden. Diese sind hier in einer kleinen Methode zusammengefasst, die direkt nach dem Start des Journals aufgerufen werden kann.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-csharp&#34;&gt;/// &amp;lt;summary&amp;gt;
/// Prepare debugging of uncompiled journals.
/// &amp;lt;/summary&amp;gt;
public static void InitJournalDebug()
{
    string journalPath = Session.GetSession().ExecutingJournal;
    string extension = Path.GetExtension(journalPath);
    Uri uri = new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase);
    string tmpSourcePath = Path.ChangeExtension(uri.LocalPath, extension);
    using (StreamWriter sw = File.CreateText(tmpSourcePath))
    {
        sw.NewLine = &amp;quot;\n&amp;quot;;
        foreach (string line in File.ReadLines(journalPath))
        {
            sw.WriteLine(line);
        }
    }
    UI.GetUI().NXMessageBox.Show(&amp;quot;Source File&amp;quot;, NXMessageBox.DialogType.Information, string.Format(&amp;quot;Source file for debugging:\n{0}&amp;quot;, tmpSourcePath));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Die Methode kopiert das ursprüngliche Journal, versieht es mit den richtigen Zeilenumbrüchen und benennt es um. Danach wird die Programmausführung mittels eines Dialoges angehalten. Die im Dialog angezeigte Quellcodedatei kann vom Anwender in Visual Studio geöffnet und nach Bedarf mit Breakpoints versehen werden. Abschließend muss der Debugger an den NX-Prozess (&lt;em&gt;ugraf.exe&lt;/em&gt;) angehängt und das Programm durch Bestätigen des Dialoges fortgesetzt werden.&lt;/p&gt;
&lt;p&gt;Ein minimales Journal könnte also so aussehen:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-csharp&#34;&gt;using NXOpen;
using System;
using System.IO;
using System.Reflection;

public class Journal
{
    /// &amp;lt;summary&amp;gt;
    /// Journal entry point.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name=&amp;quot;args&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
    /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
    public static int Main(string[] args)
    {
        int retValue = 0;
        try
        {
            InitJournalDebug();//Only for debugging, remove in production

            //Do something.
            double result = Foobar(Math.PI, Math.E);
        }
        catch (NXOpen.NXException e)
        {
            UI.GetUI().NXMessageBox.Show(&amp;quot;Message&amp;quot;, NXMessageBox.DialogType.Error, e.Message);
        }
        return retValue;
    }

    /// &amp;lt;summary&amp;gt;
    /// Prepare debugging of uncompiled journals.
    /// &amp;lt;/summary&amp;gt;
    public static void InitJournalDebug()
    {
        string journalPath = Session.GetSession().ExecutingJournal;
        string extension = Path.GetExtension(journalPath);
        Uri uri = new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase);
        string tmpSourcePath = Path.ChangeExtension(uri.LocalPath, extension);
        using (StreamWriter sw = File.CreateText(tmpSourcePath))
        {
            sw.NewLine = &amp;quot;\n&amp;quot;;
            foreach (string line in File.ReadLines(journalPath))
            {
                sw.WriteLine(line);
            }
        }
        UI.GetUI().NXMessageBox.Show(&amp;quot;Source File&amp;quot;, NXMessageBox.DialogType.Information, string.Format(&amp;quot;Source file for debugging:\n{0}&amp;quot;, tmpSourcePath));
    }

    /// &amp;lt;summary&amp;gt;
    /// Do something.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name=&amp;quot;foo&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
    /// &amp;lt;param name=&amp;quot;bar&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
    /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
    public static double Foobar(double foo, double bar)
    {
        double res = foo * bar;
        return res;
    }

    /// &amp;lt;summary&amp;gt;
    /// Unload option.
    /// Without effect for uncompiled journals
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name=&amp;quot;arg&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
    /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
    public static int GetUnloadOption(string arg)
    {
        return System.Convert.ToInt32(Session.LibraryUnloadOption.Immediately);
    }
}
&lt;/code&gt;&lt;/pre&gt;





  
  











&lt;figure&gt;


  &lt;a data-fancybox=&#34;&#34; href=&#34;https://www.ib-boettcher.de/de/post/debug-dotnet-journal/nx_hu_58f2bda9b16fae2d.jpg&#34; data-caption=&#34;Meldungsfenster in NX mit Pfad zum Quelltext.&#34;&gt;


  &lt;img data-src=&#34;https://www.ib-boettcher.de/de/post/debug-dotnet-journal/nx_hu_58f2bda9b16fae2d.jpg&#34; class=&#34;lazyload&#34; alt=&#34;&#34; width=&#34;567&#34; height=&#34;288&#34;&gt;
&lt;/a&gt;


  
  
  &lt;figcaption&gt;
    Meldungsfenster in NX mit Pfad zum Quelltext.
  &lt;/figcaption&gt;


&lt;/figure&gt;






  
  











&lt;figure&gt;


  &lt;a data-fancybox=&#34;&#34; href=&#34;https://www.ib-boettcher.de/de/post/debug-dotnet-journal/attach_hu_467f7a0e320ec78f.jpg&#34; data-caption=&#34;Anfügen des Debuggers.&#34;&gt;


  &lt;img data-src=&#34;https://www.ib-boettcher.de/de/post/debug-dotnet-journal/attach_hu_467f7a0e320ec78f.jpg&#34; class=&#34;lazyload&#34; alt=&#34;&#34; width=&#34;994&#34; height=&#34;657&#34;&gt;
&lt;/a&gt;


  
  
  &lt;figcaption&gt;
    Anfügen des Debuggers.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;h2 id=&#34;fazit&#34;&gt;Fazit&lt;/h2&gt;
&lt;p&gt;Es ist möglich, zur Fehleranalyse von uncompilierten Journalen einen Debugger zu verwenden. Das Vorgehen ist ein wenig umständlich, erweitert aber die Einsatzmöglichkeiten dieser Journale, da so auch umfangreichere Fehlersuchen in komplexeren Programmen möglich sind.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Der Begriff Journal wird im erweiterten Sinn häufig auch für NX Open-Programme allgemein verwendet. Hier sind aber ausschließlich in VB.NET oder C# realisierte Programme gemeint, die direkt als Quellcode ausgeführt werden.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
  </channel>
</rss>
