Java unter Tomcat, grafische Gui-Anwendung und ein C++ Wrapper

von   3 Kommentare

Ein externes Programm aufzurufen ist in den meisten Programmiersprachen kein Problem. So auch in Java nicht. In Java sieht das grundsätzlich so aus:

Runtime.getRuntime.exec( "/pfad/zum/program" );

Jetzt muß man aber natürlich auch die Randbedingungen im Auge behalten. Geht es zum Beispiel um Java innerhalb von Tomcat, hat das für eine Anwendung mit Oberfläche natürlich Auswirkungen. Prinzipiell wird Tomcat als Dienst laufen, ob das jetzt unter Linux oder Windows ist, dürfte für das grundsätzliche Problem keine Rolle spielen.
Als Dienst hat Tomcat beziehungsweise der Java Prozess nicht einfach die Rechte, eine Gui zu starten, mal abgesehen davon, dass auf einem Server nicht sichergestellt ist, dass es eine grafische Schnittstelle gibt. Hier sei die Wartung eines Windows-Servers per Remotedesktop im Vergleich zur SSH/Konsolen Wartung eines Linux Servers als Beispiel erwähnt.

Das heisst, stellt das starten der externen (grafischen) Anwendung aus einem Desktop-Java-Prozess kein Problem dar, sieht das auf einem Server unter Umständen anders aus.

Unter Linux kann man den Zugriff eines anderen Nutzers (unter dem der Service-Prozess) auf den X-Server mit xhost erlauben (das war jetzt aus dem Gedächtnis). In diesem Fall geht es aber um einen Dienst unter Windows.

service-interaktion-desktop-erlauben

Auch Windows hält hierfür Boardmittel bereit: In der Diensteverwaltung kann man die Eigenschaften des Dienstes bearbeiten. Unter dem Reiter “Login” gibt es den Punkt “Datenaustausch zwischen Dienst und Desktop” erlauben. Aktiviert man den Haken, kann auch ein Serverprozess eine grafische Anwendung, wie z.B. Word oder Excel starten.

Oftmals wird dieser Haken, aber nicht das Mittel der Wahl sein. Zum Beispiel, weil das Erscheinen der grafischen Oberfläche der Anwendung nicht erwünscht ist oder auf dem Server schlicht niemand angemeldet ist/sein soll (auf einem logischerweise Server auch nicht unüblich). In dieser Situation ist man mit javaeigenen Mitteln am Ende angelangt. In C# beispielsweise kann man eine Anwendung als invisible/nicht sichtbar starten. Diese Möglichkeit bietet Java nicht an. Um dies zu erreichen muß man sich mit einem Wrapper behelfen. Für Windows-Programm gibt es die sog. Exe-Header, in diese kann man ebenfalls eintragen, dass die Anwendung nicht sichtbar sein soll. Hierzu kommt das SW_HIDE Flag zum Einsatz. Folgender C++ Code, ruft eine Anwendung auf und setzt für diese das SW_HIDE Flag. Damit dieses greift, muss aber in jedem Fall auch das dwFlag STARTF_USESHOWWINDOW gesetzt sein.

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
 
void _tmain( int argc, TCHAR *argv[] )
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
 
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
si.wShowWindow = SW_HIDE;
si.dwFlags=STARTF_USESHOWWINDOW;
 
 
ZeroMemory( &pi, sizeof(pi) );
 
if( argc != 2 )
{
printf("Usage: %s [cmdline]\n", argv[0]);
return;
}
 
// Start the child process. 
if( !CreateProcess( NULL,   // No module name (use command line)
argv[1],        // Command line
NULL,           // Process handle not inheritable
NULL,           // Thread handle not inheritable
FALSE,          // Set handle inheritance to FALSE
CREATE_NO_WINDOW,              // No creation flags
NULL,           // Use parent's environment block
NULL,           // Use parent's starting directory 
&si,            // Pointer to STARTUPINFO structure
&pi )           // Pointer to PROCESS_INFORMATION structure
) 
{
printf( "CreateProcess failed (%d).\n", GetLastError() );
return;
}
 
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
 
// Close process and thread handles. 
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}

Diesen C++-Schnipsel kann man z.B. mit dem freien Borland C++ Compiler übersetzen und erhält somit einen universellen Wrapper, um Programme mit dem SW_HIDE Flag zu starten.

Allerdings kann es sein, dass auch das nicht reicht. Aus unerfindlichen Gründen war es bei mir notwendig die gewünschte Anwendung nicht unter dem Windows System User, unter dem Tomcat standardmäßig läuft, sondern unter einem anderen lokalen User laufen zu lassen. Selbiges lässt sich aber auch in oben bebildertem Dialog einstellen.

Mit diesen Mitteln war es mir möglich aus Java mittels des C++ Wrappers eine grafische Anwendung zu starten, ohne dass ein Benutzer angemeldet sein muss.


Tags: , , , ,

3 Kommentare zu “Java unter Tomcat, grafische Gui-Anwendung und ein C++ Wrapper”

  1. Peter Frühberger Germany Mozilla Firefox Ubuntu Linux 61 Kommentare   am:

    Vorsicht. Andere Nutzer haben potentiell andere (höhere) Rechte. Dass ein Tomcat in einer Art chroot läuft, hat schon seinen Sinn.

  2. crash Germany Opera Windows 365 Kommentare   am:

    Ich meinte ja nicht einen beliebigen anderen Nutzer, sondern eher einen speziell für den Tomcat eingerichteten. Dass das nicht die optimale Lösung ist, ist klar, aber leider nicht anders lösbar gewesen.

  3. wo kann ich Germany Internet Explorer Windows 1 Kommentar   am:

    “In C# beispielsweise kann man eine Anwendung als invisible/nicht sichtbar starten” – danke! *g*

Kommentar hinterlassen

Ja, ich möchte bei Kommentaren benachrichtigt werden!