Gå til innhold

Batch-fil må køyrast ved avslutning av Windows


Anbefalte innlegg

God kveld!

 

Eg jobbar med eit prosjekt som skal vera absolutt installasjonsfritt. I den samanheng treng eg å få køyrt ei batch- eller programfil for å rydda opp når Windows avslutter. Aller helst burde det vore såpass kraftig at om Windows blir kritisk avslutta, så blir det køyrd ved neste oppstart.

 

Dette er i tilfelle brukaren ikkje avslutter prosessen sjølv.

 

Lagt til:

 

Etter litt utforsking har eg kome fram til at dette antageleg ikkje går an. Derimot har eg laga meg ein teori:

 

Prosjektet mitt blir nemleg starta av start.bat, og avslutta av shutdown.bat. Eg tenkjer at eg kunne laga eit enkelt program i C++ som køyrer som ein prosess, kun synleg i oppgåvebehandlaren.

 

Me kallar dette programmet for atshutdown.exe. Dette bør nok skiftast til eit meir unikt namn, men den tid, den sorg. I alle fall. Til slutt i start.bat har me linja start atshutdown.exe shutdown.bat.

 

I atshutdown.exe må eg nok bruka Win32-API-et. Programmet skal ikkje gjera anna enn å venta til det får kill-signal frå Windows. Då skal programmet køyra kommandoen / programmet det fekk som argument. Altså shutdown.bat.

 

Om brukaren køyrer shutdown.bat før Windows avslutter vil derimot shutdown.bat avslutta prosessen atshutdown.exe.

 

Er denne teorien mogleg i praksis, og utan å stela for mykje prosessorkraft?

Endret av knuto
Lenke til kommentar
Videoannonse
Annonse

Ja det er fullt mulig WM_CLOSE blir sendt når programmet blir avsluttet (dvs nå må programmet avslutte seg selv).

Men hva hvis strømmen går eller noe slikt, meget kritiske! system feil og slikt.

Det finnes jo steder der man kan legge filer som blir automatisk kjørt ved oppstart (startup direktivet på startmenyen osv).

Lenke til kommentar

Jeg bare tenker litt.. Hva er det som skal fjernes? win32 har en variabel som man kan sette på en delete funksjonen (lenge siden jeg var borti den)

 

Men den mener jeg gjør at filene slettes først ved oppstart.

Hvis du forklarte litt nærmere opplegget ditt så tror jeg det finnes en enklere løsning.

Lenke til kommentar

Her er en liten kodebit jeg rasket sammen som kan hjelpe deg. Det er en liten app som lager et skjult vindu som tar i mot WM_QUERYENDSESSION og WM_ENDSESSION. Du må selv skrive koden du ønsker skal kjøre ved shutdown under WM_ENDSESSION. Se på MSDN for nærmere beskrivelse av meldingene.

 

Koden:

 

#include <windows.h>
#include <tchar.h>


// prototypes
LRESULT CALLBACK WindowProc (HWND hwndd, UINT message, WPARAM wParam, LPARAM lParam);


// constants
const TCHAR* WNDCLASSNAME = _T("MyHiddenWindow");


// entry point
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
{
 // register window class
 WNDCLASS wc;
 memset(&wc, 0, sizeof(wc));
 wc.lpszClassName = WNDCLASSNAME;
 wc.lpfnWndProc = WindowProc;
 RegisterClass(&wc);

 // create hidden window
 HANDLE hiddenWindow = CreateWindow( WNDCLASSNAME, 
                   WNDCLASSNAME, 
                   WS_OVERLAPPEDWINDOW, 
                   CW_USEDEFAULT, 
                   CW_USEDEFAULT, 
                   CW_USEDEFAULT, 
                   CW_USEDEFAULT, 
                   0, 
                   0, 
                   hInstance, 
                   0);

 // message loop
 MSG msg;
 while(GetMessage(&msg, NULL, 0, 0 ))
 {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
 }

 return static_cast<int>( msg.wParam );
}


// event handlers
LRESULT CALLBACK WindowProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 switch(message)
 {
 case WM_QUERYENDSESSION:
   // you may cancel shutdown here...

   return TRUE;


 case WM_ENDSESSION:
   if(wParam == FALSE)
     return 0;

   // do your cleanup here...

   DestroyWindow(hwnd);
   PostQuitMessage(0);

   return 0;


 default:
   return DefWindowProc(hwnd, message, wParam, lParam); 

 }

 return 0;
}

