Προς το περιεχόμενο

Windows EXE launcher


nikolakisgr

Προτεινόμενες αναρτήσεις

Δημοσ.

Καλησπέρα,

 

Προσπαθώ να φτιάξω μια εφαρμογή στα windows (σε C ή σε κάποια άλλη γλώσσα) η οποία το μόνο που θα κάνει θα είναι να τρέχει ένα εκτελέσιμο αρχείο (.exe) το οποίο θα το διαβάζει απο ένα αρχείο ini όπως επίσης και τις παραμέτρους με τις οποίες θα πρέπει να εκτελεστεί.

 

Για παράδειγμα έαν το αρχείο ini είναι της μορφής:

application=c:\myapp.exe

params=param1 param2

 

τρέχοντας το launcher.exe θα πρέπει να τρέξει το "c:\myapp.exe param1 param2"

 

Ο βασικός λόγος που θέλω να δημιουργήσω launcher και δεν τον κάνω με bataki είναι επειδή δεν θέλω να εμφανίζετε καθόλου το εκνευριστικό command prompt παράθυρο των windows προτού ξεκινήσει η εφαρμογή.

 

Ευχαριστώ πολύ για την βοήθειά σας.

Δημοσ.

Δοκίμασε αυτό (γραμμένο σε C):

>
#include <stdio.h>
#include <windows.h>
#define INI_NAME "yourini.ini"

int main(int argc, char *argv[]) {
char *szApp,*szParams,*szDir;
szApp=malloc(sizeof(char)*BUFSIZ);
szParams=malloc(sizeof(char)*BUFSIZ);
szDir=malloc(sizeof(char)*BUFSIZ);
GetCurrentDirectory(sizeof(char)*BUFSIZ,szDir);
strcat(szDir,"\\");
strcat(szDir,INI_NAME);
GetPrivateProfileString("run","application",0,szApp,sizeof(char)*BUFSIZ,szDir);
GetPrivateProfileString("run","params",0,szParams,sizeof(char)*BUFSIZ,szDir);
ShellExecute(0,"open",szApp,szParams,0,SW_SHOWNORMAL);
return 0;
}

Πρέπει να αλλάξεις το "yourini.ini" με το όνομα του δικού σου .ini. Επίσης, θα πρέπει να γράψεις [run] στην αρχή του .ini σου, ώστε να γίνει έτσι:

>
[run]
application=c:\myapp.exe
params=param1 param2

(Μπορείς να χρησιμοποιήσεις κάτι άλλο εκτός από το run, αρκεί να αλλάξεις την πρώτη παράμετρο σε κάθε κλήση του GetPrivateProfileString)

Δημοσ.

Πάλι μου εμφανίζει το Command Prompt παράθυρο προτού φορτώσει την εφαρμογή (θέλει μερικά δευτερόλεπτα για να φορτώσει) με τον παραπάνω κώδικα.

 

