Example Code

Passing Custom Command Line Arguments to a TestStand Operator Interface (CVI)

Code and Documents

Attachment

Overview

The TestStand Application Manager supports processing custom command line arguments through the ProcessUserCommandLineArguments event. This can prove useful when automating test execution from a CI server.

Description

 

This example is similar to the LabWindows/CVI Basic User Interface, but has been modified to accept the following command line arguments:

Option Purpose
/SimulateFailure <failures> When used with the included example sequence file, this suppresses the simulation dialog and instead simulate failures as specified. This argument accepts the following parameters:
  • Keyboard
  • Video
  • Power
  • CPU
  • ROM
  • RAM
If no parameters are specified, then all components are simulated to pass.

 

This example demonstrates the following concepts:

  • Using TSUI__ApplicationMgrEventsRegOnProcessUserCommandLineArguments to handle custom command line arguments
    Spoiler
    HRESULT CVICALLBACK ApplicationMgr_OnProcessUserCommandLineArguments(CAObjHandle caServerObjHandle, void *caCallbackData, VBOOL  processCommand, TSUIObj_Strings  arguments, long *currentArgument, enum TSUIEnum_ProcessCommandLineErrors *errorProcessing, char **errorMessage)
    {
    	int 	error = 0;
    	long 	numArgs = 0;
    	int 	offset = 0;
    	char 	*currentArg = NULL;
    	char 	**simFails = NULL;
    	
    	tsErrChk(TSUISUPP_StringsGetCount ((CAObjHandle)arguments, &errorInfo, &numArgs)); 
    	tsErrChk(TSUISUPP_StringsGetItem ((CAObjHandle)arguments, &errorInfo, *currentArgument, &currentArg));
    	
    	if (strcmp(currentArg, "/SimulateFailure") == 0)
    	{
    		*currentArgument += 1;
    		offset = numArgs - *currentArgument;
    		simFails = calloc (numArgs-*currentArgument, sizeof(char*));
    		
    		for (int i = 0; i  < offset; i++)
    		{
    			tsErrChk(TSUISUPP_StringsGetItem ((CAObjHandle)arguments, &errorInfo, *currentArgument, &simFails[i]));
    		
    			if (strcmp(simFails[i],"Keyboard")==0)
    			{
    				if (processCommand == VTRUE)
    					fails.Keyboard = 4;
    				*currentArgument += 1;
    			}		
    			else if (strcmp(simFails[i],"Video")==0)
    			{
    				if (processCommand == VTRUE)
    					fails.Video = 15;
    				*currentArgument += 1;
    			}
    			else if (strcmp(simFails[i],"Power")==0)
    			{
    				if (processCommand == VTRUE)
    					fails.Power = VTRUE;
    				*currentArgument += 1;
    			}
    			else if (strcmp(simFails[i],"CPU")==0)
    			{
    				if (processCommand == VTRUE)
    					fails.CPU = VTRUE;
    				*currentArgument += 1;
    			}
    			else if (strcmp(simFails[i],"ROM")==0)
    			{
    				if (processCommand == VTRUE)
    					fails.ROM = VTRUE;
    				*currentArgument += 1;
    			}	
    			else if (strcmp(simFails[i],"RAM")==0)
    			{
    				if (processCommand == VTRUE)
    					fails.RAM = VTRUE;
    				*currentArgument += 1;
    			}
    			else
    			{
    				break;
    			}	
    		}
    	}
    	else
    	{   
    		char buf[1024];
    		*errorProcessing = TSUIConst_ProcessCommandLineError_CustomError;
    		CA_FreeMemory(*errorMessage);
    		*errorMessage = CA_AllocMemory(sizeof(buf));
    		Fmt(buf, "%s<%s%s", "Invalid command line argument: ",currentArg);
    		strncpy (*errorMessage, buf, 1024);
    	}
    	
    Error:
    	free(simFails);
    	DisplayError(error);
    	return error < 0 ? E_FAIL : S_OK;
    }
  • Modifying a TestStand user interface to print UI error messages to the console and set the return code appropriately
    Spoiler
    static void DisplayError(int errorCode)
    {
    	if (errorCode < 0)
    	{
    		printf("Error: %d  %s",errorCode,errMsg);		
    		TSUI_ApplicationMgrSetExitCode (gMainWindow.applicationMgr, NULL, errorCode);
    
    	}
    }
  • Use of the TSUI_ApplicationMgrAddCommandLineArgumentsHelp function to add custom command line arguments help.
    Spoiler
    tsErrChk( TSUI_ApplicationMgrAddCommandLineArgumentsHelp (gMainWindow.applicationMgr, &errorInfo, "[/SimulateFailure <failures>]", "<failures>: components to fail separated by spaces.\nvalid parameters are: Keyboard, Video, Power, CPU, ROM, & RAM", ""));
  • Creating a custom UI Message handler to pass command line data to sequence execution.
    Spoiler
    HRESULT CVICALLBACK ApplicationMgr_OnUserMessage (CAObjHandle caServerObjHandle, void *caCallbackData, TSUIObj_UIMessage  uiMsg)
    {
    	int error = 0;
    	LPUNKNOWN tempPropObject = 0;
    	CAObjHandle SeqContext = 0;
    	enum TSEnum_UIMessageCodes msgEvent;
    	
    	tsErrChk( TS_UIMessageGetEvent (uiMsg, &errorInfo, &msgEvent));
    	tsErrChk( TS_UIMessageGetActiveXData (uiMsg, &errorInfo, &tempPropObject));
    	CA_CreateObjHandleFromInterface (tempPropObject, &IID_IUnknown, 0, LOCALE_NEUTRAL, 0, 0, &SeqContext);
    	
    	if (msgEvent == TS_UIMsg_UserMessageBase +1)
    	{
    		tsErrChk( TS_PropertySetValBoolean 	( SeqContext, &errorInfo, "Locals.UiMsgHandled", 0, VTRUE));
    		tsErrChk( TS_PropertySetValNumber 	( SeqContext, &errorInfo, "Locals.KeyboardValue", 0, fails.Keyboard));
    		tsErrChk( TS_PropertySetValNumber 	( SeqContext, &errorInfo, "Locals.VideoValue", 0, fails.Video));
    		tsErrChk( TS_PropertySetValBoolean 	( SeqContext, &errorInfo, "Locals.PowerFail", 0, fails.Power));
    		tsErrChk( TS_PropertySetValBoolean 	( SeqContext, &errorInfo, "Locals.CPUFail", 0, fails.CPU));
    		tsErrChk( TS_PropertySetValBoolean 	( SeqContext, &errorInfo, "Locals.ROMFail", 0, fails.ROM));
    		tsErrChk( TS_PropertySetValBoolean 	( SeqContext, &errorInfo, "Locals.RAMFail", 0, fails.RAM));
    	}
    	
    Error:
    	
    	CA_DiscardObjHandle(SeqContext);
    	DisplayError(error);
    	return error < 0 ? E_FAIL : S_OK;	
    }

