2009-10-27 9 views
24

È possibile (e in tal caso, come faccio) far funzionare un singolo programma sia come applicazione console sia come versione GUI utilizzando Delphi 2007?Programma sia come console che come interfaccia utente

Quello che sto cercando è che se il programma viene eseguito con le opzioni della riga di comando appropriate, dovrebbe funzionare come un programma di console, stampando l'output sulla console usando WRITELN, ma se non viene fornito alcun argomento da riga di comando, deve essere eseguito come una normale applicazione GUI Delphi?

Il problema è che quando si esegue come applicazione console, l'interprete della riga di comando attende che l'applicazione termini prima di consentire l'immissione di un nuovo comando, mentre un'applicazione GUI avviata dalla riga di comando riporta immediatamente alla riga di comando e l'applicazione GUI viene avviata in un processo separato. Voglio mantenere questo comportamento.

Non mi importa qualcosa di simile:

SE POI GUI StartApplicationAsGUI (ParamStr (0))

es. Non mi dispiace che dovrò riavviare l'applicazione utilizzando una qualche forma di chiamata EXECUTE per avviarla in modalità GUI, se necessario, purché l'interfaccia della riga di comando ritorni all'ingresso della riga di comando quando viene avviata la versione della GUI.

Preferirei una soluzione/proposta che è lungo le linee di:

< Parse Comnand Linea >
SE POI ConsoleMode
      RunConsole (Parametri)
ELSE BEGIN
      Application.Initialize;
      Application.CreateForm (...)
      Application.Run;
FINE

(o viceversa, vale a dire. Fare le cose un modo particolare se la modalità GUI)

in modo che posso ancora usare IDE e VCL di Delphi quando si effettua l'interfaccia GUI ...

risposta

4

Windows ha valori diversi nell'intestazione dell'eseguibile per la console e l'applicazione dell'interfaccia utente (vedere ulteriori dettagli here). Quindi sembra impossibile rendere lo stesso eseguibile per funzionare in entrambe le modalità.

In alternativa, è possibile aprire una console nell'app dell'interfaccia utente, ma sarà una nuova console, non quella da cui hai avviato l'app.

12

Su Windows questo è un po 'complicato. In realtà la distinzione tra un'applicazione di console e una GUI è un singolo flag nell'intestazione PE. Puoi facilmente scrivere le applicazioni della console che creano finestre, ma in questo modo hai sempre la finestra della console in giro (potresti nasconderlo, però, ma non sarebbe bello quando le persone eseguono il tuo programma da cmd).

È possibile, però scrivere un'applicazione GUI che crea una console se deve, tramite la funzione AllocConsole:

Un processo può essere associato a una sola console, in modo che il AllocConsole funzione fallisce se il processo chiamante ha già una console. Un processo può utilizzare la funzione FreeConsole per staccarsi dalla sua console corrente, quindi può chiamare AllocConsole per creare una nuova console o AttachConsole da collegare a un'altra console.

Se il processo chiamante crea un processo figlio, il figlio eredita la nuova console.

AllocConsole inizializza gli input standard, l'output standard e le maniglie degli errori standard per la nuova console. L'handle di input standard è un handle per il buffer di input della console e l'output standard e gli handle di errori standard sono handle per il buffer dello schermo della console. Per recuperare queste maniglie, utilizzare la funzione .

Questa funzione è utilizzata principalmente dall'applicazione GUI (graphical user interface) per creare una finestra della console. Le applicazioni GUI sono inizializzate senza una console. Le applicazioni della console vengono inizializzate con una console, a meno che non vengano create come processi separati (chiamando la funzione CreateProcess con il flag DETACHED_PROCESS).

Tuttavia, quando viene eseguito da cmd, è probabile che venga visualizzata un'altra finestra console invece di riutilizzare quella esistente. Non so se esiste una buona soluzione lì.

12

IMO, l'approccio migliore è quello di avere classi non-visivi che in realtà fanno il lavoro del programma. Quindi puoi chiamarlo da un programma GUI, e puoi anche chiamarlo da un programma a riga di comando separato. Entrambi i programmi sono solo involucri attorno alla funzionalità delle tue classi.

Questo costringe anche il design a essere pulito: le classi sono necessariamente separate dal livello GUI dell'applicazione.

+2

Questa è la risposta giusta. – Tim

+0

Il problema con questo approccio è che richiede la distribuzione di tre file se eseguito correttamente: 1) Un eseguibile da riga di comando, 2) Un eseguibile della GUI e 3) Un file di libreria contenente il nucleo principale del programma. Preferirei un singolo eseguibile, e l'opzione migliore sembra avere un programma GUI con un bit di console nell'intestazione che poi può riavviarsi con una console distaccata se deve essere eseguita come GUI. Proprio come ildasm nei vari collegamenti forniti. – HeartWare

+0

Beh, direi che solo due eseguibili sono fattibili. Se si crea l'EXE inclusi i BPL, non è necessario distribuire alcun file "principale", ma solo un exe per applicazione. Ma ovviamente tu sei colui che conosce le tue esigenze di implementazione; Mi fa piacere che la risposta di ildasm sia stata d'aiuto. – JosephStyons

3

AttachConsole() può essere utilizzato per ottenere una sospensione della console genitori. E.g. se l'applicazione viene avviata da una conchiglia cmdline, AllocConsole() può essere evitato:

if not AttachConsole(ATTACH_PARENT_PROCESS) 
then AllocConsole; 

Maggiori informazioni qui: http://msdn.microsoft.com/en-us/library/windows/desktop/ms681952(v=vs.85).aspx

+0

un esempio di codice di Chee Wee è qui: http://chuacw.ath.cx/blogs/chuacw/archive/2015/12/02/delphi-app-with-console-and-gui.aspx – dummzeuch

Problemi correlati