Δοκίμασα και με _execv() και CreateProcess() αλλά πάλι το βγάζει το dos παράθυρο :-(

 

Any ideas?

 

Ευχαριστώ για την γρήγορη απάντηση

Δημοσ.
Πάλι μου εμφανίζει το Command Prompt παράθυρο προτού φορτώσει την εφαρμογή (θέλει μερικά δευτερόλεπτα για να φορτώσει) με τον παραπάνω κώδικα.

 

Δοκίμασα και με _execv() και CreateProcess() αλλά πάλι το βγάζει το dos παράθυρο :-(

 

Any ideas?

 

Ευχαριστώ για την γρήγορη απάντηση

Ωχ sorry, δεν είχα διαβάσει καλά το post σου... Απλώς κάνε το project σου win32 project και όχι win32 console project (αν χρησιμοποιείς visual studio, για άλλους compilers δεν είμαι σίγουρος). Ο κώδικας θα πρέπει να είναι έτσι:

>
#include <stdio.h>
#include <windows.h>
#define INI_NAME "yourini.ini"

int WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,char *szCmdLine,int nShowCmd) {
char *szApp,*szParams,*szDir;
szApp=malloc(sizeof(char)*BUFSIZ);
szParams=malloc(sizeof(char)*BUFSIZ);
szDir=malloc(sizeof(char)*BUFSIZ);
GetCurrentDirectory(sizeof(char)*BUFSIZ,szDir);
strcat(szDir,"\\");
strcat(szDir,INI_NAME);
GetPrivateProfileString("run","application",0,szApp,sizeof(char)*BUFSIZ,szDir);
GetPrivateProfileString("run","params",0,szParams,sizeof(char)*BUFSIZ,szDir);
ShellExecute(0,"open",szApp,szParams,0,SW_SHOWNORMAL);
return 0;
}

Δημοσ.

Το nircmd και το cmdow καλα ειναι αλλα νομιζω οτι δεν λυνουν το προβλημα. Θα πρεπει να καλεσεις πρωτα το nircmd η το cmdow τα οποια θα καλεσουν το launcher με κρυμμενο παραθυρο, αλλα το παραθυρο του ιδιου του Nircmd/cmdow ποιος θα το κρυψει?

 

Υπαρχει παντα και η επιλογη στο bat του start /min. Οποτε ξεκιναει ελαχιστοποιημενο. Μετα μπορεις να προσθεσεις και exit ωστε να κλεισει αμεσως το παραθυρο (οχι ομως και το προγραμμα σου) Αυτο δεν ειναι και τοσο ενοχλητικο.

 

Το καλυτερο ομως ειναι να φτιαξεις ενα compiled bat.

Φτιαξε bat και ψαξε το bat2exe converter. Ουσιαστικα ενας batch file compiler. Εχει και την επιλογη το exe που θα φτιαξεις να μην δειχνει καθολου παραθυρο (ghost application)

Δημοσ.

Το πιο απλό είναι χρησιμοποιώντας τη visual basic σου παραθέτω τον κώδικά που χρησιμοποιώ:

>
Private sub command_click()
Shell "my.exe param1 param2", vbhide 

 

όπου param1 είναι η 1η παράμετρος και όπου param2 είναι η 2η παράμετρος.Το vbhide είναι για να μην εμφανιστεί το command prompt και να εκτελείτε η εντολή στο background,αν ήθελες να εμφανιστεί το command prompt θα έπρεπε να αλλάξεις το vbhide σε vbNormalFocus.

Δημοσ.

Ευχαριστώ πολύ για τις απαντήσεις σας. Τελικά το έκανα με τον κώδικα του Aesmade.

 

Κάτι ακόμα που θέλω να ρωτήσω είναι πώς γίνετε να κρύψω (προγραμματιστικά) το παράθυρο από το process που θα τρέξω ? Όπως λειτουργεί δηλαδή το option /HIDE του cmdo

 

Εάν για παράδειγμα στον launcher τρέξω την εντολή xcopy θα εμφανιστεί πάλι το command prompt παράθυρο καθώς το process xcopy ξεκινάει σε command prompt, αυτό το παράθυρο θέλω να κρύψω βάζοντας για παράδειγμα μια επιλογή showwindow=0 στο .ini .

 

Any ideas?

 

Ευχαριστώ

Δημοσ.
Ευχαριστώ πολύ για τις απαντήσεις σας. Τελικά το έκανα με τον κώδικα του Aesmade.

 

Κάτι ακόμα που θέλω να ρωτήσω είναι πώς γίνετε να κρύψω (προγραμματιστικά) το παράθυρο από το process που θα τρέξω ? Όπως λειτουργεί δηλαδή το option /HIDE του cmdo

 

Εάν για παράδειγμα στον launcher τρέξω την εντολή xcopy θα εμφανιστεί πάλι το command prompt παράθυρο καθώς το process xcopy ξεκινάει σε command prompt, αυτό το παράθυρο θέλω να κρύψω βάζοντας για παράδειγμα μια επιλογή showwindow=0 στο .ini .

 

Any ideas?

 

Ευχαριστώ

ezpz

1ος τρόπος - Χρησιμοποίησε τη ShellExecute με την παράμετρο SW_HIDE, ώστε να μην εμφανίζει παράθυρο. Παράδειγμα:

>
ShellExecute(0,"open","xcopy","C:\\example1 C:\\example2","C:\\WINDOWS\\system32",SW_HIDE);

Αυτό χρησιμοποιεί την xcopy με τις παραμέτρους C:\example1 και C:\example2 χωρίς να εμφανίζει παράθυρο χάρη στο SW_HIDE. Μπορείς να χρησιμοποιήσεις και την GetWindowsDirectory για να σιγουρευτείς πως έχεις το σωστό path των windows.

2ος τρόπος - Φτιάξε δικιά σου xcopy που να μην εμφανίζει παράθυρο.

Δημοσ.

Με τις εντολές _exec* και CreateProcess μπορεί να γίνει κάτι αντίστοιχο ? Να κρύψω δηλαδή το παράθυρο από το child process

 

Ευχαριστώ

Δημοσ.

ShellExecute(0,0,"notepad.exe",NULL,0,SW_SHOW);

 

και τίποτα άλλο .

 

Αν θέλεις να μην σου εμφανίζει τίποτα φτιάξε μια form application και βγάλε την φορμα απο το προγραμμά σου .

αυτό που θα αλλάξει θα είναι η main και αντι για αυτήν θα έχεις την WinMain

 

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)

