Alexander (HH): INI-Datei verschieben

Beitrag lesen

Moin Moin!

Hallo,

Nein, ich weiß, wie man Dateien verschiebt. ;-)

na da bin ich ja beruhigt!

Ich bzw. wir müssen uns mit einer Entwicklungsumgebung + Runtime herumschlagen, die einen Großteil ihrer Einstellungen in einer zentralen INI-Datei ablegt und sie dort natürlich auch wieder sucht.

Das ist fein - ist zumindest schonmal besser als die vielen Programme, die ihre Einstellungen irgendwo in der Registry ablegen.

Ja, finde ich auch. Nur sieht die INI-Datei im Moment (bevor ich den Müll mal aufräume) ähnlich übersichtlich aus wie ein Binärdump der Registry. Naja, das ist eine andere Baustelle.

Blöderweise erwartet dieses System die INI-Datei im Windows-Verzeichnis und nicht in dem Verzeichnis, in dem wir unsere Projekte verwalten. [...]
Letztlich ruft die Anwendung über ein paar Abstraktionslayer die Windows-API-Funktionen GetPrivateProfileString(), GetPrivateProfileInt() und WritePrivateProfileString() auf, das läßt sich anhand der Strings in den EXE-Dateien nachvollziehen.

Die von dir verlinkte Beschreibung von MS ist unvollständig: Anders als dort angegeben suchen diese Funktionen (zumindest bis Windows XP, für Vista oder 7 keine Garantie) die Datei zuerst im Verzeichnis der Applikation (also das Verzeichnis, in dem die EXE-Datei liegt), dann im Windows-Verzeichnis.

Hmmm, genau das hatte ich auch im Kopf, aber das ist das Suchverhalten für DLLs (LoadLibrary()), nicht für INIs.

Und ich hab der Doku auch nicht geglaubt, aber eine blafasel.ini direkt neben meiner Test.EXE wird zugunsten der blafasel.ini im Windows-Verzeichnis ignoriert, wenn ich GetPrivateProfileString(....,"blafasel.ini") aufrufe, sowohl unter XP SP3 als auch unter W2K SP4. Die INI-Datei neben der Test.EXE wird auch dann ignoriert, wenn keine blafasel.ini im Windows-Verzeichnis liegt. GetPrivateProfileString() liefert dann den Wert des Default-Parameters zurück.

Test.c:

  
#include <stdio.h>  
#include <stdlib.h>  
#include <windows.h>  
  
int main(int argc, char ** argv)  
{  
	char buf[1024];  
  
	GetPrivateProfileString("hallo","welt","*DEFAULT*",buf,sizeof(buf),"blafasel.ini");  
	puts(buf);  
	return 0;  
}  

blafasel.ini:

[hallo]
welt=moin

Oder halt exakt da, wo's der Programmierer vorgibt, wenn ein Pfad angegeben wird.

Ja, genau.

Der jeweils letzte Parameter, lpFileName, ist entweder nur der reine Dateiname "blafasel.ini", oder aber einer der Wrapper bastelt noch den Namen des Windows-Verzeichnisses vor "blafasel.ini", das kann ich im Moment nicht sehen.

Das wäre eigentlich unsinnig, aber was heißt das schon ...

Das heißt, dass der Code-Sklave die Doku nicht zuende gelesen hat oder genug Erfahrung mit MS hat, dem dokumentierten Default-Verhalten nicht weiter zu trauen, als er seinen Rechner werfen kann.

Egal wie, in beiden Fällen sucht Windows die INI-Datei ausschließlich im Windows-Verzeichnis, und da gehört sie wenigstens auf den Entwickler-Systemen nicht hin.

Da gehört sie IMHO *grundsätzlich* nicht hin. Ist das Programmverzeichnis für dein Projekt keine gangbare Alternative?

Doch, genau da soll sie hin. Deswegen ja dieser Thread.

Denn da sollte sie als erstes gefunden werden.

Nur wenn die INI eine DLL wäre und per LoadLibrary() geladen würde.

Ich suche also irgendeinen Kniff, wie ich Windows oder die Anwendung dazu bringe, die INI-Datei in einem Verzeichnis meiner Wahl zu suchen.

Nicht ohne Änderung der Anwendung. Selbst wenn man der Anwendung ein anderes Arbeitsverzeichnis zuweist, sucht sie ihre INI-Dateien immer noch im Programmverzeichnis.

Eben. Ich hab keinen Quelltext, ich kann und vor allem DARF die Executables nicht patchen, also bleibt mir nur noch, die Programme jedes Mal wieder im Speicher zu patchen.

Das in Windows implementierte IniFileMapping klingt zwar schön, aber murkst die INI-Dateien nur in die Registry-Müllhalde, wo sie noch schlechter kontrollierbar sind.

ACK.

Bleibt also eigentlich nur noch, die Programme zur Laufzeit auszutricksen. Man müßte die drei Funktionen auf eigene Funktionen umbiegen, so ähnlich wie das iwatch aus dem c't-Artikel Wachtmeister macht, um den Original-Funktionen den "richtigen" Verzeichnispfad mitzugeben.

Puh, das ist dann im Prinzip die gleiche Technik, als wenn ein Debugger ein Programm unter seiner Kontrolle laufen lässt und dessen Code im Arbeitsspeicher beliebig manipulieren kann. Das wird dann richtig fies.

Ja. Ich hab mir gerade mal die Quelltexte ausgepackt. VC4 mit handgemachten Extras. *schauder*

Gibt's was fertiges dafür? Irgendwelche Hinweise? Alternative Ideen?

Leider nein. Das sysinternals-Tool FileMon kann zwar Zugriffe beliebiger Prozesse auf das Filesystem überwachen und protokollieren, aber AFAIK nicht eingreifen.

Richtig. Und laut Regmon fragt weder Entwicklungsumgebung noch Runtime die Registry ab, wo die INI-Datei denn liegen soll. *grummel*

Was waren das noch für Zeiten, als man einfach den DOS-Interrupt 21h abgefangen und die Funktionsnummern und Parameter einfach abgefragt und umgebogen hat ...

Ja, und sich dann irgendwann gewundert hat, warum die Kiste abstürzt, nur weil der blöde Interupt irgendwo ins mittlerweile überschriebene Nirvana zeigt ... ;-)

Alexander

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".