<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Posts (en) | Ingenieurbuero Jan Boettcher</title>
    <link>https://www.ib-boettcher.de/en/post/</link>
      <atom:link href="https://www.ib-boettcher.de/en/post/index.xml" rel="self" type="application/rss+xml" />
    <description>Posts (en)</description>
    <generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>en-us</language><copyright>© Ingenieurbüro Jan Böttcher 2026</copyright><lastBuildDate>Wed, 06 Apr 2022 10:13:00 +0200</lastBuildDate>
    <image>
      <url>https://www.ib-boettcher.de/img/gear_hero_2020.png</url>
      <title>Posts (en)</title>
      <link>https://www.ib-boettcher.de/en/post/</link>
    </image>
    
    <item>
      <title>Debug NX Open in VS Code</title>
      <link>https://www.ib-boettcher.de/en/post/debug-vscode/</link>
      <pubDate>Wed, 06 Apr 2022 10:13:00 +0200</pubDate>
      <guid>https://www.ib-boettcher.de/en/post/debug-vscode/</guid>
      <description>&lt;h2&gt;Table of Contents&lt;/h2&gt;
&lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#background&#34;&gt;Background&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#requirements&#34;&gt;Requirements&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#configure-the-nx-open-project&#34;&gt;Configure the NX Open Project&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#create-start-configuration&#34;&gt;Create Start Configuration&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;background&#34;&gt;Background&lt;/h2&gt;
&lt;p&gt;In another 
&lt;a href=&#34;https://www.ib-boettcher.de/en/post/nxopen-vscode/&#34;&gt;article&lt;/a&gt;, I showed how NX Open programs can be created and compiled with the source code editor VS Code (Visual Studio Code)&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;A debugger is an important tool for program development and troubleshooting. VS Code and the C# extension primarily target .NET Core and not the .NET Framework required for NX Open development. Nevertheless, .NET Framework applications can also be debugged&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;requirements&#34;&gt;Requirements&lt;/h2&gt;
&lt;p&gt;The procedure described here is only suitable for debugging compiled NX Open applications. Debugging journals&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; is not possible with VS Code.&lt;/p&gt;
&lt;p&gt;Setting up the development environment is described 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;.&lt;/p&gt;
&lt;h2 id=&#34;configure-the-nx-open-project&#34;&gt;Configure the NX Open Project&lt;/h2&gt;
&lt;p&gt;First, the project file &lt;em&gt;*.csproj&lt;/em&gt; must be adapted. &lt;em&gt;PlatformTarget&lt;/em&gt; must be &lt;em&gt;x64&lt;/em&gt; and the &lt;em&gt;DebugType&lt;/em&gt; must be &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;create-start-configuration&#34;&gt;Create Start Configuration&lt;/h2&gt;
&lt;p&gt;To create a debug configuration, a corresponding entry must be added to the &lt;em&gt;launch.json&lt;/em&gt; file. If this file does not yet exist, it must be created in the &lt;em&gt;.vscode&lt;/em&gt; directory (see e.g. &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/en/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;
    Debug Configuration 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;First, NX must be started. Then the debug session can be launched in VS Code with &lt;em&gt;F5&lt;/em&gt; and the NX process can be selected.&lt;/p&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/en/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;
    Start Debug Session
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;p&gt;When executing the NX Open application, the program stops at a breakpoint.&lt;/p&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/en/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 in C# 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/en/post/nxopen-vscode/&#34;&gt;https://www.ib-boettcher.de/en/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;The term journal is often used in a broader sense for NX Open programs in general. Here, however, it is used only for programs implemented in VB.NET or C # that are executed directly from source code.&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>Slow Journals?</title>
      <link>https://www.ib-boettcher.de/en/post/time-comp/</link>
      <pubDate>Fri, 14 May 2021 09:46:18 +0200</pubDate>
      <guid>https://www.ib-boettcher.de/en/post/time-comp/</guid>
      <description>&lt;h2&gt;Table of Contents&lt;/h2&gt;
&lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#background&#34;&gt;Background&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#test-setup&#34;&gt;Test Setup&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#results&#34;&gt;Results&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;p&gt;Whether I rely on a 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; or a compiled solution when implementing an NX add-on program depends on many different factors. If a certain programming language is intended for the implementation, there may not be a choice. C/C++ and Java must always be compiled. Python programs are always executed as scripts.&lt;/p&gt;
&lt;p&gt;The .NET languages C# and VB.NET can be used in NX both compiled and uncompiled. The responsiveness and the processing speed can be important factors for the selection of one or the other variant. It is obvious that compiled .NET programs have a speed advantage. But how big is this difference actually? What is its effect in practice?&lt;/p&gt;
&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;
&lt;p&gt;Uncompiled .NET NX Open Journals are not interpreted at runtime. Each time the journal is called, the source code is compiled with the standard compiler in the .NET Framework, loaded and then regularly executed. During the program run you can find the corresponding assembly under the name &lt;em&gt;journal.dll&lt;/em&gt; in the temporary directory used by NX. After completion of the program run, this dll is deleted each time by NX.&lt;/p&gt;
&lt;p&gt;Interestingly, this means for the execution speed of the actual program content that compiled programs cannot have any advantage over uncompiled Journals. In the overall balance, however, the overhead for internal compilation is added. This overhead increases the response time of the application after the start.&lt;/p&gt;
&lt;p&gt;Another aspect must also be taken into account. In the case of compiled programs, the unload option for the assembly can be specified (&lt;em&gt;Immediately&lt;/em&gt;, &lt;em&gt;At Termination&lt;/em&gt;, &lt;em&gt;Explicitly&lt;/em&gt;). In the case of Journals, this option is ignored in the source code. The assemblies of journals are always unloaded after the end of the program (&lt;em&gt;Immediately&lt;/em&gt;). If necessary, compiled programs can benefit from the fact that NX holds the assemblies in memory for re-execution.&lt;/p&gt;
&lt;h2 id=&#34;test-setup&#34;&gt;Test Setup&lt;/h2&gt;
&lt;p&gt;Since, as shown, only the overhead for compiling and the unloading behavior matter, a very simple test program can be used. It only writes a marker to the NX log file.&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;To determine the influence of the size of the source code, another program was created that corresponds to the first program in terms of its content. In addition, the source code of a medium-sized real project was added in such a way that it is compiled but not executed. The result is a source code file with around 2700 lines.&lt;/p&gt;
&lt;p&gt;A variant of both programs was created, compiled, and signed with the authoring license with the unloading option &lt;em&gt;Immediately&lt;/em&gt; (directly after the end of the program) and &lt;em&gt;At Termination&lt;/em&gt; (when exiting NX). The source codes of the short and long programs can also be executed directly as journals. This results in a total of 6 variants to be tested:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SUI: Short Program, compiled, unload immediately&lt;/li&gt;
&lt;li&gt;SUAT: Short Program, compiled, unload at NX termination&lt;/li&gt;
&lt;li&gt;SUIJ: Short Program, run as Journal&lt;/li&gt;
&lt;li&gt;BUI: Long Programm, compiled, unload immediately&lt;/li&gt;
&lt;li&gt;BUAT: Long Programm, compiled, unload at NX termination&lt;/li&gt;
&lt;li&gt;BUIJ: Long Programm, run as Journal&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To determine the execution time of those programs, there is also a small program that only writes a timestamp in the NX log file.
In addition, a MenuScript file (.men) was written that creates an action button with a consecutive sequence of actions in NX for each of the 6 variants mentioned.&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;In this way, the individual programs are executed immediately one after the other by NX at the push of a button. The timestamps and markers of the actual programs can be read from the log file for evaluation. The actual execution time of the variant to be tested can be determined from the distance between two timestamps enclosing a marker minus the distance between two directly consecutive timestamps.
The first tests showed that outliers repeatedly occurred during the runtime of the time stamp program. This is why the timestamp program is called several times in succession and the median is used to calculate the execution times of the actual programs.&lt;/p&gt;
&lt;p&gt;For each of the 6 program variants, 9 runs were carried out with a newly started NX. The execution times for the first and the second program call result from the median of these 9 runs.
The values ​​determined are a measure of the response behavior of the various variants.&lt;/p&gt;
&lt;p&gt;The tests were carried out under NX1953 on an older workstation with a Xeon CPU. The results can only be transferred qualitatively to other systems.&lt;/p&gt;
&lt;h2 id=&#34;results&#34;&gt;Results&lt;/h2&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/en/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;
    Execution times of short program variants.&lt;br/&gt;SUI: compiled, unload immediately.&lt;br/&gt;SUAT: compiled, unload at termination of NX.&lt;br/&gt;SUIJ: run as Journal.&lt;br/&gt;(1): first run, (2): second run.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;p&gt;The figure shows the results for the short program variants. The full execution time for the compiled variants is just under 0.6 seconds when started for the first time (&lt;em&gt;SUI (1)&lt;/em&gt;, &lt;em&gt;SUAT (1)&lt;/em&gt;). At the second start, the execution time is reduced to around 0.2 seconds if the dll was not unloaded beforehand (&lt;em&gt;SUAT (2)&lt;/em&gt;). If the dll was unloaded (&lt;em&gt;SUI (2)&lt;/em&gt;), the execution time corresponds to that of the initial start.
The journal variants (&lt;em&gt;SUIJ (1)&lt;/em&gt;, &lt;em&gt;SUIJ (2)&lt;/em&gt;) have a significantly longer execution time of around 1.2 seconds. The second run is slightly faster than the first.&lt;/p&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/en/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;
    Execution times of short program variants.&lt;br/&gt;BUI: compiled, unload immediately.&lt;br/&gt;BUAT: compiled, unload at termination of NX.&lt;br/&gt;BUIJ: run as Journal.&lt;br/&gt;(1): first run, (2): second run.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;p&gt;The figure shows the results for the long program variant. Here, too, the execution time for the compiled variants is just under 0.6 seconds at the first start (&lt;em&gt;BUI (1)&lt;/em&gt;, &lt;em&gt;BUAT (1)&lt;/em&gt;) and 0.2 seconds at the second start if the dll has not been unloaded beforehand (&lt;em&gt;BUAT (2 )&lt;/em&gt;). The uncompiled journal (&lt;em&gt;BUIJ&lt;/em&gt;) has a slightly longer execution time of 1.4 seconds than the short version.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Overall, the measurements show no surprises. Uncompiled journals take significantly longer to start and stop than their compiled counterparts. Ideally, the response time to user interaction is less than a second (see e.g. &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; or &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;). The compiled programs are all well below this mark. Journals show poorer response behavior. However, the values are not so high that the workflow is interrupted.&lt;/p&gt;
&lt;p&gt;The influence of the source code size on the start time of the programs is small, compiled, and uncompiled.&lt;/p&gt;
&lt;p&gt;Concerning the speed at which the actual program content runs, there is no difference between compiled and uncompiled applications.&lt;/p&gt;
&lt;p&gt;If responsiveness plays a very important role, then compiled NX Open .NET applications are preferable. In all other cases, Journals can also be used.&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;The term journal is often used in a broader sense for NX Open programs in general. Here, however, it is used only for programs implemented in VB.NET or C # that are executed directly from source code.&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>Create QR Code Annotations (Example)</title>
      <link>https://www.ib-boettcher.de/en/post/qr-python/</link>
      <pubDate>Fri, 21 Aug 2020 08:46:18 +0200</pubDate>
      <guid>https://www.ib-boettcher.de/en/post/qr-python/</guid>
      <description>&lt;h2&gt;Table of Contents&lt;/h2&gt;
&lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#background&#34;&gt;Background&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#requirements&#34;&gt;Requirements&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#implementation&#34;&gt;Implementation&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;
&lt;p&gt;QR codes are often used to attach information that is fault-tolerant and machine-readable. NX (currently) only offers the option of generating one-dimensional barcodes as annotations using a special character set. This post aims to show how QR codes can be easily inserted using an NX Open Journal in Python.&lt;/p&gt;
&lt;h2 id=&#34;requirements&#34;&gt;Requirements&lt;/h2&gt;
&lt;p&gt;The python package &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; is required to encode the content. The system font &lt;em&gt;Courier New&lt;/em&gt; must also be available.&lt;/p&gt;
&lt;h2 id=&#34;implementation&#34;&gt;Implementation&lt;/h2&gt;
&lt;p&gt;If a non-proportional font is selected for generating the annotation, the text can be composed of spaces and a square symbol (here &lt;em&gt;Courier New, Geometric Shapes, Black Square&lt;/em&gt;) line by line. The point matrix for this can be determined from the content to be coded using the &lt;em&gt;get_matrix&lt;/em&gt; method of the &lt;em&gt;qrcode.QRCode&lt;/em&gt; class.&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 and VS Code</title>
      <link>https://www.ib-boettcher.de/en/post/nxopen-vscode/</link>
      <pubDate>Thu, 09 Jul 2020 08:46:18 +0200</pubDate>
      <guid>https://www.ib-boettcher.de/en/post/nxopen-vscode/</guid>
      <description>&lt;h2&gt;Table of Contents&lt;/h2&gt;
&lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#background&#34;&gt;Background&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#requirements&#34;&gt;Requirements&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#set-up-nx-open-projects&#34;&gt;Set up NX Open Projects&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#compiling&#34;&gt;Compiling&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;
&lt;p&gt;NX Open applications written in C# are usually created with Microsoft&amp;rsquo;s Visual Studio. NX has wizards to easily set up the corresponding projects. However, if you can&amp;rsquo;t or don&amp;rsquo;t want to use that development environment, the open-source program VS Code (Visual Studio Code) is a good alternative.
Apart from the name and the manufacturer, those two tools have only a few things in common. VS Code is primarily a source code editor&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;
For small and medium-sized NX Open projects, all necessary features are there. In particular, IntelliSense, which is indispensable for working productively with the numerous classes and methods of the NX Open API, corresponds to that of Visual Studio.&lt;/p&gt;
&lt;h2 id=&#34;requirements&#34;&gt;Requirements&lt;/h2&gt;
&lt;p&gt;In addition to the actual program, other components are required to use VS Code as a development environment for NX Open applications. The required version of these components depends on the NX target version. In the example presented here, the target version is NX 1899. All components necessary in addition to NX are available online for free.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NX 1899 including the &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 Extension)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If not only uncompiled journals are to be created, the compiler must be installed separately:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;.NET Desktop-Buildtools (part of the der Buildtools for 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;). From the optional components at least the .NET Framework 4.6.2 development tools should be installed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Details on the use of VS Code can be found here&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;.
The C# extension for vs code can be installed from within the program.&lt;/p&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/en/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;
    Install C# extension.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;p&gt;VS Code with the C # extension is primarily aimed at .NET Core and not .NET Framework, which is required for NX Open development. Accordingly, a message may appear indicating that the .NET Core SDK is missing. This message can be ignored or suppressed.&lt;/p&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/en/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;
    The message on the .NET Core SDK can be ignored.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;p&gt;Furthermore, the environment variable &lt;em&gt;UGII_BASE_DIR&lt;/em&gt; should be set when using VS Code for NX Open development. This can be done by using a small start script. The path to the build tools can also be added to the &lt;em&gt;PATH&lt;/em&gt; variable here if not only uncompiled journals are to be created.&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;set-up-nx-open-projects&#34;&gt;Set up NX Open Projects&lt;/h2&gt;
