Ton Plomp Posted November 14, 2011 Report Share Posted November 14, 2011 I have an app that needs to communicate via the CMD, I think that every call into the CMD is causing quite some overhead. Does anybody know how I can keep a CMD reference open and execute commands in it, and read the output? Ton Quote Link to comment
asbo Posted November 14, 2011 Report Share Posted November 14, 2011 (edited) Hmm. Is using CMD a necessity or a crutch? You could create the target process yourself and read its output using pipes (or a slightly denser example from Microsoft). You can use the console functions to create a console and then read/write at will, but I'm not sure how easy it is to make that console a shell session. Edited November 14, 2011 by asbo 1 Quote Link to comment
crelf Posted November 15, 2011 Report Share Posted November 15, 2011 Do you need to execute, read, execute, read, etc, or can you run a bunch of commands in a batch file and then read the output when it completes? Quote Link to comment
asbo Posted November 15, 2011 Report Share Posted November 15, 2011 Do you need to execute, read, execute, read, etc, or can you run a bunch of commands in a batch file and then read the output when it completes? K.I.S.S. award goes to ... Quote Link to comment
John Lokanis Posted November 15, 2011 Report Share Posted November 15, 2011 LabVIEW does not 'normally' run as a console application. So, making it write to StdOut and StdErr is not simple. But, it can be done with some hacking (in Windows). Not sure if it is possible in OSX or Linux. But, keep in mind that you get one shot at sending in commands. The app must then process those commands, write to the StdOut and then exit. You cannot send additional commands via the CMD console. (search LAVA for a thread on this from last year) If you need continuous commands to a running application, I would suggest you write a DLL or create a web service interface for your application. The bonus of the web service is you can use something like curl on the CMD line to send and receive data and you can do that from any machine on the network. good luck! -John Quote Link to comment
Ton Plomp Posted November 15, 2011 Author Report Share Posted November 15, 2011 No I need to run an Mercurial API command, and read it's output. Sometimes I have to do this many times due to some issues out of my control, I have a hunch that opening the CMD is quite extensive. So I want to remove that overhead. Ton Quote Link to comment
asbo Posted November 15, 2011 Report Share Posted November 15, 2011 A batch file may still be a viable option - if the Mecurial executable properly sets exit codes, you may be able to handle looping logic within the batch file. Quote Link to comment
Ton Plomp Posted November 15, 2011 Author Report Share Posted November 15, 2011 It's not the looping I'm concerned about, it's more that I've got a lot of calls, that I need to route via an executable. Ton Quote Link to comment
asbo Posted November 15, 2011 Report Share Posted November 15, 2011 The multiple calls isn't an issue - that's the fundamental reason batch files exist. I was trying to get at the fact that you might be able to move some of your logic from LabVIEW into the batch file, eliminating the need for multiple call-and-returns. If that still isn't making sense, post a flowchart of your process and I'll see if it'll work in MS Batch. Quote Link to comment
FraggerFox Posted November 16, 2011 Report Share Posted November 16, 2011 (edited) It's not the looping I'm concerned about, it's more that I've got a lot of calls, that I need to route via an executable. Ton Ton, How about using the following process, for controlling any third-party executable running on cmd prompt using WinAPIs: 1) Get the third party window handle by using GetWindowHandle API. 2) Use AttachConsole() API from kernel32.dll - This would make the third party console controllable through LabVIEW 3) Use GetConsoleScreenBufferInfo() from kernel32.dll, with which you can read the console information 4) Use another function (can't remember the function name) which would write to the console 5) Repeat Step 3 and read the output for the written command in step 4 (you might need to do some string parsing to get the desired output) 6) Use FreeConsole() function from kernel32 again, to free up the console at the end of the application. This way, you don't need to redevelop the third party app in labview, rather you could re-use the cmd prompt with this method with labview and have control/read data on it. I am planning to make a small example of this and post it very soon. -FraggerFox! Edited November 16, 2011 by FraggerFox 2 Quote Link to comment
Rolf Kalbermatter Posted November 19, 2011 Report Share Posted November 19, 2011 It's not the looping I'm concerned about, it's more that I've got a lot of calls, that I need to route via an executable. Ton You could save the cmd intermediate process creation altogether by directly piping into the (Mercurial) command line tool. And if you use the OpenG Pipe functions you could potentially even use the same single mercurial command line instance to issue many commands after each other through a pipe to the stdin and receive any response through another pipe from stdout. And your hunch that process creation is quite an expensive task under Windows is quite right. And doing this through CMD really doubles that. But unless you need to also access Windows shell features, such as its build in commands, or locating an unqualified executable name in one of the PATH directories, it should be usually not a problem to directly instantiate the target command line app, by simply issuing its fully qualified exe name as first parameter, leaving out the cmd \c step completely. Quote Link to comment
asbo Posted November 19, 2011 Report Share Posted November 19, 2011 ... it should be usually not a problem to directly instantiate the target command line app, by simply issuing its fully qualified exe name as first parameter, leaving out the cmd \c step completely. As an exception, I wanted to throw out that I had an instance some weeks ago with calling an external executable (a C-based Windows 32-bit executable written by me) with System Exec.vi which would always return LabVIEW's error 2 ("Memory is full"). The situation required a relatively quick fix, so I added in the cmd /c call and it worked. I'd like to go back any figure what's going on; the EXE itself is a mere 8KB and only depends on one atypical component (bthprops.cpl). Quote Link to comment
Ton Plomp Posted April 13, 2012 Author Report Share Posted April 13, 2012 You could save the cmd intermediate process creation altogether by directly piping into the (Mercurial) command line tool. And if you use the OpenG Pipe functions you could potentially even use the same single mercurial command line instance to issue many commands after each other through a pipe to the stdin and receive any response through another pipe from stdout. I detected that Mercurial has a commandserver/pipe interface, after some debugging I got a stable 38 msec per call for the most basic call, (coming from 150 msec) so that speed improvement is pretty good. Here's the code I ended with: Do you know what the overhead per dll call is? Ton 1 Quote Link to comment
Rolf Kalbermatter Posted April 17, 2012 Report Share Posted April 17, 2012 I detected that Mercurial has a commandserver/pipe interface, after some debugging I got a stable 38 msec per call for the most basic call, (coming from 150 msec) so that speed improvement is pretty good. Here's the code I ended with: Do you know what the overhead per dll call is? Ton Well DLL call overhead is in the order of microsoeconds or less. You could experiment with the configuration of the Call Library Node and change the error reporting mode (in the extreme case to Disabled), but I doubt you would see any significant difference there. The delay is most likely in passing the command over the pipe itself and then even more in the interpretation and execution of the command in the program. And your two String Subset Functions could be replaced by a single Split String node. Quote Link to comment
the_dude Posted January 28, 2014 Report Share Posted January 28, 2014 Ton, How about using the following process, for controlling any third-party executable running on cmd prompt using WinAPIs: 1) Get the third party window handle by using GetWindowHandle API. 2) Use AttachConsole() API from kernel32.dll - This would make the third party console controllable through LabVIEW 3) Use GetConsoleScreenBufferInfo() from kernel32.dll, with which you can read the console information 4) Use another function (can't remember the function name) which would write to the console 5) Repeat Step 3 and read the output for the written command in step 4 (you might need to do some string parsing to get the desired output) 6) Use FreeConsole() function from kernel32 again, to free up the console at the end of the application. This way, you don't need to redevelop the third party app in labview, rather you could re-use the cmd prompt with this method with labview and have control/read data on it. I am planning to make a small example of this and post it very soon. -FraggerFox! FraggerFox, I'm very interested in your solution. Did you ever make an example (I'm using LV 8.6)? Corey Quote Link to comment
Jon Kokott Posted February 25, 2015 Report Share Posted February 25, 2015 (edited) If anyone stumbles across this, a better method is to use the windows .net calls. https://msdn.microsoft.com/en-us/library/system.diagnostics.process%28v=vs.110%29.aspx its probably the same thing system exec does under the hood, but you get asynchronous control of standard in, out, and err. I'm certain the performance of this will crush anything else, and all the software is already on your windows machine. ~Jon Edited February 25, 2015 by Jon Kokott 2 Quote Link to comment
123 Posted October 4, 2016 Report Share Posted October 4, 2016 Ton, How about using the following process, for controlling any third-party executable running on cmd prompt using WinAPIs: 1) Get the third party window handle by using GetWindowHandle API. 2) Use AttachConsole() API from kernel32.dll - This would make the third party console controllable through LabVIEW 3) Use GetConsoleScreenBufferInfo() from kernel32.dll, with which you can read the console information 4) Use another function (can't remember the function name) which would write to the console 5) Repeat Step 3 and read the output for the written command in step 4 (you might need to do some string parsing to get the desired output) 6) Use FreeConsole() function from kernel32 again, to free up the console at the end of the application. This way, you don't need to redevelop the third party app in labview, rather you could re-use the cmd prompt with this method with labview and have control/read data on it. I am planning to make a small example of this and post it very soon. -FraggerFox! FraggerFox, Did you make any example for this. If yes, it will be great if you share it. Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.