NI TestStand

cancel
Showing results for 
Search instead for 
Did you mean: 

Create TS Engines in differents version of TestStand in c# using TSVersionSelector and AppDomain

Hi everyone,

 

I'm facing an issue with my application in c# . 

This is what I want to do :

-> Create a TS Engine in the current version of TestStand, use it then destroy it

-> Change the current version of TestStand with TSVersionSelector

-> Create a new TS Engine in the new version and use it also.

 

My problem is that as far as I don't close my application, the assemblies from the first TS Engine are still loaded and the new Engine which is created is still from the old version of TS.

 

I don't want to close my application before using TSVersionSelector

 

I also tried to use my TS Engine in a different AppDomain but it still keep the old assemblies in memory.

I'm not quite used to AppDomain so I'm not sure to use it correctly.

Maybe there is some other stuff to unload.

 

Or maybe there is another way to chose in which version we want to create an Engine but I don't think so.

 

Here is a bit of code:

 

 

 

using NationalInstruments.TestStand.Interop.API;
using NationalInstruments.TestStand.Utility;
using System;
using System.Runtime.InteropServices;

namespace ConsoleApp1
{
public class Program
{
[STAThread]
private static void Main(string[] args)
{
// Create application domain, call MainEntryPoint, and cleanup before return.
LaunchTestStandApplicationInNewDomain.Launch(
new LaunchTestStandApplicationInNewDomain.
MainEntryPointDelegateWithArgs(MainEntryPoint),
args);



// Manually change the current TS version with TSVersionSelector



// Create application domain, call MainEntryPoint, and cleanup before return.
LaunchTestStandApplicationInNewDomain.Launch(
new LaunchTestStandApplicationInNewDomain.
MainEntryPointDelegateWithArgs(MainEntryPoint),
args);

}



public class LaunchTestStandApplicationInNewDomain
{
/// <summary> Delegate for the main entry point to the application. </summary>
public delegate void MainEntryPointDelegate();

/// <summary> Delegate for the main entry point to the application with command-line arguments </summary>
public delegate void MainEntryPointDelegateWithArgs(string[] args);

/// <summary> Delegate for displaying error messages from the LaunchProtected method </summary>
/// <param name="caption"> Receives the caption that should be displayed in the message </param>
/// <param name="message"> Receives the error message to display </param>
public delegate void DisplayErrorMessageDelegate(string caption, string message);

private class TestStandApplication : System.MarshalByRefObject
{
public void CallEntryPoint(MainEntryPointDelegate entryPoint)
{
entryPoint();
}

public void CallEntryPoint(MainEntryPointDelegateWithArgs entryPoint, string[] args)
{
entryPoint(args);
}
}

/// <summary> Launches the application in a new AppDomain. </summary>
/// <param name="entryPoint"> Pass the main entry point to the application </param>
/// <param name="args"> Command-line arguments </param>
public static void Launch(MainEntryPointDelegateWithArgs entryPoint, string[] args)
{
LaunchHelper(null, entryPoint, args);
}

/// <summary> Launches the application in a new AppDomain. </summary>
/// <param name="entryPoint"> Pass the main entry point to the application </param>
public static void Launch(MainEntryPointDelegate entryPoint)
{
LaunchHelper(entryPoint, null, null);
}

private static void LaunchHelper(MainEntryPointDelegate entryPoint, MainEntryPointDelegateWithArgs entryPointWithArgs, string[] args)
{
try
{
AppDomain appDomain = AppDomain.CreateDomain("TestStandAppDomain");

string path2 = "C:\\Windows\\assembly\\GAC_MSIL\\NationalInstruments.TestStand.Interop.UI.AxControls\\5.1.0.226__ad9244eb3b825cd8\\NationalInstruments.TestStand.Interop.UI.AxControls.dll";
byte[] buffer2 = File.ReadAllBytes(path2);

Assembly assm = Assembly.Load(buffer2);

AxApplicationMgr applicationObj = (AxApplicationMgr)appDomain.CreateInstanceFromAndUnwrap(assm.Location, typeof(AxApplicationMgr).FullName);

applicationObj.CreateControl();
Engine Engine1 = applicationObj.GetEngine();
string m_sTestStandCfgDirectory = Engine1.GetTestStandPath(TestStandPaths.TestStandPath_Config);
// Engine clean up.
Engine1.UnloadAllModules();
Engine1.UnloadTypePaletteFiles();
Engine1.ShutDown(true);
applicationObj.Shutdown();

TSHelper.DoSynchronousGCForCOMObjectDestruction();
Marshal.FinalReleaseComObject(Engine1);
Engine1 = null;
applicationObj = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();

AppDomain.Unload(appDomain);
}

 

 

 

Kindest regards,

0 Kudos
Message 1 of 7
(1,124 Views)

@R0mm29 wrote:

[...]

 

My problem is that as far as I don't close my application, the assemblies from the first TS Engine are still loaded and the new Engine which is created is still from the old version of TS.

 

 


Do I get this right, that you are trying to switch the TestStand Version while there is still an application / engine of the old version running?

0 Kudos
Message 2 of 7
(1,087 Views)

Yes there is the order of the operations :

1) Launch an application (Assemblies are loaded)

2) Sart Engine in one version of TestStand

3) Stop the Engine and the COM object

4) Change the active version of TestStand

5) Start Engine in the new version -> the issue is in this step, it still start an Engine in the old version of TestStand

0 Kudos
Message 3 of 7
(1,067 Views)

so my interpretation is that as long as you keep the application running , the engine / COM objects can not be released completely, that's why you are seeing this issue

 

May I ask for your use-case? Maybe there is a different of implementing what you are trying to achieve 

0 Kudos
Message 4 of 7
(1,064 Views)

I use the Engine to create StepTypes and TypePalettes in a specific version of TS and then to know in which directories to copy the generated files. It also helps to know if it's a TestExec.ini (before TS2016) or GeneralEngine.cfg (after TS2016) because I modify this file. 

0 Kudos
Message 5 of 7
(1,055 Views)

I'm more of a LabVIEW guy, so my C# / COM whatever knowledge is limited...

 

The TestStand Version selector is actually modifiying some registry key upon switching version. I guess this fails, because some objects are not properly released. 

 

 

 

 

0 Kudos
Message 6 of 7
(1,043 Views)

Thanks for the help. I will check this part again but I don't see what more I can do to release the objects. 

0 Kudos
Message 7 of 7
(1,030 Views)