Skip to content

Commit 6afe7e9

Browse files
Copilotnvuillam
andauthored
Make windowsHide configurable to support Java UI dialogs (#151)
* Initial plan * Add windowsHide configuration support with tests Co-authored-by: nvuillam <17500430+nvuillam@users.noreply.github.com> * Update README with windowsHide documentation and examples Co-authored-by: nvuillam <17500430+nvuillam@users.noreply.github.com> * Address code review feedback: improve test names and CLI flag parsing Co-authored-by: nvuillam <17500430+nvuillam@users.noreply.github.com> * changelog --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: nvuillam <17500430+nvuillam@users.noreply.github.com> Co-authored-by: Nicolas Vuillamy <nicolas.vuillamy@gmail.com>
1 parent 11aae02 commit 6afe7e9

File tree

6 files changed

+88
-2
lines changed

6 files changed

+88
-2
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
## Unreleased
44

5+
## [4.4.0] 2025-02-07
6+
57
- Add `timeout` and `killSignal` run options
8+
- Add `windowsHide` (default: true) to allow to show window if `windowHide: true` is sent
69

710
## [4.3.3] 2025-02-03
811

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ Example: `["-Xms256m", "--someflagwithvalue myVal", "-c"]`
7272
| javaArgs | List of arguments for JVM only, not the JAR or the class | `[]` | `['--add-opens=java.base/java.lang=ALL-UNNAMED']` |
7373
| [windowsVerbatimArguments](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) | No quoting or escaping of arguments is done on Windows. Ignored on Unix. This is set to true automatically when shell is specified and is CMD. | `true` | `false` |
7474
| [windowless](https://docs.oracle.com/en/java/javase/17/docs/specs/man/java.html#:~:text=main()%20method.-,javaw,information%20if%20a%20launch%20fails.) | If windowless is true, JavaCaller calls javaw instead of java to not create any windows, useful when using detached on Windows. Ignored on Unix. | false | true
75+
| [windowsHide](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) | On Windows, hide the subprocess console window that would normally be created. Set to `false` if you need Java UI dialogs to be visible (e.g., print dialogs). Ignored on Unix. | `true` | `false`
7576
| [timeout](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) | In milliseconds the maximum amount of time the process is allowed to run. | `undefined` | `1000`
7677
| [killSignal](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) | The signal value to be used when the spawned process will be killed by timeout or abort signal. | `SIGTERM` | `SIGINT`
7778

@@ -149,6 +150,23 @@ const java = new JavaCaller({
149150
const { status, stdout, stderr } = await java.run(['--sleep'], { windowless: true });
150151
```
151152

153+
Call java process with visible windows (e.g., for print dialogs)
154+
155+
```javascript
156+
const java = new JavaCaller({
157+
classPath: 'test/java/dist',
158+
mainClass: 'com.nvuillam.javacaller.JavaCallerTester'
159+
});
160+
// Set windowsHide to false to allow Java UI dialogs to be visible
161+
const { status, stdout, stderr } = await java.run([], { windowsHide: false });
162+
```
163+
164+
When using CLI mode with `--no-windows-hide` flag:
165+
166+
```bash
167+
node index.js --no-windows-hide
168+
```
169+
152170
You can see **more examples in** [**test methods**](https://github.com/nvuillam/node-java-caller/blob/master/test/java-caller.test.js)
153171

154172
## TROUBLESHOOTING

lib/cli.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,18 @@ class JavaCallerCli {
2626
const java = new JavaCaller(this.javaCallerOptions);
2727
const args = [...process.argv];
2828
args.splice(0, 2);
29-
const { status } = await java.run(args);
29+
30+
// Parse --no-windows-hide flag (remove all occurrences)
31+
const runOptions = {};
32+
const filteredArgs = args.filter(arg => {
33+
if (arg === '--no-windows-hide') {
34+
runOptions.windowsHide = false;
35+
return false; // Remove from args
36+
}
37+
return true; // Keep in args
38+
});
39+
40+
const { status } = await java.run(filteredArgs, runOptions);
3041
process.exitCode = status;
3142
}
3243
}

lib/index.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,13 @@ export interface JavaCallerRunOptions {
131131
* @default "SIGTERM"
132132
*/
133133
killSignal?: number | NodeJS.Signals;
134+
135+
/**
136+
* On Windows, hide the subprocess console window that would normally be created.
137+
* This option is ignored on Unix.
138+
* @default true
139+
*/
140+
windowsHide?: boolean;
134141
}
135142

136143
/**

lib/java-caller.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ class JavaCaller {
115115
cwd: javaExeToUse === "java" || javaExeToUse === "javaw" ? runOptions.cwd : undefined,
116116
env: Object.assign({}, process.env),
117117
stdio: this.output === "console" ? "inherit" : runOptions.detached ? "ignore" : "pipe",
118-
windowsHide: true,
118+
windowsHide: runOptions.windowsHide !== undefined ? runOptions.windowsHide : true,
119119
windowsVerbatimArguments: runOptions.windowsVerbatimArguments,
120120
};
121121
if (javaExeToUse.includes(" ")) {

test/java-caller.test.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,36 @@ describe("Call with classes", () => {
5858
checkStatus(0, status, stdout, stderr);
5959
});
6060

61+
it("should call JavaCallerTester.class with windowsHide set to false", async () => {
62+
const java = new JavaCaller({
63+
classPath: 'test/java/dist',
64+
mainClass: 'com.nvuillam.javacaller.JavaCallerTester'
65+
});
66+
const { status, stdout, stderr } = await java.run([], { windowsHide: false });
67+
checkStatus(0, status, stdout, stderr);
68+
checkStdOutIncludes(`JavaCallerTester is called !`, stdout, stderr);
69+
});
70+
71+
it("should call JavaCallerTester.class with windowsHide explicitly set to true", async () => {
72+
const java = new JavaCaller({
73+
classPath: 'test/java/dist',
74+
mainClass: 'com.nvuillam.javacaller.JavaCallerTester'
75+
});
76+
const { status, stdout, stderr } = await java.run([], { windowsHide: true });
77+
checkStatus(0, status, stdout, stderr);
78+
checkStdOutIncludes(`JavaCallerTester is called !`, stdout, stderr);
79+
});
80+
81+
it("should call JavaCallerTester.class with default windowsHide (should be true)", async () => {
82+
const java = new JavaCaller({
83+
classPath: 'test/java/dist',
84+
mainClass: 'com.nvuillam.javacaller.JavaCallerTester'
85+
});
86+
const { status, stdout, stderr } = await java.run([]);
87+
checkStatus(0, status, stdout, stderr);
88+
checkStdOutIncludes(`JavaCallerTester is called !`, stdout, stderr);
89+
});
90+
6191

6292
it("should call JavaCallerTester.class with proper stdout encoding", async () => {
6393
const java = new JavaCaller({
@@ -188,6 +218,23 @@ describe("Call with classes", () => {
188218
await javaCli.process();
189219
});
190220

221+
it("should use JavaCallerCli with --no-windows-hide flag", async () => {
222+
// Save original argv
223+
const originalArgv = process.argv;
224+
225+
// Mock process.argv to include --no-windows-hide
226+
process.argv = ['node', 'script.js', '--no-windows-hide'];
227+
228+
try {
229+
const javaCli = new JavaCallerCli("examples/cli_app/lib");
230+
await javaCli.process();
231+
checkStatus(0, process.exitCode);
232+
} finally {
233+
// Restore original argv
234+
process.argv = originalArgv;
235+
}
236+
});
237+
191238
it("Should work with an absolute path", async () => {
192239
const absolutePath = path.join(process.cwd(), "test/java/jar/JavaCallerTesterRunnable.jar");
193240

0 commit comments

Comments
 (0)