mikrocontroller.net

Forum: PC-Programmierung Shell ersetzen in Windows 2000/XP


Autor: Minetti (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin.

Man kann mit Hilfe der Registry in Windows 2000/XP bestimmen, mit 
welcher Shell Windows starten soll. Normalerweise ist das der Explorer, 
es lassen sich aber auch andere Programme angeben.

Der Schlüssel ist unter
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows 
NT\CurrentVersion\Winlogon]
und heisst Shell.

Trägt man dort zB cmd.exe ein, startet Windows nach dem Login nur die 
Kommandozeile und zeigt lediglich ein eventuell eingestelltes 
Hintergrundbild auf dem Desktop an. Die Taskleiste und alle 
Desktopsymbole sind verschwunden. Für meine Anwendung als Kiosksystem 
ist das ideal.

Nun möchte ich 2 Java Programme starten und habe mir dafür eine kleine 
Launcher exe geschrieben, die so aussieht:
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include "Shlwapi.h"

int main(int argc, char *argv[])
{
  FILE * fp;
  char fullpath[1024];
  char path[1024];
  
  int pos = 0;
  
  fp = fopen("programs.ini", "r");
  
  if (fp)
  {
    while (fgets(fullpath, sizeof(fullpath), fp))
    {
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
        
      ZeroMemory( &si, sizeof(si) );
      si.cb = sizeof(si);
        ZeroMemory( &pi, sizeof(pi) );
              
        printf("*******************************************************************************\n");
      printf("Launching:  %s\n", fullpath);
        printf("*******************************************************************************\n");
      // Pfad ausführen
      
      if( !CreateProcess( NULL,   // No module name (use command line)
              fullpath,        // Command line
              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,            // Pointer to STARTUPINFO structure
              &pi )           // Pointer to PROCESS_INFORMATION structure
          ) 
        {
            printf( "CreateProcess failed (%d)\n", GetLastError() );
            return 0;
        }
    }

    fclose(fp);
  }
  
    system("PAUSE");
    return 0;
}

In der Datei programs.ini steht
java -classpath hsqldb.jar org.hsqldb.Server -database.0 
file:hsqldb/fabu/fabu -dbname.0 fabu

und in weiteren Zeilen noch mehr, aber zum Testen reicht es. Starte ich 
nun das Programm per Kommandozeile oder Doppelklick, wird das Java 
Programm con CreateProcess gestartet und ich sehe die 
Kommandozeilenausgabe.

Trage ich meine Exe als Shell ein, wird sie auch gestartet, es steht 
aber nur "Drücken Sie eine beliebige Taste . . ." (die Wirkung von 
system("PAUSE");) und java startet nicht und man sieht demzufolge auch 
keine Ausgaben. Ich kann aber sofort im Anschluss die Exe nochmal per 
Taskmanager ausführen lassen, dann startet java ganz normal.

Hat jemand ne Idee, was ich machen muss, damit die java Prozesse richtig 
erzeugt werden? Die exe liegt auch in demselben Verzeichnis wie die java 
Klassen.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du könntest den "PAUSE"-Murks auch hinter der Zeile mit der 
Fehlerausgabe einbauen, dann würdest Du sehen, ob und wenn welche 
Fehlermeldung ausgegeben wird.

Autor: Jorge (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wer hsqldb bentuzen muss tut mir leid. Das ist ein schlechtes System von 
Bugfaces entwickelt. Wie wärs mit "derby.jar". Das ist performant und es 
hält was es verspricht (konform, kleine jar, grosse Datenbestände).

Du könntest dein Java-Programm als Systemdienst starten, dafür gibt es 
mehrere fertige Lösungen (Tomcat hat sowas). In diesem Zusammenhang wird 
dein Problem auch beschrieben und gelöst.

In Visual C++ einen Systemdienst zu generieren geht einfach via Wizard 
("ATL Com Anwendungsassistent... Dienst..."). Natürlich kann man auch 
alles zu Fuss machen und ist auch kein grosser Aufwand (s.a. 
www.codeguru.com). Dein Problem wird dadurch aber nicht gelöst.

Der Vorteil von Systemdiensten ist, dass sie fensterlos sind und damit 
wirst du dann deinen "Hänger" los. Alles dies ist mir noch so ungefähr 
in Erinnerung geblieben, liegt aber leider schon zu lange zurück.


Hilfreich in diesem Zusammenhang:
http://netez.com/2xExplorer/shellFAQ/bg_shell.html...

Gruss



Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann man keine Batch-Datei als Shell angeben? ;)

