Versionsinformationen auslesen
Oft implementiert man in seine Applikation einen About-Dialog, in dem man sich nicht nur selbst verewigt, sondern auch die Programmversion usw. anzeigt.
Hardcodet man nun diese Information, so hat man hier unnötige Doppelgleisigkeiten, da man die Versionsnummer normalerweise ja schon in der Versioninfo-Resource angibt.
Bei einem Programmupdate müsste man dann immer 2 Werte ändern, was man häufig vergisst.
Die Idee ist daher naheliegend, dass man sich für seinen About-Dialog gleich die Versionsinformationen aus der Versioninfo-Resource extrahiert. Unglücklicherweise ist dies weniger trivial, als man viell. ursprünglich annehmen möchte. Generell sollte man sich hierfür die Hilfe zur VerQueryValue-Funktion ansehen.
Hier sind auch die Strings beschrieben, die man aus der Versioninfo auslesen kann.
Nachdem für die Benutzung dieser Funktion jedoch einige Vorarbeiten notwendig sind, ist es praktisch, die Versionsabfrage in eine Klasse zu kapseln, welche im Konstruktor die Extraktion der Resourcen zur weiteren Verwendung durch VerQueryValue
übernimmt und im Destruktor den Speicher wieder frei gibt.
Ich habe daher eine kleine Klasse implementiert, die diese Aufgabe übernimmt:
Diese lässt sich relativ bequem dann in der Window-Procedure the About-Dialogs einsetzen:
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
try {
char szDestBuf[256];
QueryResource qr;
_snprintf (szDestBuf, sizeof (szDestBuf), "%s\nVersion %s\n\n%s - %s\n\nAuthor: dose", qr.GetValue ("ProductName"), qr.GetValue ("ProductVersion"), qr.GetValue ("LegalCopyright"), qr.GetValue ("CompanyName") );
SetDlgItemText (hDlg, IDC_VERSION, szDestBuf );
}
catch (QueryResource::xError) {}
catch (bad_alloc) {}
return TRUE;
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
EndDialog(hDlg, 0);
break;
}
break;
}
return FALSE;
}
#tkwg Treffen!
ABGESAGT/VERSCHOBEN AUF NÄCHSTE WOCHE!
*Terminvorschlag: Fr. 2005-09-16 ~20:00
*Lokalvorschlag: Tunnel (Florianigasse 39, 1080 Wien)
Das Lokal bietet sehr günstige Preise, große Tische und is mit J Bim vom Karlsplatz aus super zu erreichen (vom Gürtel aus auch irgendwie). Zum später irgendwoanders hingehn gibts in der Umgebung Milliarden andere Lokale.
Anmeldungen, Absagen und Alternativtermine bitte als Kommentar!
Eine Weisheit…
An einem See ist ein Baum. An diesem Baum hängt eine Spinne. Im See schwimmt ein Fisch. Der denkt sich: “Wenn die Spinne 10cm runterklettert, kann ich hochspringen und die Spinne fressen.”
Am Rand des Sees steht ein Bär. Der denkt sich: “Wenn die Spinne 10 cm runterklettert, springt der Fisch hoch um, um die Spinne zu fressen und ich kann dann nach dem Fisch schlagen.”
Hinter einer Hecke steht ein Jäger. Der denkt sich: “Wenn die Spinne 10 cm runterklettert, springt der Fisch hoch, der Bär schlägt nach dem Fisch und ich kann dann aus dem Hinterhalt den Bären erschießen.”
Am Tisch des Jägers steht eine Maus. Die denkt sich: “Wenn die Spinne runterklettert, springt der Fisch hoch, der Bär schlägt nach dem Fisch, der Jäger erschießt den Bären und ich kann hochklettern und mir den Käse schnappen.”
Hinter einem Gebüsch lauert eine Katze. Die denkt: “Wenn die Spinne runterklettert, springt der Fisch hoch, der Bär schlägt nach dem Fisch, der Jäger erschießt den Bären, die Maus holt sich den Käse und ich schnapp mir die Maus.”
Nach wenigen Sekunden klettert die Spinne 10 cm runter, der Fisch springt hoch und frisst die Spinne, der Bär fängt den Fisch, der Jäger erschießt den Bären, die Maus rennt hoch und holt sich den Käse. Die Katze stürmt auf die Maus zu, rutscht aus und fällt in den See.
Und die Moral von der Geschicht….
Je länger das Vorspiel, desto nasser die Muschi!
LoadString() C++ Klasse
Um eine WIN32-Applikation in mehreren Sprachversionen zu lokalisieren,
gibt es neben den lokalisierten Forms auch die String tables, die sich in den Programmresourcen befinden.
Wenn man sein Programm also mehrsprachig gestalten will, sind alle hardcoierten
strings aus dem Sourcecoe zu entfernen und durch Aufrufe zur LoadString Funktion zu ersetzen.
Diese Funktion hat nur leider einige Einschränkungen, wie z.B., dass es nicht möglich ist, die Größe des zu ladenden Strings im vornherein zu bestimmen, um dadurch dynamisch Speicher zu allozieren. Der simpelste Ansatz zum Laden von Strings ist nun, einen globalen Puffer zu definieren, der einfach eine fixe Größe (#define MAX_LOADSTRING 512
z.B. in der Microsoft Hallo-Welt-WIN32-Anwendung, die das Visual Studio durch den Assistenten generiert) hat. Dies ist jedoch mit dem Risiko verbunden, dass einerseits evtl. unnötig Speicher vergeudet wird, andererseits man viell. doch einmal Strings hat, die diese Größe überschreiten und – wenn man darauf vergisst, seine Konstante anzupassen – der Benutzer dann einen abgeschnittenen Text vorfindet.
Außerdem kann man in Multithreaded Applikationen logischerweise keine globale Variable verwenden, die den Text erhält, sondern muss zumindest pro Thread eine eigene lokale
Variable hierfür definieren.
Eine Möglichkeit, diese Limitierung zu umgehen wird von Raymond Chen in seinem Blog beschrieben. Er lädt sich einfach selbst den String aus den Programmresourcen.
Eine andere Möglichkeit bietet die CString Klasse mit ihrer LoadString Methode.
Das Problem hierbei ist jedoch, dass CString Bestandteil der MFCs ist und man in seiner
einfachen WIN32-Anwendung evtl. nicht unbedingt den Ballast der MFCs mitschleppen möchte.
Ich habe daher meine eigene kleine StringLoader – Klasse gebastelt, die dynamisch Speicher alloziert und intern behält. Der Destruktor sorgt für die ordnungsgemäße Freigabe des Speichers:
gameboy music club @ rhiz
Am 25.8.2005 ab ~21:00 Uhr im rhiz.
Es spielen die üblichen Verdächtigen.
gbmc presents: curated by members: grabherr, suszynski
21h live (open air): gbmc open: tableconcerts
djs: sirene, michael suszynski visuals by gürtel eintritt frei
dotmatrix @ gürtel nightwalk
Am Gürtel Nightwalk, am 27.8.2005, gibt’s dann gleich nochmal Gameboy Musik und zwar von dotmatrix.
Das gute im Programm im Groben: Tunakan ab 19:15 Uhr bei der Hauptbücherrei, um 20:00 Uhr dotmatrix im rhiz und nachher dann ab 21:00 Uhr Velojet im Chelsea.
f-prot & amavisd – Stichtag 15.08.2005
Ich benutze, wie bei den vorherigen Blog-Einträgen ja bereits bemerkt, Postfix + amaivsd zum Mails scannen.
Desweiteren benutze ich auch das autoupdater-script, sodass das Programm immer am aktuellsten Stand bleibt. Nur leider hat das auch seine negativen Seiten. Mit Stichtag 15.08.2005 bekam ich plötzlich keine Mails mehr zugestellt. Ein kurzer Blick in top
ergab, dass die f-prot virenscanner-Prozesse hängen bleiben und volle CPU-Last fressen, was einen sehr hohen load auf den betroffenen Systemen zur Folge hat
und eine Mailzustellung verhindert.
Durch eine Suche in den Gogle groups fand ich die Ursache für das Problem:
http://lists.debian.org/debian-release/2005/08/msg00054.html
Hier ist die Lösung, wie ich das Problem behoben habe (der Tip der obrigen URL klappte bei meinen Installationen nicht):
killall -9 f-prot
/etc/init.d/amavis stop
# respektive: /etc/init.d/amavis-postfix stop
/etc/init.d/postfix stop
rm /usr/bin/f-prot
vi /usr/bin/f-prot
---- /usr/bin/f-prot ---
#!/bin/sh
sh -c "/usr/lib/f-prot/f-prot $1 $2 $3 $4 $5 $6 $7 $8 $9"
---------------------------
chmod +x /usr/bin/f-prot
/etc/init.d/amavis start
# respektive: /etc/init.d/amavis-postfix start
/etc/init.d/postfix start
/etc/init.d/fetchmail awaken
postqueue -f
Anschließend wie üblich mit
tail -f /var/log/mail.log
überprüfen, ob alles wieder läuft.
WORD (=USHORT) = 32bit ?
Heute hatte ich ein interessantes Problem:
Ich wollte ein kleines Tool zum Schreiben von .DBF (DBASE) Dateien schreiben und habe daher
die Datenstrukturen entsprechend in einer Struktur definiert.
Als ich dann mittels sizeof()
die Größe der Struktur ermitteln wollte, war diese leider größer, als sie sein sollte. Die Struktur beinhaltete unter Anderem auch WORDs (=unsigned short), um 16bit-Werte zu repräsentieren. Diese sind auf einer 32bit-Architektur jedoch 32bit groß, was zu dieser Inkonsistenz führte.
Endlich weiß ich, wie man das Problem behebt:
#pragma pack(1)
Dadurch erfolgt die Ausrichtung der Größen entsprechend, sodass es eine lückenlose Speicherbelegung gibt.