Hallo,
ich hab ein C# (WinForms) Programm. Dieses kann per Doppelklick gestartet werden -> dann soll eine Winforms Oberfläche angezeigt werden, also ganz normal.
Das Programm soll aber auch über die Console ausgeführt werden können, wobei dann Kommandozeilenparameter übergeben werden müssen. Das Programm läuft dann mit den übergebenen Parametern im "silent" mode, d.h. ohne Oberfläche-
Das funktioniert auch alles so weit.
Ein Problem habe ich jetzt, wenn das Programm über die Konsole aufgerufen wird, aber keine Command Line args übergeben wurden. Dann öffnet sich ebenfalls die Winforms Oberfläche. Es sollte dann aber ebenfalls "silent" laufen, mit default-Parametern.
Die Unterscheidung ist so umgesetzt:
static void Main(string[] args)
{
if (args == null || args.Length == 0)
{
// exe double click -> show gui
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Main(null));
}
else
{
// command line parameters -> execute in silent mode
// ...
}
}
Demnach logisch, dass die Form aufgeht. Die Frage ist, wie könnte ich es anders machen? Meine Idee wäre, irgendwie zu erkennen, dass das Programm von der Console aufgerufen wurde, ich wüsste aber nicht wie. Einfach prüfen, ob cmd.exe läuft, hilft mir nicht, da während das Programm gestartet wird, noch mehrere cmd-Instanzen laufen können.
Hat jemand eine simple Idee ?
Danke...
Entscheide Dich für eine Variante, die gestartet werden soll, wenn es keine Parameter gibt.
Aber zu erkennen, ob das über die CMD läuft (oder batch, Direktaufruf oder was auch immer) geht so nicht.
Du kannst ja auch -Forms als Parameter fordern und per default es als Console laufen lassen, oder eine Auswahl anbieten wenn es keine Parameter gibt etc etc....
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Du könntest versuchen Deine Applikation mittels der API AttachConsole
an eine Console zu binden und zu prüfen, ob das Fenster was gerade den Focus hat eine Console ist. Das ist zwar keine tolle und vollständig sichere Lösung, _könnte _aber funktionieren.
Normalerweise löst man so ein Problem, wie Abt es bereits vorgeschlagen hat, mit Übergabeparametern.
Danke für die Antwort, ich werde mir dann wohl irgendwas überlegen müssen.
Noch was Anderes dazu:
Mir ist gerade aufgefallen, dass Console.WriteLine im obigen else-Fall nur dann dann eine Consolen-Ausgabe produziert, wenn cmd.exe als Administrator gestartet wurde. Hat cmd.exe keine Admin-Rechte werden die Konsolenausgaben einfach ignoriert.
Gibt es dafür einen bestimmten Grund und eine Möglichkeit das zu umgehen ?
Über eine manifest-Datei sorge ich zwar schon dafür. dass mein Programm Admin-Rechte fordert, ich habe aber keinen Einfluss darauf, ob cmd.exe als admin ausgeführt wird.
Danke nochmals..
Update: mein letzter Post kann ignoriert werden, das Problem gestaltet sich anders:
wenn cmd.exe mit Admin-Rechten läuft, werden die Consolenausgaben in dieser cmd.exe-Instanz ausgegeben.
wenn cmd.exe nicht mit Admin-Rechten läuft, wird beim Aufruf des Programms ein neues consolenfenster geöffnet und die Ausgaben werden darin ausgegeben.
Kann ich irgendwie dafür sorgen, dass die Ausgaben immer in der aufrunden cmd-Instanz ausgegeben werden ?
Ja, das geht mittels der von mir genannten API-Funktion:
static class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AttachConsole(int ProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AllocConsole();
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool FreeConsole();
[STAThread]
static int Main(string[] args)
{
if (args.Length > 0)
{
if (!AttachConsole(-1)) AllocConsole();
Console.WriteLine("test");
FreeConsole();
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
return 0;
}
}
-1 - Use the console of the parent of the current process.
Hallo hypersurf,
danke, aber das scheint nicht zu funktionieren, wenn cmd.exe keine Admin-Rechte hat, öffnet die Anwendung weiterhin ein neues Konsolen-Fenster.
Bei mir funzt das, wobei mein Benutzer lokaler Admin ist. Liegt es vielleicht daran, dass Deine Anwendung Adminrechte anfordert?
Du könntest versuchen mittels des Parent Prozesses zu entscheiden. Wenn in der Aufrufskette cmd oder powershell auftaucht die Konsolenversion nutzen, und sonst auf Forms zurückweichen
Hallo Mallett,
wie ist deine Anwendung übersetzt, als Windows Forms oder als Konsolenanwendung? Will meinen, /target:winexe oder /target:exe?
So oder so: Bei solchen Hybrid-Anwendungen gibt es immer Probleme. Der einzige saubere Weg wäre wohl zwei EXE-Dateien zu erzeugen. Dazu muss man keinen Code duplizieren, sondern nur die momentane Entscheidung im Main per if dann über zwei Buildkonfigurationen und per #IFDEF zu treffen.
herbivore
Hi Mallet,
bei Anwendung "klaut" Konsolenfenster? konnten wir zwar nicht alles lösen, aber vielleicht hilft dir auch die Funktion GetConsoleWindow.
beste Grüße
zommi