LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Real-time Command Line Interface (System Exec)

Hello; I've searched through the forums for an answer to this topic, but couldn't find what I was looking for.  Hence my post.

 

For reasons too long and boring to get into, our company has developed a command-line interface method of controlling our equipment and engineering test methodologies.  In fairness, it works pretty well, but there are some shortcomings which I am trying to resolve with LabVIEW.  However, to do this (without reinventing the wheel), requires that I interface to the command-line interface.

 

Now, I've read the available examples, and am able to start the process sending a command to the Sys Exec, and the nice cmd window pops up and I can see the script run normally, which is a good start.  While this script is running, I want to be able to send (within the same window) a series of real-time commands to receive UUT status updates.  In this way, I want to be able to read back the responses (while the script is still active) and display it on my LabVIEW script (eventually to automate this as a system check).

 

I've tried writing the update commands directly to the UUT via a serial interface, and the error I get is something like "the VISA resource is valid, but not available" (mainly because the script is still in communication with the UUT).

 

The questions are:

(1) Is what I'm trying to do possible with Sys Exec?

(2) If so, how do I accomplish this?

(3) If not, how else would I accomplish this?

 

So, any help on this would be, helpful!

0 Kudos
Message 1 of 11
(11,222 Views)

I don't think this is possible to do with System Exec but I think it might be possible using .NET (google turns up Process and System.IO.StreamReader) or using Pipes (??)

 

Edit - this should point you in the right direction:

CommandLineInteraction.png

 

(these might not be the right functions to use...I only glanced at the documentation - you can either read the data from the stream by polling or you can register for an event each time a line of data is received from the process)


LabVIEW Champion, CLA, CLED, CTD
(blog)
Message 2 of 11
(11,219 Views)

Have you tried to capture the Standard Output string from System Exec?  I've successfully done this with commands that return responses -- you may get back a multi-line string that you'll need to parse, but you're probably hoping for that ...

 

Bob Schor

0 Kudos
Message 3 of 11
(11,200 Views)

Thanks, Sam; hadn't yet considered dotNet... I'll give that a shot.

 

Yes Bob, I had.  Unfortunately, it's not quite that simple.  There is a cmd-line program running in the background... let's call it "SLUG".  So, to get the ball rolling, I need to enter the following into the Cmd line window:

=>slug script.ext comportnumber

