2011-01-18 8 views
5

Czy jest możliwe utworzenie programu działającego jako aplikacja konsolowa, jeśli został uruchomiony z konsoli i działa jako program windowsowy (z graficznym interfejsem użytkownika), gdy jest uruchamiany w inny sposób?Problem z konsolą Win32:

Jeśli to możliwe - jak mogę to zrobić?

pozdrowienia Tobias

Odpowiedz

2

Jeśli potrzebujesz, aby program działał jako aplikacja konsolowa (np. wydrukuj informacje o użytkowaniu do konsoli), musisz Uzgodnij jako aplikację konsolową. Aplikacja systemu Windows nie będzie miała dostępu do konsoli, a program cmd.exe nie będzie czekać na jej zakończenie przed wydrukowaniem monitu i zaakceptowaniem następnego polecenia.

Najlepszym rozwiązaniem jest posiadanie dwóch wersji, jednej dla wiersza poleceń i drugiej dla interfejsu GUI (zazwyczaj użytkownicy uruchamiani przez łącze na pulpicie lub w menu startowym).

Jeśli nalegasz na używanie pojedynczego pliku binarnego, będziesz musiał żyć z oknem konsoli pojawiającym się, przynajmniej na krótki czas. Możesz pozbyć się okna konsoli, używając Możesz powiedzieć, że twoja aplikacja została uruchomiona z GUI, jeśli jest to jedyny proces dołączony do konsoli. Możesz użyć GetConsoleProcessList, aby znaleźć listę procesów dołączonych do konsoli.

+0

fajny pomysł. Dziękuję Ci. –

0

Sam program nie będzie wiedział, jak to się zaczęło. Chyba, że ​​jesteś gotów przekazać argumenty wykonawcze do programu. Na przykład: program.exe - GUI ... można przechwytywać przekazane parametry i zdecydować, w jaki sposób program powinien działać na podstawie przekazanych parametrów.

program whould być coś takiego:

class MainClass 
{ 
    public static int Main(string[] args) 
    { 
     // Test if input arguments were supplied: 
     if(args[0]=="GUI") 
      new myGUI().show(); //runs an instance of your gui 
     else 
      //you know what should go here 
    } 
} 
+2

można sprawdzić procesu nadrzędnego dla powłoki poleceń w celu ustalenia, czy został on uruchomiony poprzez cmd lub w inny sposób. Głównym problemem jest okno cmd, które jest wyświetlane, jeśli flaga jest ustawiona w nagłówku pe. –

+0

Możesz ukryć okno cmd. To jest możliwe. – deadlock

+0

można sprawdzić std uchwyt z GetStartUpInfo. (http://msdn.microsoft.com/en-us/library/ms683230(v=vs.85).aspx) oraz świetny pomysł Len's Holgate. więc jesteś w błędzie, są sposoby. – Andrey

0

rodzaju można odgadnąć, czy są uruchamiane z konsoli lub nie w ten sposób:

CONSOLE_SCREEN_BUFFER_INFO csbi; 
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); 
fConsole = csbi.dwCursorPosition.X | csbi.dwCursorPosition.Y; 

To przypuszczenie - jeśli pozycja kursora nie jest równa 0,0 niż w konsoli i może działać jako aplikacja konsolowa. W przeciwnym razie idź i stwórz swoje okna.

Innym sposobem na odgadnięcie jest spojrzenie na drzewo procesu i zobacz, w którym procesie uruchomiono twoją aplikację. Jeśli jest to cmd.exe, przejdź do trybu konsoli, w przeciwnym razie przejdź do trybu GUI.

3

Jeśli ustawisz program jako program GUI, możesz spróbować dołączyć do konsoli za pomocą AttachConsole(). Założono, że jesteś OK, a następnie zostałeś uruchomiony z konsoli i możesz przejść do przekierowania standardowych uchwytów do nowo dołączonej konsoli.

W ten sposób można uruchomić i sprawdzić, czy uruchamiany jest z konsoli, do której można dołączyć, a jeśli tak, to program konsoli. Jeśli nie możesz dołączyć, możesz pokazać GUI.

Osiągnąłem pewien sukces, głównym problemem, jaki mam, jest ponowne wyświetlenie monitu okna poleceń po wyjściu mojego programu (tak działają normalne programy konsolowe), ale spodziewam się, że możesz zrobić coś sprytnego (przeczytaj konsolę bufor przy uruchomieniu i znaleźć monit o ponowne wyświetlenie po wyjściu?) jeśli naprawdę chcesz ...

+0

Zamiast tego użyj AllocConsole(). –

+0

Ale czy nie utworzymy nowego okna konsoli zamiast łączenia się z wierszem polecenia, który uruchomił okno konsoli? –

+0

Tak. Nie ma udokumentowanego ograniczenia dotyczącego wywoływania 'AttachConsole' z programu GUI; to po prostu nie jest domyślne. – MSalters