&lt;p&gt;First, a new directory must be created for the project and must be opened in VS Code. This can be done in one step by &lt;em&gt;File/Open Folder&amp;hellip;&lt;/em&gt; and the corresponding context menu.





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/en/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;
    Create and open project directory.
  &lt;/figcaption&gt;


&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;The project file required for a working IntelliSense and compilation must be created by hand. The template file of the wizard from the NX installation can serve as a template (&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;). The extension of the new file must be &lt;em&gt;csproj&lt;/em&gt;.&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/en/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;
    Project directory with project file.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;p&gt;Now one or more source code files can be added to the project. All files must be entered into the project file.&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;Now all features for source code highlighting and automatic completion are available.&lt;/p&gt;





  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/en/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;
    Source code highlighting and autocomplete.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;h2 id=&#34;compiling&#34;&gt;Compiling&lt;/h2&gt;
&lt;p&gt;Before compiling, the build tools must be installed and the &lt;em&gt;PATH&lt;/em&gt; environment variable must be adjusted accordingly.
Press &lt;em&gt;Ctrl&lt;/em&gt; + &lt;em&gt;Shift&lt;/em&gt; + &lt;em&gt;b&lt;/em&gt; to compile. If the necessary build task is not yet available, the generation is offered.&lt;/p&gt;
&lt;p&gt;




  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/en/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;
    Create build task.
  &lt;/figcaption&gt;