So, this executes the script.exe using the SLUG program, and begins tx/rx at the given COM port.  So, this spits along happily, and as it is configuring the device, SLUG spits out info into the Cmd window.  When everything is configured, it enters a wait state until some sort of user intervention to continue or end the program (such as "C" for "Continue".  What I've found is that because of this, a simple program will not capture the data as it would in a simple "send a command, get a simple response" type scenario.  Perhaps if I selected the "Wait Until Finished" it would, but at that point, it is no further use to me.  As the SLUG program is churning away in the background, I need to periodically send a single command ("such as maybe "U" for "Update Status") to send me a update on some of the operational parameters of the UUT.  Hence the need to be able to interface to the same Cmd window (i.e. the same session) in real time.

 

If that makes sense... it made sense in my head.

 

But I'll try the dotNet thing when I get a chance.  Looking into some other options also, as the SLUG also maintains an event file, in which case any actual event is logged to file, in real time.  So, if I can set this SLUG stuff up to auto-update, and write that to file, I can simply read and parse the file contents.  IF that option is available (still waiting on that answer, in the meantime, trying this).

 

Thanks all!

0 Kudos
Message 4 of 11
(11,179 Views)

Sam, I'm trying your suggestion using .NET, but I'm having trouble locating the particular constructor... what assembly did you link it to?  Also, you mentioned documentation... can you provide a link?  Google searching for me returned a lot of C# stuff.  Sorry if this is a silly question.

0 Kudos
Message 5 of 11
(11,152 Views)

I too had trouble finding it - it's under 'System' and then 'System.Diagnostics'.

 

The picture I posted above is actually a VI snippet - you can drag it onto the block diagram in LV2013 or above and it will re-create the code for you.

 

Just look at the .NET help for 'Process', 'StreamWriter' and 'StreamReader' - it's pretty well documented online by MS.


LabVIEW Champion, CLA, CLED, CTD
(blog)
0 Kudos
Message 6 of 11
(11,122 Views)

Ok, I got curious and decided to have a bit more of a play and I'm sure it'll come in handy at some point. Using this code/snippet I'm able to open up a command prompt and send commands (using the StreamWriter write function) and view the response in the 'Output' indicator.

 

On closing the panel, it closes the process (rather than killing it!) and then releases the streams which causes the top loop to error out and exit.

 

The only thing it doesn't do is actually detect if the process is closed (e.g. if it shuts itself down) but I think this is possible by checking a property on the process ('hasexited') or using an event callback.

 

dotNETProcessExample.png


LabVIEW Champion, CLA, CLED, CTD
(blog)
Message 7 of 11
(11,107 Views)

Sam: this is huge!  My thanks.  Can't wait to get started on this!  I'll post to let know how it goes.

0 Kudos
Message 8 of 11
(11,087 Views)

That got me a lot further.  I'm able to use this to effect commands and see simple returns and such.  I'll attach my VIs for reference.

 

Still having a problem in that the "SLUG" output (i.e. program run in command line interface... mentioned in an earlier post) is not being displayed.  In a regular command line window, the output displays as it is happening, but not in this interface.  I tried to redo the StreamReader to read each individual character, but that didn't help either.  I've noticed also, that StreamReader seems to wait until there is something available in the buffer, and once it recognises something, outputs it.  I'm wondering now why the "SLUG" output shows up in a command line window and not here... maybe capture the data asynchronously?  Not making much sense to me.

 

I tried also to figure out how to register a callback for when the StreamReader has valid data in the buffer, but I gave up after a few disastrous attempts.  Reason I wanted this, was so I could stop the program without having to wait until the StreamReader output is ready (tends to hang when in use with "SLUG").  Is there an online tutorial somewhere to explain how to do this?  I read the NI.com page, and took a look at the examples, but my VI reference was always broken (do I need to save it as a strict type def or something?), and I wasn't sure how to link the two.

 

 

Message 9 of 11
(11,058 Views)

If you're not getting anything on the read, does the SLUG program actually output to STDOUT? The example I showed redirects both STDIN and STDOUT to the streams...but there is also a stream for STDERR as well. I tried a few different methods of reading and the one I used in my example seemed to work the best. There was a specific reason why I close the streams from the 'exit' case - that stops it from hanging on the read when you exit as the reference is destroyed which causes the read to error out. You probably need to have a dedicated loop for reading, which is why I implemented like I did. Reading a single character at a time was very slow for me - doing a directory listing took ages to catch up.

 

You can turn off the 'create no window' - that should show the SLUG window while it's running...of course...if you're redirecting the input/output to the stream then you won't actually see anything there - just an empty command prompt.

 

As for the callback...

 

Drop down a 'register for callback events' node, wire in the 'Process' reference to the 'event' input, select the event from the dropdown box and then right click on the callback VI terminal and click 'create callback VI' - this will open up a VI template with the appropriate terminals for the callback VI. If you unbundle the pink cluster you will have an element 'e' which contains the string data. You can then use a queue or a user event to send that data back to your main loop (you can wire whatever you like into 'user parameters' and use variant to data to convert it back to whatever data type.

 

I had a look at your VI, it's essentially the same as what I gave you but you've scattered property nodes everywhere. You can also use 'writeln' which will automatically add the return to the command, instead of needing to concatenate it.

 


LabVIEW Champion, CLA, CLED, CTD
(blog)
0 Kudos
Message 10 of 11
(11,030 Views)