0

Zrób to aplikacja konsoli i umieścić to w kodzie:

void ConsoleWindowVisible(bool show) 
{ 
    DWORD dummy; 
    if 
    (
     !show && // Trying to hide 
     GetConsoleProcessList(&dummy, 1) == 1 // Have our own console window 
    ) 
     ShowWindow(GetConsoleWindow, SW_HIDE); // Hide the window 
    else // Trying to show or use parent console window 
     ShowWindow(GetConsoleWindow, SW_NORMAL); // Show the window 
} 

int main(int argc, char** argv) 
{ 
    ConsoleWindowVisible(false); 
} 

Cheers.

[email protected]

0

Jest to odpowiedź od Dan Tillettem i jest niezwykle skuteczna. Bez fleszy, bez .com i .exe do oszukania cmd.exe. Wydaje się działać bezbłędnie wpisując polecenie, w pliku .bat, z fokusem, bez fokusu i jako podwójnie kliknij GUI.

To kolana pszczół!

Oto strona opisująca tę stronę, ale opublikowałem ją tutaj, ponieważ jeśli ta strona przejdzie 404 w przyszłym miesiącu lub za 2 lata, doskonałym i "najbardziej kompletnym" rozwiązaniem, jakie widziałem, będzie "poza siecią ".

http://www.tillett.info/2013/05/13/how-to-create-a-windows-program-that-works-as-both-as-a-gui-and-console-application/

#define WINVER 0x0501 // Allow use of features specific to Windows XP or later. 
#define _WIN32_WINNT 0x0501 
#define WIN32_LEAN_AND_MEAN 
#include <windows.h> 
#include <io.h> 
#include <fcntl.h> 
#include <stdio.h> 
#pragma comment(lib, "User32.lib") 

// Attach output of application to parent console 
static BOOL attachOutputToConsole(void) { 
HANDLE consoleHandleOut, consoleHandleError; 
int fdOut, fdError; 
FILE *fpOut, *fpError; 

if (AttachConsole(ATTACH_PARENT_PROCESS)) { 
    //redirect unbuffered STDOUT to the console 
    consoleHandleOut = GetStdHandle(STD_OUTPUT_HANDLE); 
    fdOut = _open_osfhandle((intptr_t)consoleHandleOut, _O_TEXT); 
    fpOut = _fdopen(fdOut, "w"); 
    *stdout = *fpOut; 
    setvbuf(stdout, NULL, _IONBF, 0); 

    //redirect unbuffered STDERR to the console 
    consoleHandleError = GetStdHandle(STD_ERROR_HANDLE); 
    fdError = _open_osfhandle((intptr_t)consoleHandleError, _O_TEXT); 
    fpError = _fdopen(fdError, "w"); 
    *stderr = *fpError; 
    setvbuf(stderr, NULL, _IONBF, 0); 

    return TRUE; 
    } 
//Not a console application 
return FALSE; 
} 

//Send the "enter" to the console to release the command prompt on the parent console 
static void sendEnterKey(void) { 
INPUT ip; 
// Set up a generic keyboard event. 
ip.type = INPUT_KEYBOARD; 
ip.ki.wScan = 0; // hardware scan code for key 
ip.ki.time = 0; 
ip.ki.dwExtraInfo = 0; 

//Send the "Enter" key 
ip.ki.wVk = 0x0D; // virtual-key code for the "Enter" key 
ip.ki.dwFlags = 0; // 0 for key press 
SendInput(1, &ip, sizeof(INPUT)); 

// Release the "Enter" key 
ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release 
SendInput(1, &ip, sizeof(INPUT)); 
} 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow) { 
int argc = __argc; 
char **argv = __argv; 
UNREFERENCED_PARAMETER(hInstance); 
UNREFERENCED_PARAMETER(hPrevInstance); 
UNREFERENCED_PARAMETER(lpCmdLine); 
UNREFERENCED_PARAMETER(nCmdShow); 
BOOL console; 
int i; 

//Is the program running as console or GUI application 
console = attachOutputToConsole(); 

if (console) { 
    //Print to stdout 
    printf("Program running as console application\n"); 
    for (i = 0; i < argc; i++) { 
     printf("argv[%d] %s\n", i, argv[i]); 
     } 

    //Print to stderr 
    fprintf(stderr, "Output to stderr\n"); 
    } 
else { 
    MessageBox(NULL, "Program running as windows gui application", 
    "Windows GUI Application", MB_OK | MB_SETFOREGROUND); 
} 

//Send "enter" to release application from the console 
//This is a hack, but if not used the console doesn't know the application has returned 
//"enter" only sent if the console window is in focus 
if (console && GetConsoleWindow() == GetForegroundWindow()){ 
    sendEnterKey(); 
    } 
return 0; 
}