I was fiddling with some code based on automation with the java.awt.Robot
class. The code was running perfectly, but when I changed a few things, some of which did not even run with main
, code seemed to partially finish it's task, but then the computer started its shutdown sequence, closing all of the programs. I was only able to stop it by clicking cancel on the "Waiting For..." screen. Do any of you have any idea why this code below could make this occur?
Again, this code worked perfectly before I added/removed/changed something.
I'm pasting it exactly as it is, incase there are any specific things causing this. Sorry for the long post.
package _defaultpackage;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import static java.awt.event.InputEvent.*;
import static java.awt.event.KeyEvent.*;//static import means we can type VK_1 instead of KeyEvent.VK_1
public class JavaRobot {
static Robot robot;
public static void main(String[] args) {
try {robot = new Robot();} catch (Exception e) {}
robot.setAutoDelay(30);
robot.setAutoWaitForIdle(true);
combination(VK_WINDOWS, VK_R);
paste("notepad");
hit(VK_ENTER);
paste("Hello World!\n123");
robot.delay(2000);
combination(VK_ALT, VK_F4);
hit(VK_RIGHT);
hit(VK_ENTER);
robot.setAutoDelay(10);
for (int i = 0; i < 700; i++) {
robot.mouseMove(i, i);
}
System.out.println("Done.");
}
static void leftClick() {
robot.mousePress(BUTTON1_MASK);
robot.delay(200);
robot.mouseRelease(BUTTON1_MASK);
robot.delay(200);
}
static void type(String s) {
byte[] bytes = s.getBytes();
for (byte b : bytes) {
int code = b;
// keycode only handles [A-Z] (which is ASCII decimal [65-90])
if (code > 96 && code < 123)
code = code - 32;
//robot.delay(40);
robot.keyPress(code);
robot.keyRelease(code);
}
}
static void hit(int i) {
robot.keyPress(i);
robot.keyRelease(i);
}
static void combination(int... i) {
for (int a : i) {
robot.keyPress(a);
}
for (int a : i) {
robot.keyRelease(a);
}
}
static void paste(String s) {
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(s), null);
combination(VK_CONTROL, VK_V);
}
static void paste(String s, int delay) {//delay is additional delay after auto robot delay
String[] letters = s.split("");
for (String a : letters) {
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(a), null);
combination(VK_CONTROL, VK_V);
robot.delay(delay);
}
}
static void pasteRestore(String s) {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable save = clipboard.getContents(null);
clipboard.setContents(new StringSelection(s), null);
combination(VK_CONTROL, VK_V);
clipboard.setContents(save, null);
}
static void pasteRestore(String s, int delay) {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable save = clipboard.getContents(null);
String[] letters = s.split("");
for (String a : letters) {
clipboard.setContents(new StringSelection(a), null);
combination(VK_CONTROL, VK_V);
}
clipboard.setContents(save, null);
}
}
I guess that the bug is in method combination()
. Take a look on it again:
static void combination(int... i) {
for (int a : i) {
robot.keyPress(a);
}
for (int a : i) {
robot.keyRelease(a);
}
}
When pressing Alt-f4 user is expected to
In your case the order of releases is the same a s order of presses. So, I'd try to re-write this method as following:
static void combination(int... c) {
for (int a : c) {
robot.keyPress(a);
}
for (int i = c.length - 1; i >=0; i--) {
robot.keyRelease(c[i]);
}
}
Try it. I hope this will work.
Additionally pay attention on these lines:
robot.setAutoDelay(30);
robot.setAutoWaitForIdle(true);
I personally never used these setters. Try to work without them. Accroding to my experience when closing windows you do not really need delay. Everything works without delay and even faster. The point is in correct order of events that you generate.