Eingebettete Ressource nutzen
-
Hallo
ich habe in einem Projekt eine c#-DLL erstellt
dir unter Properties mehre Ressourcendateien enthält z.B.:Properties/Resource.resx
Properties/Resources.de.resx
Properties/Resources.fr.resxalle Ressourcen sind auf eingebettet eingestellt.
Wenn ich jetzt über den ResourceManager diverse Strings abfrage
erhalte ich leider immer nur die Strings aus der Standard-resx-Datai.
z.b.System.Resources.ResourceManager rm = Properties.Resources.ResourceManager; string result = rm.GetString("OneTen", new CultureInfo("de")); showDebugMessage(result); result = rm.GetString("OneTen", new CultureInfo("fr")); showDebugMessage(result);
Hinzu kommt das die c#-DLL von einen externen Programm ausgeführt wird
dieses liegt zb. unter
C:\Program Files (x86)\externeAPP
und die c#DLL
c:\cSharpDLL\
Wenn ich die Ressourcen-Ordner aus dem C# DLL-Ordner in das Bin-Verzeichnis der externen Anwendung kopiere funktioniert die Übersetzung einwandfrei. Mir ist es leider nicht erlaubt die ganzen Ordner dorthin zu kopieren. Was kann man da tun, dass der ResourcenManager trotzdem korrekt arbeit?
Viele Grüße
-
Könnte es sein, dass ich die cSharp-DLL in eine eigene Domain laden muss?
Zur Zeit wird das Assembly einfach in der Schnittstellen-DLL der externen Anwendung über ein currentDomain->AssemblyResolve- Event nachgeladen, wenn ich auf Member der cSharp-DLL zugreife.Assembly^ newAssembly = Assembly::LoadFile(pathToManagedAssembly); return newAssembly
-
Hi,
ich hab mal versucht die Assembly in eine separate Domain zu laden,
falls das überhaupt mein Problem löst, jedoch bricht er mit einer Exception
bei dem versuch ab. :"Die Datei oder Assembly oder eine Abhängigkeit davon wurde nicht gefunden. Der angegebene Assemblyname oder die Codebasis ist ungültig. (Ausnahme von HRESULT: 0x80131047)"
hier mein Versuch in der currentDomain->AssemblyResolve
..... AppDomainSetup tAppSetup = new AppDomainSetup(); tAppSetup.ApplicationName = "CsharpLibrary"; tAppSetup.ApplicationBase = directory; tAppSetup.PrivateBinPath = directory; tAppSetup.ShadowCopyFiles = "true"; ... AppDomain tAppDomain = AppDomain.CreateDomain("LIBD", null,tAppSetup); if(System.IO.File.Exists(pathToManagedAssembly)) { Assembly newAssembly = tAppDomain.Load(pathToManagedAssembly); return newAssembly; }
einer eine Idee was ich da falsch mache?
-
Also ich kann dir sagen, wie ich das in meinen C# Programmen/Bibliotheken mache:
Die Ressourcen liegen ganz normal als "MyTextResource.resx" vor. Da steht der deutsche Quark drin.
Nachdem ich den Code kompiliert habe, gehe ich mit Visual Localize drüber und übersetze die Texte. Der generiert mir dann eine "MyLibrary.resources.dll", die er z.B. in das Unterverzeichnis "en" packt.
Sobald die CurrentCulture bzw. eig. CurrentUICulture auf iwas mit en steht, also z.B. en-GB, dann wird automatisch auf die Satelliten-DLL mit den englischen Ressourcen benutzt.
-
Ja, genau so habe ich es ja auch gemacht. Leider findet .Net anscheinend die Satelliten-DLL nicht, da die Bibliothek von einem externen Programm gerufen wird und in dem Ordner des externen Programms, befinden sich nicht die Satelliten-DLLs.
Wenn ich sie in das Bin-Verzeichnis des externen Programms kopiere funktioniert es ja, ich darf die da aber nicht dorthin kopieren. Sie müssen bei der .Net- Bibliothek liegen.
zb.c:\externesProgramm\bin\app.exe
c:\cSharpDLL\app.dll
c:\cSharpDLL\de\app.resources.dll
-
Und wie rufst du die DLL aus deinem Hauptprogramm auf? Irgendwie muss ja die Verbindung zwischen den zweien hergestellt werden
-
wie die "wrapper" DLL gerufen bzw. angesteuert wird weiß ich nicht genau, da habe ich keinen Einblick. Ich weiß nur das die Schnittstellen in der DLL
per .def Datei public gemacht werden müssen. Die Definition der Funktionen
in der DLL muss so aussehenLPCSTR __stdcall funktionsName(const char* );
da die Kommunikation komplett über char* erfolgt und mir das Programmieren
von gui Elementen in C zu anstrengend war hab ich bei der DLL einfach
CLI Unterstützung angestellt und ein Verweis auf die cSharp-Dll gesetzt
in der dann alles Programmiert wurde.
-
Okay, also jetzt mal langsam
Du hast eine Anwendung, welche eine DLL aufruft?
In welcher Technologie ist die Anwendung implementiert? In welcher die DLL? Und was hat C++/CLI bzw. eine Wrapper-DLL jetzt damit zu tun?Hast du eine Dll mit C# erstellt und für diese DLL eine weitere DLL (mit C++/CLI) als Wrapper, welche eine C-style-Schnittstelle für die aufrufende Anwendung bietet?
-
ok ich hab mal ein Bild gemalt
[url]
http://dl.dropbox.com/u/69535794/beispiel.jpg
[/url]
-
Schick
Bin mir nicht sicher ob dir das weiterhilft, aber schau's dir mal an: http://stackoverflow.com/questions/8527306/deploying-net-satellite-assemblies-in-specific-folder
Insgesamt ist deine Situation etwas ungewöhnlich, wenn auch nicht realitätsfremd. Ich habe aber in der Richtung noch nicht viel gemacht und müsste daher erst mal ein Testprojekt aufziehen, damit ich das nachvollziehen kann.
-
Hallöchen ,
dein Beispiel hab ich mir angeschaut, allerdings
steht darunter :
"You can specify any directories that exists below the application executable file. " das würde ja in meinen Fall ja wieder die externe Anwendung sein.
und selbst wenn es funktioniert müsste ich ja quasi den absoluten Pfad angeben, was ich nicht so toll wäre.Damit du nicht extra 2 TestProjekte anlegen musst um es nachzuvollziehen, hab ich das mal gemacht. Die 2Projekte simulieren im Prinzip meine Situation. Das eine Projekt erzeugt eine Exe -Datei die, die 2 DLL aus dem anderen Projekt aufruft.
Ob die EXE- aus dem Beispielprojekt den Aufruf genauso macht, wie die externe Anwendung die ich eigentlich verwende, weiß ich nicht so genau, jedoch reproduziere ich hier das gleiche verhalten.
[url]
http://dl.dropbox.com/u/69535794/beispiel.zip
[/url]
Die zwei generierten DLL sollten unter C:\externin
leigen sonst findet die exe Datei die dlls nicht. Oder du passt den Pfad halt an.
Vielen dank schon mal
-
Jo, also ich werd erst wieder am Dienstag dazu kommen, mir das anzusehen.. bis dahin ist Programmier-Freie Zeit
-
Hi,
ich hab mich jetzt noch mal daran versucht
in meinem Beispielprojekt die c#DLL in eine separate Domain
zu laden.
Er lädt zwar die DLL aber scheint trotzdem nicht zu funktionieren
wie ich es mir erhofft hatte. Es wird scheinbar das Assembly
in die Hauptdomain geladen, da durch irgendein Grund AssemblyResolve gefeuert wird
. Wahrscheinlich muss ich mich wohl vom Gedanken verabschieden, SatellitenDLL zu verwenden und einen file-Basierten RessourcenManager anlegen.
grüßehier der Versuch in separate Domain zu laden:
void AssemblyUtilities::testAppDomian() { ::System::Windows::Forms::MessageBox::Show("testAppDomain"); ::System::String^ directory = "c:\\externin\\"; ::System::AppDomainSetup^ tAppSetup = gcnew ::System::AppDomainSetup(); tAppSetup->ApplicationName = "CsharpLibrary"; tAppSetup->ApplicationBase = directory; tAppSetup->PrivateBinPath = directory; tAppSetup->ShadowCopyFiles = "true"; ::System::AppDomain^ tAppDomain = ::System::AppDomain::CreateDomain("LIBD", nullptr,tAppSetup); ::System::String^ pathToManagedAssembly = "c:\\externin\\cSharpDLL.dll"; if(System::IO::File::Exists(pathToManagedAssembly)) { try { array<byte>^ tASMbyte; ::System::IO::FileStream^ fs = gcnew ::System::IO::FileStream(pathToManagedAssembly, ::System::IO::FileMode::Open); int tLength = (int)fs->Length; tASMbyte = gcnew array<byte>(tLength); fs->Read(tASMbyte, 0, tASMbyte->Length); fs->Close(); ::System::Object^ tObj = tAppDomain->CreateInstanceAndUnwrap("cSharpDLL","cSharpDLL.Class1"); ::System::Reflection::MethodInfo^ mI = tObj->GetType()->GetMethod("showFrom",::System::Reflection::BindingFlags::Public | System::Reflection::BindingFlags::Static); mI->Invoke(nullptr,nullptr); } catch(::System::Exception^e) { ::System::Windows::Forms::MessageBox::Show(e->ToString()); } } }