03-04-2013 05:58 PM
Hello,
I was wondering if it is possible to develop WPF GUI's that can be called by TestStand. Ultimately, I would like to create a WPF DLL which can be called by TestStand and fed parameters back and forth.
At the moment I'm trying to just do a very simple WPF form (no parameters, just a message in a window), however, I am having trouble doing this. I am able to create the DLL in Visual Studio 2010 but when I try to call it in TestStand, it does not seem to work. I'm also not sure if I am using the correct Action Adapter. I tried calling it as a .NET adapter but when I do I get the following error:
An exception occurred inside of the call to .NET member 'UserControl1':
System.InvalidOperationException: The calling thread must be STA, because many UI components require this.
at System.Windows.Input.InputManager..ctor()
at System.Windows.Input.InputManager.GetCurrentInputManagerImpl()
at System.Windows.Input.KeyboardNavigation..ctor()
at System.Windows.FrameworkElement.FrameworkServices..ctor()
at System.Windows.FrameworkElement.EnsureFrameworkServices()
at System.Windows.FrameworkElement..ctor()
at System.Windows.Controls.Control..ctor()
at WpfControlLibrary1.UserControl1..ctor() in c:\users\mcooblal\documents\visual studio 2010\Projects\WpfControlLibrary1\WpfControlLibrary1\UserControl1.xaml.cs:line 22
I can attach files if that helps, just let me know. In the meantime, I'm going to keep looking for solutions.
Thanks!
Mukesh.
03-05-2013 09:48 AM
The error says, "The calling thread must be STA, because many UI components require this".
STA is a COM/ActiveX threading model. By default, TestStand threads use MTA rather than STA. Using a sequence call step with its execution option set to "new thread" you can call a sequence using an STA (Single Threaded-Apartment) thread by checking the option for it on the advanced panel of the module settings. You will then likely want a "wait" step immediately after the sequence call to wait for the thread to complete before continuing.
Another alternative is to do the equivalent in your .NET code module (i.e. create a new STA thread internally in your .NET code and have that run your dialog, while the original thread waits for it to complete).
Hope this helps,
-Doug
10-20-2020 06:45 PM
This is not a reply with answer, but more of a call to NI to provide more examples using TestStand with WPF. Even better... release some plans on how this will work with WinUI and .NET Core. NI, your customers are waiting/listening. Thanks
02-08-2021 10:03 AM
Hello,
Since I experienced the same concern, here's an example that worked for me in a quick test with TS2019 (my main window is declared in Win.xaml):
public static void TestStandLaunchWPF()
{
Thread t = new Thread(() =>
{
var w = new Win();
w.ShowDialog();
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
}
Regards
02-13-2021 10:07 AM
Thanks @thumble. This worked for me, as well.
03-05-2021 10:03 PM
By any chance did you try to make the wpf modal?
It seems it does not work.
I tried inside the thread and outside. Calling from another library and from inside the library that contains the WPF.
I checked the example from NI and they use forms and seems to work just like in CVI and LabVIEW.
Any advice?
03-08-2021 01:12 AM
Hello, what do you mean by "make the wpf modal" ?
03-08-2021 09:11 PM
I mean make the WPF dialog modal to teststand. I make it work on forms but cant on WPF.
03-09-2021 12:46 AM
OK, my sample blocks TestStand execution in the calling step, but to make the windows modal you may look at https://www.codeproject.com/tips/226984/make-a-wpf-dialog-window-as-application-modal.
HAGD
03-09-2021 07:01 PM
Actually I mean using the teststand API.
I used your example with some success, but I also want to to it modal to teststand like this.
public static void ShowSerialDialogWPF(SequenceContext seqContext, out string serialNumber, out bool continueTesting)
{
Engine engine = seqContext.Engine;
bool shoudAbort = false;
int modalId = 0;
bool continueTest = false;
string currentSerial = "AllFail";
modalId = engine.NotifyStartOfModalDialogEx(seqContext, out shoudAbort);
System.Threading.Thread uiThread = new System.Threading.Thread(() =>
{
continueTest = UserInterface(out currentSerial);
});
uiThread.SetApartmentState(System.Threading.ApartmentState.STA);
uiThread.Start();
uiThread.Join();
continueTesting = continueTest;
serialNumber = currentSerial;
engine.NotifyEndOfModalDialog(modalId);
bool UserInterface(out string selectedSerialNumber)
{
SerialDialog userInterfaceDialog = new SerialDialog();
userInterfaceDialog.ShowDialog();
selectedSerialNumber = userInterfaceDialog.Serial;
return userInterfaceDialog.ContinueTesting;
}
}
As you can see I want to use
modalId = engine.NotifyStartOfModalDialogEx(seqContext, out shoudAbort);
But with no success in WPF
I was successful in windows forms but not WPF.