Lenke til kommentar

Hmm. Virker av ein eller annan grunn til at det der ikkje fungerer heilt ... Om eg avslutter prosessen som heiter AtShutdown.exe, så vil allikevel ikkje noko bli gjennomført. Verken om eg legg inn ein message box, eller ein system-kommando ...

 

Kode som blei brukt:

#include <cstdlib>
#include <windows.h>
#include <tchar.h>

// prototypes
LRESULT CALLBACK WindowProc (HWND hwndd, UINT message, WPARAM wParam, LPARAM lParam);

// constants
const TCHAR* WNDCLASSNAME = _T("AtShutdown");

// entry point
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd) {
// register window class
WNDCLASS wc;
memset(&wc, 0, sizeof(wc));
wc.lpszClassName = WNDCLASSNAME;
wc.lpfnWndProc = WindowProc;
RegisterClass(&wc);

// create hidden window
HANDLE hiddenWindow = CreateWindow( WNDCLASSNAME,
         WNDCLASSNAME,
         WS_OVERLAPPEDWINDOW,
         CW_USEDEFAULT,
         CW_USEDEFAULT,
         CW_USEDEFAULT,
         CW_USEDEFAULT,
         0,
         0,
         hInstance,
         0);

// message loop
MSG msg;
while(GetMessage(&msg, NULL, 0, 0 )) {
 TranslateMessage(&msg);
 DispatchMessage(&msg);
}//end while

return static_cast<int>( msg.wParam );
}//end entry point


// event handlers
LRESULT CALLBACK WindowProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch(message) {
 case WM_QUERYENDSESSION:
 	return TRUE;
 
 case WM_ENDSESSION:
 	if(wParam == FALSE)
   return 0;
 
 	/* {...} */
 	system("shutdown.bat");
 	MessageBox(NULL, "xxx does not run any more ...", "Finish..", MB_OK);
 
 	DestroyWindow(hwnd);
 	PostQuitMessage(0);
 	
 	return 0;
 	
 default:
 	return DefWindowProc(hwnd, message, wParam, lParam);
}//end switch
return 0;
}//end callback

Endret av knuto
Lenke til kommentar

WM_ENDSESSION blir sendt når Windows avslutter sesjonen (dvs. log off, restart eller shutdown), og ikke om du terminerer applikasjonen i task manager. Da har jeg misforstått hvis det var det du ønsket. Trodde du ville ha et program som lå i bakgrunnen og detekterte når brukeren avsluttet Windows.

Lenke til kommentar

Hvorfor er det bedre å bruke WM_CLOSE?

 

WM_ENDSESSION blir sendt når sesjonen eller Windows avsluttes. Synes det er bedre enn å bruke WM_CLOSE selv om du sikkert kan oppnå det samme med den siden vinduet er skjult.

 

Du trenger strengt tatt ikke bry deg om WM_QUERYENDSESSION, men jeg tok den med for å illustrere.

Lenke til kommentar

Hvis du dreper prosessen tror jeg det blir vanskelig å detektere hvis du ikke ønsker enda et program som overvåker AtShutdown.exe. Er ganske sikker på at task manager ikke sender noen meldinger til prosesser den terminerer (nei, ikke noe WM_CLOSE heller).

 

Du kan jo alltids lage AtShutdown.exe slik at den alltid sørger for at det er minst to AtShutdown.exe prosesser.

 

Edit: kan bekrefte at task manager ikke sendte meldinger til applikasjonen den terminerer (sjekket i spy++).

Endret av kjetil7
Lenke til kommentar

Kan tydeleg vis ikkje bruka funksjonen system frå cstdlib til å gje Apache kommandoar. Det resulterar i cmd.exe feil. Må gjera dette på eit anna vis, men eg legg prosjektet midlertidig på hulla, for eg skal nok ein gong prøva å venna meg til Linux :)

 

Forresten positivt overraska sidan eg har fått til eksternt skrivebord, slik at eg kan bruka min win-laptop i stova for å styra linuxen på loftet :)

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...