C++ Sprachresourcen (resx) und FileLoadException

Macan

Mitglied
So - ich mal wieder :/

Die Resourcen lassen mich einfach nicht los.
Folgendes habe ich gemacht:
Code:
Locale.resx
Locale.de.resx
sind erstellt und werden auch eingebunden.

Code:
	Thread::CurrentThread->CurrentCulture = gcnew CultureInfo(Name);
	ResMan = gcnew ResourceManager("Client.Locale", Assembly::GetExecutingAssembly());
Obiges ist auch 1:1 aus einem MSDN Beispiel übernommen.

Code:
MessageBox::Show(LocalManager::ResMan->GetString("TestString"));

Der Spass ist, ich bekomme gleich bei Programmstart eine System.IO.FileLoadException (erste Chance). Die wird natürlich schon von der Runtime abgefangen und somit falle ich eben immer auf die eingebettete (englische) Sprachresource zurück. Die Exception kommt bei jedem Durchlauf des obigen Codes.

Die Namen der Dateien sind wohl richtig, denn FxCop zeigt, dass alles richtig eingebunden wurde. Strong Names sind auch in Ordnung und richtig signiert.
Sicherheitshalber habe ich es schon komplett ohne Keys versucht, aber auch das macht keinen Unterschied.

Was übersehe ich da? Weiss das vielleicht jemand?

P.S.: Interessant ist zumindest folgendes: Vorher habe ich ja keine .resx Dateien verwendet und meine .txt Dateien mittels resgen in .resources überführt. Dort gab es zumindest einen Namensunterschied: "Client.Locale" war dann einfach nur "Locale". Aber das dürfte wohl nichts mit dem Fehler zu tun haben (vor allem bekäme ich, würden die Namen nun falsch sein, eine MissingManifest...Exception).
 

Christian Kusmanow

Erfahrenes Mitglied
Hi Markus!

Versuch das ganze mal so:
C++:
gcnew ResourceManager( __typeof(Locale)->FullName, __typeof(Locale)->Assembly );
Wenn es nun klappt, hast einen Fehler in dem "Client.Locale" String drinne. Oder es war nicht die richtige Assembly.
Btw. wenn Du Application.Run in einem try-catch-Block ausführst, bekommst auch die Zeile
und kannst evtl auch noch eine InnerException auslesen....
 
Zuletzt bearbeitet:

Christian Kusmanow

Erfahrenes Mitglied
Das hat witzigerweise nicht funktioniert - bin überfragt, warum. Vielleicht, weil ich kein Form, sondern einen ApplicationContext starte.
Warum ein ApplicationContext? Hast Du vor das Form deiner Anwendung auszutauschen?
Ansonsten würd ich für das eigentliche Programm noch eine Klasse definieren.
Wenn Du schon innerhalb der MainMethode oder in der Klasse die die MainMethode enhält,
auf Namespaces deiner Anwendung zugreifst, bekommst immer einen Laufzeitfehler.
 
Zuletzt bearbeitet:

Macan

Mitglied
Warum ein ApplicationContext? Hast Du vor das Form deiner Anwendung auszutauschen?
Ansonsten würd ich für das eigentliche Programm noch eine Klasse definieren.
Genau. Ich habe da mehrere Forms und will nicht immer alles mit Update() aktualisieren lassen. Die Klasse habe ich auch geschrieben und von ApplicationContext abgeleitet. Funktioniert alles und nur in dieser Klasse arbeite ich eigentlich wirklich (mit namespaces).

Mit diesem typeof (in C++ ist das wohl typeid oder einfach GetType()) kann ich nicht wirklich etwas anfangen. Sprich, ich kann das nicht in C++ übersetzen (finde da FullName, etc. einfach nicht).

Und... nur mal zur Sicherheit:
Code:
	Context^ App = gcnew Context;
	try {
		Application::Run(App);}
	catch (System::Exception^ e)
		{
		MessageBox::Show(e->InnerException->Message);
		}
So sieht mein catch aus. Aber vielleicht bin ich da auf dem falschen Dampfer damit.
 

Christian Kusmanow

Erfahrenes Mitglied
Mit diesem typeof (in C++ ist das wohl typeid oder einfach GetType()) kann ich nicht wirklich etwas anfangen. Sprich, ich kann das nicht in C++ übersetzen (finde da FullName, etc. einfach nicht).
Ja, hast recht. Hab mal auf der MSDN nachgeschaut. __typeof währe dazu sicher das Equivalent dazu in c++.
GetType() macht aber das gleiche...

Und... nur mal zur Sicherheit:
Code:
	Context^ App = gcnew Context;
	try {
		Application::Run(App);}
	catch (System::Exception^ e)
		{
		MessageBox::Show(e->InnerException->Message);
		}
So sieht mein catch aus. Aber vielleicht bin ich da auf dem falschen Dampfer damit.
Nein, bist nicht. Aber Du gibst die Exception ansich gar ned aus.
Eine InnerException ist auch nicht immer verfügbar. D. h. dass es einen zu einer NullReferenceException kommen kann,
wenn Du versuchst auf die InnerException->Message zuzugreifen.
Prüfe daher ob die InnerException nicht null ist und gib sie dann erst mit aus.
 

Macan

Mitglied
Das habe ich nur schnell noch einmal reingetippt. Das Problem ist, dass die MessageBox sich nicht zeigt. Genauso läuft es auch, wenn ich die Zuweisung des ResourceManagers und die GetString() Methode catche - alle Fehler werden wohl schon intern abgefangen und erreichen mich überhaupt nicht:
Eine Ausnahme (erste Chance) des Typs "System.IO.FileLoadException" ist in mscorlib.dll aufgetreten.
ist alles, was ich zu sehen bekomme (im Ausgabefenster).
Würde ich nun ein Namensproblem haben, dann kommt sofort ein Ausnahmefenster.

EDIT: Aber es ist gut zu wissen, immer erst die Existenz der InnerException zu prüfen :)
Noch einmal EDIT: Ich weiss einfach nicht, wie ich den Type von "Locale" bekomme, denn das ist ja keine Klasse, Typ, etc. Oder sehe ich das falsch? (Ist ja nur ein String, der übergeben wird).
Jetzt aber - letzter EDIT: __typeof ist die alte Notation. typeid müsste es dann sein. Aber weder mit GetType, noch mit typeid bekomme ich solch ein Konstrukt hin (mit Fullname, etc.).
 
Zuletzt bearbeitet:

Macan

Mitglied
Hmmm, das könnte vielleicht das Problem sein. Der ResourceManager wird in einer Init-Methode, die gleich am Anfang im Konstruktor der LocaleResourcen-Klasse aufgerufen wird, instantiiert (also mehr oder weniger, denn... static ResMan).
Dann wird diese Init-Methode bei Sprachwechsel wieder aufgerufen (und auch dann kommt immer die FileLoadException).
Ich habe ResMan auch schon nonstatic versucht - macht keinen Unterschied (aber vielleicht hatte ich da auch noch andere Fehler dabei).
Du wirst mir jetzt sicher gleich sagen, dass static das Problem ist, weil dadurch das Object nicht neu instantiiert werden kann? *g*

EDIT: Noch etwas witziges: Wenn ich etwas in den .resx Dateien verändere, dann kommt beim nächsten Start z.B. nur die deutsche Resource... dann beim nächsten Start wieder nur die englische...