1

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.

Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
  • Can't you pass the required data as startup arguments? – m7913d Mar 28 '17 at 19:16
  • No I can't just pass the required data as startup arguments. First of all, they aren't start up arguments, they are responses to required user input asked by the exe. Second, the inputs are dynamically generated by the matlab script after the initial exe has run, so the inputs aren't known yet – darlingtonia Mar 28 '17 at 19:57

3 Answers3

1

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

Community
  • 1
  • 1
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
  • Nice ! But you assume that the external program requires the input immediately. What if it asks for inputs "randomly"? – Ratbert Mar 29 '17 at 05:57
  • @Ratbert If the pause times are known in advance they could be easily programmed. If not, I'm not sure how any other approach could work – Luis Mendo Mar 29 '17 at 09:02
  • wow haha, this is awful, but I think it will work! Thank you so much for this, I will let you know how it goes when I implement it, but for now I think this might solve my problem – darlingtonia Mar 29 '17 at 13:02
  • Yes, it's ugly, but for simple inputs it will do :-) – Luis Mendo Mar 29 '17 at 14:06
0

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.

Ratbert
  • 5,463
  • 2
  • 18
  • 37
0

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