darlingtonia
darlingtonia

Reputation: 13

How to route Matlab input to specific DOS cmd input?

I have a Matlab script that uses the dos command to open an exe. This exe pauses awaiting user input. For this project I need everything to be scripted and dynamic, so matlab has to be able to continue running its script, dynamically determine what to input to the running exe, and then input it.

So far, I have been able to get the exe to run in the background and let the matlab script continue by using dos('test.exe &'), but I cant get then get matlab to send inputs to the running exe. I have tried batch files and I still run into the same issue, which is how do I automate the sending of inputs to the cmd line when the cmd line exe running is paused awaiting user input?

My best guess would be that I need to reroute the standard output of matlab to the standard input of a specific, already open instance of cmd, but I have no idea how to do that and have been unable to find anything so far on the internet. Any insight would be greatly appreciated, thanks.

Upvotes: 1

Views: 196

Answers (3)

darlingtonia
darlingtonia

Reputation: 13

Thanks to the wonderful explanation by Luis Mendo, I have quickly put together a function that takes a string input and outputs the proper robot commands. It works for me!

function typeStringOut(robot,text)

keyMatch = {};
keyMatch(1,:) = {'`','-','=',',','.','/',';','[',']','\'};
keyMatch(2,:) = {'~','_','+','<','>','?',':','{','}','|'};
keyMatch(3,:) = {'BACK_QUOTE','MINUS','EQUALS','COMMA','PERIOD','SLASH','SEMICOLON','OPEN_BRACKET','CLOSE_BRACKET','BACK_SLASH'};
numKeyMatch = {};
numKeyMatch(1,:) = {'1','2','3','4','5','6','7','8','9','0'};
numKeyMatch(2,:) = {'!','@','#','$','%','^','&','*','(',')'};

for i=1:length(text)
    if isstrprop(text(i),'alpha')
        if isstrprop(text(i),'upper')
            robot.keyPress(java.awt.event.KeyEvent.VK_SHIFT);
        end
        eval(['robot.keyPress(java.awt.event.KeyEvent.VK_',upper(text(i)),');']);
        if isstrprop(text(i),'upper')
            robot.keyRelease(java.awt.event.KeyEvent.VK_SHIFT);
        end
    elseif isstrprop(text(i),'digit')
        eval(['robot.keyPress(java.awt.event.KeyEvent.VK_',text(i),');']);
    elseif isstrprop(text(i),'wspace')&&strcmp(text(i),' ')
        eval('robot.keyPress(java.awt.event.KeyEvent.VK_SPACE);');
    elseif isstrprop(text(i),'punct')||isstrprop(text(i),'graphic')
        switch text(i)
            case {'`','-','=',',','.','/',';','[',']','\'}
                matchIdx = strcmp(keyMatch(1,:),text(i));
                eval(['robot.keyPress(java.awt.event.KeyEvent.VK_',keyMatch{3,matchIdx},');']);
            case {'~','_','+','<','>','?',':','{','}','|'}
                robot.keyPress(java.awt.event.KeyEvent.VK_SHIFT);
                matchIdx = strcmp(keyMatch(2,:),text(i));
                eval(['robot.keyPress(java.awt.event.KeyEvent.VK_',keyMatch{3,matchIdx},');']);
                robot.keyRelease(java.awt.event.KeyEvent.VK_SHIFT);
            case {'!','@','#','$','%','^','&','*','(',')'}
                robot.keyPress(java.awt.event.KeyEvent.VK_SHIFT);
                matchIdx = strcmp(numKeyMatch(2,:),text(i));
                eval(['robot.keyPress(java.awt.event.KeyEvent.VK_',numKeyMatch{3,matchIdx},');']);
                robot.keyRelease(java.awt.event.KeyEvent.VK_SHIFT);
            otherwise
                error([text(i),' is unknown character']);
        end

    elseif strcmp(text(i),'<')||strcmp(text(i),'>')
        robot.keyPress(java.awt.event.KeyEvent.VK_SHIFT);
        matchIdx = strcmp(keyMatch(2,:),text(i));
        eval(['robot.keyPress(java.awt.event.KeyEvent.VK_',keyMatch{1,matchIdx},');']);
        robot.keyRelease(java.awt.event.KeyEvent.VK_SHIFT);
    else
        error([text(i),' is unknown character']);
    end
end

robot.keyPress(java.awt.event.KeyEvent.VK_ENTER);
robot.keyRelease(java.awt.event.KeyEvent.VK_ENTER);

end

Upvotes: 0

LowPolyCorgi
LowPolyCorgi

Reputation: 5171

Unfortunately there is no way to do what you are describing.

The fact that the external program pauses and awaits for an input is a serious challenge: for Matlab, there is just a program running in the background, and it has no way to "know" that this program is awaiting for an input at a given moment.

Then, another issue is that there is no "Matlabish" way to send a command to a running thread send in the background. edit The solution proposed by Luis is ugly but works for this.

If you can modify the external program, then you can certainly avoid the problem by defining a different protocol for input tranfer, like TCP/IP. But it's not a general answer and I guess you don't have such a possibility.

You could try to use Sikuli for this, if you are really desperate.

Upvotes: 0

Luis Mendo
Luis Mendo

Reputation: 112659

There is a way. It's just not elegant.

When you call a program with &, its window appears in the foreground and has focus (at least on my system). So you can send it keyboard events from Matlab using the java.awt.Robot class.

If you need to automatize the conversion from characters to key presses, you probably need a big switch statement along these lines. The following example defines the events manually, which is only practical for small inputs.

robot = java.awt.Robot;
dos('copy con &'); % open MS-DOS Window that will just echo the input text
pause(1) % allow some time for the external program to start up
robot.keyPress(java.awt.event.KeyEvent.VK_SHIFT);
  robot.keyPress(java.awt.event.KeyEvent.VK_H);
  robot.keyRelease(java.awt.event.KeyEvent.VK_H);
robot.keyRelease(java.awt.event.KeyEvent.VK_SHIFT);
robot.keyPress(java.awt.event.KeyEvent.VK_E);
robot.keyRelease(java.awt.event.KeyEvent.VK_E);
robot.keyPress(java.awt.event.KeyEvent.VK_L);
robot.keyRelease(java.awt.event.KeyEvent.VK_L);
robot.keyPress(java.awt.event.KeyEvent.VK_L);
robot.keyRelease(java.awt.event.KeyEvent.VK_L);
robot.keyPress(java.awt.event.KeyEvent.VK_O);
robot.keyRelease(java.awt.event.KeyEvent.VK_O);
robot.keyPress(java.awt.event.KeyEvent.VK_SHIFT);
  robot.keyPress(java.awt.event.KeyEvent.VK_1);
  robot.keyRelease(java.awt.event.KeyEvent.VK_1);
robot.keyRelease(java.awt.event.KeyEvent.VK_SHIFT);
robot.keyPress(java.awt.event.KeyEvent.VK_ENTER);
robot.keyRelease(java.awt.event.KeyEvent.VK_ENTER);

Here's an example run:

enter image description here

Upvotes: 1

Related Questions