Autor: Minetti (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Batch Datei hab ich versucht, funktionierte aber nicht. Es gab zwar 
irgendwelche Aktionen, aber das Kommandofenster war schneller weg als 
ich schauen konnte.

Das Problem mit dem Code oben ist der Dateizugriff. Der scheint nicht zu 
klappen, wenn das Programm von Windows gestartet wird. Vielleicht könnte 
man mal schauen, in welchem Verzeichnis man wirklich gestartet wird, für 
mein konkretes Problem hab ich es jetzt so gebaut:
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <string>
#include "Shlwapi.h"

using std::string;

int main(int argc, char *argv[])
{
  char cpath[1024];

  int count = 2;
  string paths[count];
  string pathenv = "D:\\Eigene Dateien\\FB\\Demo"; // no tailing backslash
  paths[0] = "java -classpath hsqldb.jar org.hsqldb.Server -database.0 file:hsqldb/fabu/fabu -dbname.0 fabu";
  paths[1] = "java -classpath looks-2.0.4.jar;jsuntimes-0.3.jar;hsqldb.jar;. Start";
    
  for (int i=0; i<count; i++)
  {
      STARTUPINFO si;
    PROCESS_INFORMATION pi;
          
    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );
          
       strncpy(cpath, paths[i].c_str(), sizeof(cpath));
       
    printf("*******************************************************************************\n");
    printf("Launching:  %s\n", cpath);
    printf("*******************************************************************************\n");
       
    if( !CreateProcess( NULL,   // No module name (use command line)
            cpath,        // Command line
            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
            pathenv.c_str(),           // starting directory 
            &si,            // Pointer to STARTUPINFO structure
            &pi )           // Pointer to PROCESS_INFORMATION structure
        ) 
      {
      printf( "CreateProcess failed (%d)\n", GetLastError() );
      }
    
    Sleep(100);    
  }  

//    system("PAUSE");
    return 0;
}

Ist zwar schleifentechnisch äusserst hässlich, tut aber. Muss nochmal 
schauen, ob ich es irgendwie doch so bauen kann, dass die zu startenden 
Pfade aus einer externen Textdatei gelesen werden können.

Autor: Schrumpfschlauch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum benutzt du nicht das JNI, um die Java-Programme aus C heraus zu 
starten? Beispiele gibts da genug im Weltnetz!

Autor: Minetti (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, und nun hab ich auch noch rausgefunden, warum das fopen nicht 
funktionierte: Ganz einfach, wenn Windows die Exe startet, führt sie die 
in der Umgebung von c:\ aus. So geht ein fopen ohne komplette Pfadangabe 
in die Hose. Man bekommt den kompletten Pfad jedoch an main übergeben, 
kann den dann da rausfummeln und zum öffnen der Datei benutzen.

Sieht jetzt also so aus:
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <string>
#include "Shlwapi.h"

using std::string;

int main(int argc, char *argv[])
{
  printf("EXE: %s\n", argv[0]);

  char command[1024] = {0};
  char envpath[1024] = {0};  
  strncpy(envpath, argv[0], sizeof(envpath)-1);  
  int pos = strlen(envpath);
    
  while (pos > 0 && envpath[pos] != '\\')
  {
    envpath[pos--] = '\0';
  }
  
  printf("PATH: %s\n", envpath);
  SetCurrentDirectory (envpath);
  
  FILE * fp = fopen("programs.ini", "r");
  
  if (fp)
  {
    while (fgets(command, sizeof(command), fp))
    {
      StrTrim(command, "\r\n ");
      
      if (strlen(command) == 0)
      {
        continue;
      }
      
        STARTUPINFO si;
      PROCESS_INFORMATION pi;
          
      ZeroMemory( &si, sizeof(si) );
      si.cb = sizeof(si);
      ZeroMemory( &pi, sizeof(pi) );
       
      printf("*******************************************************************************\n");
      printf("Launching:  %s\n", command);
      printf("*******************************************************************************\n");
       
      if( !CreateProcess( NULL,   // No module name (use command line)
              command,        // Command line
              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
          envpath,        // Use parent's starting directory 
              &si,            // Pointer to STARTUPINFO structure
              &pi )           // Pointer to PROCESS_INFORMATION structure
          ) 
        {
        printf( "CreateProcess failed (%d)\n", GetLastError() );
        }
    
      Sleep(100);          
    }
    
    fclose(fp);
  }
//    system("PAUSE");
    return 0;
}


War JNI nicht der Weg, um von Java auf nativen Code zugreifen zu können? 
Das ist ja dann die falsche Richtung.

So wie oben tut es jetzt genau wie es soll und ist auch noch für andere 
Anwendungsfälle geeignet, in denen die zu startenden Programme nicht 
Java sind. Als Erweiterung könnte man noch die Umgebungspfade für jedes 
Programm explizit setzen.

Autor: Schrumpfschlauch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>War JNI nicht der Weg, um von Java auf nativen Code zugreifen zu können?
>Das ist ja dann die falsche Richtung.

JNI ist für beide Richtungen. Man kann damit auch problemlos deine 
Richtung beschreiten. Aber wenn jetzt funktioniert => umso besser für 
dich!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.