C++ & C# Programming page
 

 

# Úvod
# Tvůrci
# C++
# C#
# Linky





Ukázkový program Power Logger

Jedno odpoledne mi zapípalo ICQ. Byl to kámoš Jeffry, měl na mě prosbu. Šlo o prográmek, lépe řečeno miniaturní utilitu, která by při startu zapsala do souboru datum a čas a při vypnutí windows by znovu zapsala. Lze z toho zjistit, jak dlouho bylo PC zapnuté a podobně. Vím a jsem si vědom toho, že jsou podobné a mnohem profesionálnější možnosti, ale nejde o to, jestli je tento program lepší. Jednou možná po pár (hodně) úpravách bude. Ostatní programy přece někdo taky musel naprogramovat, no ne? :)

Z teoretické části programu:
Opět, jako minule, nebudu vypisovat celý zdrojový kód, jen některé zajímavé části. Základní program, vygenerovaný Visual Studiem, sice byl změněn, to ale nemá cenu popisovat.
Při inicializaci okna, spustí se funkce na zápis do souboru. Ta načte ze systému čas, načte soubor log.txt, přidá si k němu datum, čas a uzavře práci se souborem.
V další části se docela fláká ale jde jen o přibližně 700kb v paměti, myslím, že to si dovolit můžeme.
Ve chvíli, kdy však program čeká na WM_DESTOROY, nastane překvapení. Nezkoušel jsem to v jiném OS než WinXP, ale program je docila násilněn ukončen, tudíž se musí kontrolovat speciální zpráva WM_QUERYENDSESSION. Je odeslána všem aplikacím, když uživatel požádá windows o ukončení nebo restartování systému. Trhlina je v tom, že při ukončení programu přes CTRL + ALT + DELETE se nic neukládá. Prozatím to však bude stačit, hlavní funkčnost programu lze zajistit i se zprávou WM_QUERYENDSESSION, chtěl jsem jen upozornit na tento nedostatek.
Při ukončení je tedy spuštěna funkce na uložení dalšího času, podobná té na začátku.

A nyní praktické vysvětlení:
void WriteStart(HWND hWnd)
{
SYSTEMTIME Start;
GetLocalTime(&Start);
HANDLE Soubor;
Soubor = CreateFile("log.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if( Soubor == INVALID_HANDLE_VALUE)
     return;  // chyba souboru
else

     DWORD dwActBytes; 
     char szBuf[128]; 
     for(int i=0; i<1024; i++) 
          g_szSoubor[i] = 0; // uklid celeho souboru
     do{ 
          ReadFile(Soubor, szBuf, 128, &dwActBytes, NULL); 
          if(szBuf[0] != -52) // cteni jen pokud v souboru neco je
                lstrcat(g_szSoubor, szBuf); 
     } while(dwActBytes != 0); // kontrola prectenych dat
     CloseHandle(Soubor); 
}
Soubor = CreateFile("log.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if( Soubor == INVALID_HANDLE_VALUE) 
     return; // chyba souboru
else
{
      DWORD dwActBytes; 
     // DALSI RADEK 
     g_szSoubor[GetFirstZero(g_szSoubor)] = 10; // o tomto az pozdeji...
     g_szSoubor[GetFirstZero(g_szSoubor)] = 13; 
     // FROM
     // format: FROM D.M.YYYY H:M:S

     lstrcat(g_szSoubor, "FROM "); 
     AddDWORD(Start.wDay); // tuto funkci popisu take az pozdeji
     lstrcat(g_szSoubor, ".");
      AddDWORD(Start.wMonth); 
     lstrcat(g_szSoubor, "."); 
     AddDWORD(Start.wYear); 
     lstrcat(g_szSoubor, " ");
      AddDWORD(Start.wHour); 
     lstrcat(g_szSoubor, ":"); 
     AddDWORD(Start.wMinute); 
     lstrcat(g_szSoubor, ":"); 
     AddDWORD(Start.wSecond); 
     WriteFile(Soubor, g_szSoubor, sizeof(g_szSoubor), &dwActBytes, NULL); 
     CloseHandle(Soubor); 
     }
}

Na začátku se načte celý soubor do proměnné g_szSoubor (pro neznalé jde o Global_StringZeroEnding-JMENO-). Průběh je takový, že se nejdřív celá proměnná "uklidí" binární nulou, potom se přes buffer szBuf načítá 128 bytů ze souboru a postupně ukládá do g_szSoubor, dokud není počet přečtených bytů roven nule, tzn. již není co číst. Uzavře se handle souboru a opět otevře, minulý handle totiž neměl mód zápisu a ukazatel čtení byl na konci.
Nyní přichází na řadu zapsání data a času do souboru. Neprovádím to úmyslně na konci aplikace proto, že při spadnutí či neplánovaném vypnutí windows by se nezapsalo zapnutí. Pokud se tedy v souboru objeví pouze zapnutí, okamžitě je jasné, že windows se nevypnuly správně. Z toho stejného důvodu přidávám "enter" sekvenci znaků 10 a 13 před i za zápis, dojde tak pokaždé k oddělení řádků a text se nehromadí za sebou.
Po dokončení zápis se opět zavře handle a program se dostane do stádia čekání.
K souboru log mám ještě jednu poznámku, ale to až na konec.

Funkce AddDWORD
void AddDWORD(DWORD cislo)
{
TCHAR szBuf[64]; 
for(int i=0; i<64; i++) 

     szBuf[i] = 0;
}
itoa(cislo, szBuf, 10);
lstrcat(g_szSoubor, szBuf);
}