Note: By default, TestStand shows dialogs under certain conditions. This can cause hangs when automating sequence execution without user input, such as when ran from a CI Server. In order to prevent popups that require user input, configure the following options:

  • Disable User Management or automatically log in the System User
  • Set the 'Station Options » Execution »  On Run-Time Error' setting to something other than 'Show Dialog', such as 'Run Cleanup'.
  • Specify 'Station Options » Time Limits' for Exiting and Normal Execution such that the user will not be prompted.
  • Pass the /quit argument via the command line so TestStand automatically shuts down after all executions are complete.

Hardware and Software Requirements

TestStand 2014 SP1 or later

LabWindows/CVI 2015 or later

Steps to Implement or Execute Code

  1. Unzip the attached code, open the .cws, and build the project for the bitness of TestStand you have.
  2. Open a command window in the <ExampleDir>\ModifiedBasicOI_CVI directory (Shift + Right Click » Open command window here).
  3. In order to see the Command Line help, run:

    TestExec /?

  4. Experiment with the /SimulateFailure argument. For example:

    TestExec /runEntryPoint "Single Pass" "<ExampleDir>\TestSequence\Computer Motherboard Test Sequence.seq" /SimulateFailure Keyboard Video RAM /quit

https://www.linkedin.com/in/trentweaver

Example code from the Example Code Exchange in the NI Community is licensed with the MIT license.

Contributors