&lt;/figure&gt;






  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/en/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;
    Create JSON configuration file.
  &lt;/figcaption&gt;


&lt;/figure&gt;






  
  











&lt;figure&gt;



  &lt;img data-src=&#34;https://www.ib-boettcher.de/en/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;
    Select task template.
  &lt;/figcaption&gt;


&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;tasks.json&lt;/em&gt; file can now be found in the &lt;em&gt;.vscode&lt;/em&gt; subfolder of the project directory. It can be modified according to the following example.&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;After pressing &lt;em&gt;Ctrl&lt;/em&gt; + &lt;em&gt;Shift&lt;/em&gt; + &lt;em&gt;b&lt;/em&gt; again you can choose between a debug and a release build.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;VSCode can be set up with relatively little effort and used for the development of NX Open applications in C# as an alternative to Visual Studio, especially for uncompiled journals and smaller projects.&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://en.wikipedia.org/wiki/Visual_Studio_Code&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;VS Code on 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 for 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 Documentation: 
&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>Debug .NET NX Journals</title>
      <link>https://www.ib-boettcher.de/en/post/debug-dotnet-journal/</link>
      <pubDate>Thu, 14 May 2020 09:46:18 +0200</pubDate>
      <guid>https://www.ib-boettcher.de/en/post/debug-dotnet-journal/</guid>
      <description>&lt;h2&gt;Table of Contents&lt;/h2&gt;