AddDWORD je pouze pomocná funkce, která usnadnila zápis čísel do proměnné. Vytvoří buffer na text, překonvertuje do něj vložený DWORD a připíše buffer na konec g_szSoubor.

Funkce GetFirstZero
GetFirstZero(char* Text)
{
int a = 0;
while(Text[a] != 0)
{
     a++;
}
return a;
}

Tuto funkci jsem použil v programech relativně mnohokrát. Vrací pozici, na které se nalézá první binární nula, neboli konec proměnné. Využití je u připisování dat na konec nějakého pole nebo textu. Nevím, zda v C++ tato funkce existuje, ale já osobně si ji rád vytvořil :)

Jak jsem se zmínil někde výše v textu, s log.txt je malý problém. Pokud se ho pokusíte zobrazit v notepadu, pravděpodobně se vám nezobrazí "enter" sekvence znaků 10 a 13. Zjistil jsem to až od Jeffryho, když program zkoušel. Já na zobrazování TXT souborů používám program GetDiz, dokáže si lépe poradit s různými formáty. Chyba je zřejmě někde v ukládání, ostatní aplikace totiž pracují s log souborem bez chyb. Pokud někomu bude nekompatibilita vadit, má možnost si to opravit ve zdrojácích :)

Zde jsou:

[ Zdrojáky ] - [ EXE soubor ]



Správce sekce: Dejvino



14.2 2005

C++: pridano par odkazu na clanky o OpenGL, IRC, POP3 a BMP
14.8 2004

C++: přidán klient pro Internet Relay Chat (IRC)
11.7 2004

C++: opravil jsem zdrojak WebServeru, byla tam navic jedna funkce kterou jsem nepridal a mnoho zacatecniku by si s tim nemuselo vedet rady...
27.6 2004

Vytvořen IRC kanál #c-prog na serveru Quakenet
10.6 2004

C++: přidán program WebServer, stojí za prohlédnutí!
5.6 2004

C++: přidán článek o CheckBoxu
29.5 2004

C++: přidán program WinSock Mail
28.5 2004

C#: přidán program DNStoIP
Vaše IP je 107.20.115.174
Stránka byla načtena za 0.01821 sekund.