{

ShellExecute(NULL,NULL,"notepad.exe",NULL,0,SW_SHOW);

}

Δημοσ.

Δοκίμασε αυτό αν θες τη CreateProcess, αν και νομίζω δεν δουλεύει πάντα.

>
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si,sizeof(si));
si.cb=sizeof(si);
si.wShowWindow=SW_HIDE;
ZeroMemory(&pi,sizeof(pi));
CreateProcess(0,"C:\\example.exe param1 param2 param3",0,0,0,0,0,0,&si,&pi);

Δημοσ.

Τελικά βρήκα το flag CREATE_NO_WINDOW (0x08000000) στα creation flags της CreateProcess:

 

"The process is a console application that is being run without a console window. Therefore, the console handle for the application is not set.

 

This flag is ignored if the application is not a console application, or if it is used with either CREATE_NEW_CONSOLE or DETACHED_PROCESS."

 

Δουλεύει άψογα :-)

  • 2 εβδομάδες αργότερα...
Δημοσ.

Έχω μια ακόμα ερώτηση σε περίπτωση που κάποιος γνωρίζει..

 

Έστω ότι ο launcher και το configuration .ini βρίσκονται στο drive d:

Εάν προσπαθήσω να τρέξω το .exe (από command line) μέσα από το d:\ θα τρέξει κανονικά καθώς βρίσκει το configuration file στο current working directory. Εάν όμως προσπαθήσω να το τρέξω πχ. απο το C:\ (με την εντολή d:\launcher.exe) θα τρέξει το .exe αλλά δεν θα βρει το configuration Και θα τερματιστεί.

 

Η ερώτηση μου είναι πώς γίνετε να πάρω το full path από το directory που βρίσκετε το .exe (d:\launcher.exe) ώστε να ανοίξω το σωστό path για το configuration file (d:\config.ini) ακόμα και αν το current working dir είναι διαφορετικό?

 

Ευχαριστώ για τον χρόνο σας.

Δημοσ.

Αυτό συμβαίνει διότι χρησιμοποιείς την ρουτίνα GetCurrentDirectory η οποία επιστρέφει πάντα το τρέχον (current) κατάλογο του process μας (στην περίπτωση μας αυτή είναι η Console και τον κληροδοτεί στα children processes της, δηλαδή στην εφαρμογή σου).

 

Αν θες να λαμβάνεις την διαδρομή προς τον κατάλογο της εφαρμογής σου, ανεξαρτήτως current directory (ή καλύτερα folder) θα πρέπει να χρησιμοποιήσεις την ρουτίνα GetModuleFileName με την πρώτη παράμετρο της ως NULL ώστε η ρουτίνα να αποθηκεύσει στο cszBuffer τον κατάλογο από όπου ξεκίνησε η εφαρμογή μας.

 

Ακολουθεί ένα παράδειγμα γραμμένο σε CodeGear Turbo C++ & Windows API (με ANSI charset).

 

>
/*---------------------------------------------------------------------------*/

#include <stdio.h>
#include <windows.h>
#ifdef 	__BORLANDC__
#pragma hdrstop
#endif

/*---------------------------------------------------------------------------*/

#ifdef 	__BORLANDC__
#pragma argsused
#endif
int main(int argc, char* argv[])
{
TCHAR	cszBuffer[bUFSIZ];

/* Get the absolute Executable file path using GetModuleFileName */
printf("%s",
	   (!GetModuleFileName(NULL, cszBuffer, sizeof(cszBuffer)))?
	   " OS Error: GetModuleFileName failed!":
	   cszBuffer);

printf(" \n\nPress enter to quit");
getchar();
return 0;
}
/*---------------------------------------------------------------------------*/

 

Υ.Γ.

Αν δουλεύεις με native console προγράμματα μπορείς να έχεις παρόμοια λειτουργία αν εξετάσεις το argv[0].

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • Δημιουργία νέου...