&lt;nav id=&#34;TableOfContents&#34;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;#background&#34;&gt;Background&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#approach&#34;&gt;Approach&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#implementation&#34;&gt;Implementation&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;#conclusion&#34;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;
&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;
&lt;p&gt;Journals&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; are a popular means of automating and customizing processes in NX. No compiling and no additional licenses are required for execution. But there are also several disadvantages. One that is mentioned sometimes, is that debugging is not possible. However, this is not true. With a small detour, C # and VB.NET journals can be debugged with Visual Studio or WinDbg. This effort can be worthwhile for larger journals or persistent bugs.&lt;/p&gt;
&lt;h2 id=&#34;approach&#34;&gt;Approach&lt;/h2&gt;
&lt;p&gt;The way NX .NET runs journals is critical to solving the problem. The journal to be executed is first copied into a temporary directory under a generic name. This copy is compiled at runtime and then deleted. Now NX loads the resulting .NET assembly like a regular NX Open program. After executing the program, NX deletes the temporary directory and its contents.
During the execution of the program, almost everything necessary for debugging is available in the temporary directory with the assembly and the associated symbol file (&lt;em&gt;pdb&lt;/em&gt; file). Only the source code referred to in the symbol file is no longer available at runtime.&lt;br&gt;
Assuming that the original journal from NX is copied unchanged into the temporary directory, the source code can be restored from the original file. The name of the source code file must match the name of the assembly. Additionally, the copy may only be made when the program is already being processed. Now the source code file can be opened in Visual Studio or another debugger and the debugger can be connected to the NX process.&lt;br&gt;
A quick test shows that this approach works if the original journal has line breaks in Unix format (&lt;em&gt;LF&lt;/em&gt;). With line breaks in Windows format (&lt;em&gt;CR LF&lt;/em&gt;), copying and renaming the journal is not sufficient. In this case, the MD5 hash that is stored for the source code in the assembly does not match that of the copied file. Adjusting the line breaks in the copied file is necessary.&lt;/p&gt;
&lt;h2 id=&#34;implementation&#34;&gt;Implementation&lt;/h2&gt;
&lt;p&gt;Some steps necessary for debugging can be done by the journal itself. These are summarized here in a small method that can be called immediately after the start of the journal.&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;The method copies the original journal provides it with the correct line breaks and renames it. Then the program execution is stopped using a dialog. The source code file displayed in the dialog can be opened by the user in Visual Studio and provided with breakpoints as required. Finally, the debugger must be attached to the NX process (&lt;em&gt;ugraf.exe&lt;/em&gt;), and the program continued by confirming the dialog.&lt;/p&gt;
&lt;p&gt;A minimal journal could look like this:&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/en/post/debug-dotnet-journal/nx_hu_58f2bda9b16fae2d.jpg&#34; data-caption=&#34;NX Dialog showing the path to the source code.&#34;&gt;


  &lt;img data-src=&#34;https://www.ib-boettcher.de/en/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;
    NX Dialog showing the path to the source code.
  &lt;/figcaption&gt;


&lt;/figure&gt;






  
  











&lt;figure&gt;


  &lt;a data-fancybox=&#34;&#34; href=&#34;https://www.ib-boettcher.de/en/post/debug-dotnet-journal/attach_hu_467f7a0e320ec78f.jpg&#34; data-caption=&#34;Attach the debugger.&#34;&gt;


  &lt;img data-src=&#34;https://www.ib-boettcher.de/en/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;
    Attach the debugger.
  &lt;/figcaption&gt;


&lt;/figure&gt;

&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;It is possible to use a debugger to analyze errors in uncompiled journals. It&amp;rsquo;s a little cumbersome, but it expands the possible uses of these journals since it enables advanced troubleshooting in more complex programs.&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;The term journal is often used in a broader sense for NX Open programs in general. Here, however, it is used only for programs implemented in VB.NET or C # that are executed directly from source code.&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>
