[virt-tools-list] [PATCH virt-viewer 1/4] Add a Windows command line wrapper

Marc-André Lureau marcandre.lureau at gmail.com
Mon Apr 2 21:56:59 UTC 2012


Add a small command line wrapper, to be able to call GUI/windows application from the console
---
 src/Makefile.am               |    4 ++
 src/windows-cmdline-wrapper.c |   91 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 95 insertions(+), 0 deletions(-)
 create mode 100644 src/windows-cmdline-wrapper.c

diff --git a/src/Makefile.am b/src/Makefile.am
index ba0a8bf..d47cc09 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -114,6 +114,10 @@ MANIFESTDIR = $(srcdir)
 EXTRA_DIST += $(VIRT_VIEWER_RES)
 
 if OS_WIN32
+bin_PROGRAMS += windows-cmdline-wrapper
+window_cmdline_wrapper_SOURCES = windows-cmdline-wrapper.c
+window_cmdline_wrapper_LDFLAGS = -lpsapi
+
 virt-viewer_rc.$(OBJEXT): $(VIRT_VIEWER_RES) $(top_builddir)/icons/virt-viewer.ico
 	$(AM_V_GEN)$(WINDRES)				\
 		-DICONDIR='\"$(ICONDIR)\"'		\
diff --git a/src/windows-cmdline-wrapper.c b/src/windows-cmdline-wrapper.c
new file mode 100644
index 0000000..510763b
--- /dev/null
+++ b/src/windows-cmdline-wrapper.c
@@ -0,0 +1,91 @@
+/*
+ * Windows cmd: a command line wrapper for GUI applications
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Usage:
+ * If your app is a GUI app compiled with -Wl,--subsystem,windows But
+ * you still want to run it from the command line to support console
+ * interaction (input, output), you can compile and install this small
+ * wrapper as a .com file next to your .exe. (.com takes precedence)
+ *
+ * This wrapper will call the .exe with the same arguments, and wait
+ * until it finished. The child process should attach to the same
+ * console and redirect standard input/output, this way:
+ *
+ *   if (AttachConsole(ATTACH_PARENT_PROCESS) != 0) {
+ *       freopen("CONIN$", "r", stdin);
+ *       freopen("CONOUT$", "w", stdout);
+ *       freopen("CONERR$", "w", stderr);
+ *       dup2(fileno(stdin), STDIN_FILENO);
+ *       dup2(fileno(stdout), STDOUT_FILENO);
+ *       dup2(fileno(stderr), STDERR_FILENO);
+ *   }
+
+ * Note: if you have a better solution for hybrid console/windows app,
+ * I would be glad to learn how!
+ *
+ * Author: Marc-André Lureau <marcandre.lureau at redhat.com>
+ */
+
+#include <windows.h>
+#include <psapi.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+    STARTUPINFO si = { 0, };
+    PROCESS_INFORMATION pi = { 0, };
+    TCHAR name[MAX_PATH];
+    DWORD len = GetModuleFileName(NULL, name, MAX_PATH);
+
+    if (len < 5) {
+        printf("Invalid process name\n");
+        exit(1);
+    } else {
+        // We expect our helper to end with .com
+        assert(strncmp(name + len - 3, "com", 4) == 0);
+        // replace .com with .exe
+        strncpy(name + len - 3, "exe", 3);
+    }
+
+    si.cb = sizeof(si);
+    if (!CreateProcess(name,
+                       GetCommandLine(),
+                       NULL,           // Process handle not inheritable
+                       NULL,           // Thread handle not inheritable
+                       FALSE,          // Set handle inheritance to FALSE
+                       0,              // No creation flags
+                       NULL,           // Use parent's environment block
+                       NULL,           // Use parent's starting directory
+                       &si,
+                       &pi)) {
+        printf("CreateProcess failed (%ld).\n", GetLastError());
+        exit(1);
+    }
+
+    // Wait until child process exits.
+    WaitForSingleObject(pi.hProcess, INFINITE);
+
+    // Close process and thread handles.
+    CloseHandle(pi.hProcess);
+    CloseHandle(pi.hThread);
+
+    return 0;
+}
-- 
1.7.7.6




More information about the virt-tools-list mailing list