Benutzer mit den meisten Antworten
Satelite Assemblies werden im Release nicht richtig geladen - wie handeln?

Frage
-
Hallo miteinander,
ich habe eine Solution mit 4 Projekten: 1. Controls, 2. Base, 3. Resources, 4. Applikation.
Nun möchte ich die Applikation releasen.
Wenn ich aber die .exe aus dem Release Ordner starte, erhalte ich die Meldung dass das referenzierte Assembly Controls nicht gefunden wurde.
Alle Assemblies sind jedoch im Release Ordner vorhanden.
Muss ich die Aufrufe extra umbauen?
In der Entwicklungs Umgebung funktioniert die Applikation tadellos.
Danke & sonnige Grüsse aus der Schweiz- Bearbeitet GreenLion Donnerstag, 12. Juni 2014 06:13
Antworten
-
Hallo,
danke für deine Antowrt.
habe inzwischen die Lösung gefunden.
Es lag unter anderem am fehlenden VS 2012 Update Pack (aktuell 4).
dann musste ich eigentlich nur die Controls, BaseLib Libraries per Buil-Script an einen separaten Ort kopieren lassen und von dort konsumieren.
Etwas speziell ist die nötige Referenzierung im App.xaml - dort muss nebst dem Generic.xaml vom Controls Projekt, die einzelnen Sprachresourcen referenziert werden die in den Resource.dll liegen.
Komisch - aber funktioniert so für mich.
Danke & Gruess
- Als Antwort markiert Ionut DumaModerator Donnerstag, 10. Juli 2014 14:23
Alle Antworten
-
Nachtrag:
habe mich mit folgendem Artikel schlau gemacht: http://msdn.microsoft.com/en-us/library/cc668131%28v=vs.90%29.aspx
jedoch ist das nicht ganz das wonach ich gesucht habe.
aber die assemblys sind jetzt als satelite definiert.
muss ich jetzt jeden Zugriff umschreiben, welcher auf die andere Assemblie greift?
Es ist leider mein erstes Projekt mit mehreren Satelite Assemblies.
für Unterstützung wäre ich sehr dankbar.
Gruss aus der Schweiz
-
Nachtrag:
mit dem Click Once deployment klappt es wunderbar.
wenn ich jedoch die exe aus dem "Release" Ordner starten möchte, klappt dies nicht.
Das Programm stürzt bei der ersten verwendung / Aufruf eines Elements aus einem anderen Assemblie, gleich ab.
Woran könnte das liegen?
Wäre sehr froh um ein paar Inputs.
Danke & Grüsse
-
Hi,
wenn ich dein Problem richtig versanden habe, ist das Controls Projekt vermutlich eine Klassenbibliothek mit Resourcendatein für unterschiedliche Sprachen (bzw. Cultures).
Diese Resourcendateien haben vermutlich einen Aufbau ähnlich diesem:
ressources.en-US.resx
resources.de-DE.resx
resources.fr-FR.resx
usw...
Jede dieser Resourcedateien enthällt z.B. Zeichenketten in der jeweiligen Sprache und wurden als separate Assemblies erstellt. Es müsste demnach im Release Verzeichnis eine Ordnerstruktur wei folgt geben:
de-DE/Controls.resources.dll
en-US/Controls.resources.dll
fr-FR/Controls.resources.dll
Beim Deployment bzw. Start der Hauptanwendung muss das Assembly mit den Resourcen für die jeweilige Sprache in einem Verzeichnis mit dem Culture-Code exisitieren also z.B. in ../fr-FR/ für die Darstellung in französisch.
Kann es sein dass die Assembly für die Sprache, welche du innerhalb der Anwendung verwenden willst direkt im Root-Verzeichnis liegt und nicht in dem Untergeordneten Verzeichnis mit dem Culture-Code?
Wenn dies der Fall ist, kann das "Start" Assembly die passenden Resource-Assemblies nicht finden und es wird eine MissingManifestResourceException verursacht.
Beim Click-Once Deployment funktioniert dies, da dann die Verzeichnisse mit den Culture-Codes angelegt werden.
Wie legst du innherhalb des Controls Projekts fest, welche Sprache verwendet werden soll?
Evtl. wie folgt:
...
ChangeCulture("en-US"); ...
private void ChangeCulture(string selectedLanguage) { Thread.CurrentThread.CurrentCulture = new CultureInfo(selectedLanguage); Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(selectedLanguage); lblLanguage.Content = _resourceManager.GetString("Language"); }
Vielleicht könntest du noch Beispielcode oder mehr Details zur Konfiguration posten.
Gruß
JohSu
-
Hallo JohSu,
danke für deine Antwort.
Mein Projekt sieht folgendermassen aus:
Die Sprachen werden folgendermassen geladen (app.xaml.cs):
protected override void OnStartup(StartupEventArgs e) { SetImportCatalog(); //SetLanguage(); } private void SetImportCatalog() { try { string path = AppDomain.CurrentDomain.BaseDirectory; DirectoryCatalog catalog = new DirectoryCatalog(path); CompositionContainer container = new CompositionContainer(catalog); container.ComposeParts(BaseModel.Instance.ImportCatalog); } catch (Exception ex) { MessageBox.Show(ex.Message); } }
desweiteren kann die Sprache zur Laufzeit geändert werden - diese Funktionalität ist ebenfalls im app.xaml.cs hinterlegt und sieht so aus:
public void SetLanguage(CultureInfo culture) { try { CultureInfo cultureInfo = culture; Thread.CurrentThread.CurrentCulture = cultureInfo; Thread.CurrentThread.CurrentUICulture = cultureInfo; var dictionary = (from d in BaseModel.Instance.ImportCatalog.ResourceDictionaryList where d.Metadata.ContainsKey("Culture") && d.Metadata["Culture"].ToString().Equals(culture.ToString()) select d).FirstOrDefault(); if (dictionary != null && dictionary.Value != null) { Resources.MergedDictionaries.Add(dictionary.Value); } } catch (Exception ex) { MessageBox.Show(ex.Message); } }
Somit funktioniert es eben auch dass ich die Resourcen als Resourcedictionary einsetzen kann.
Ob jetzt das etwas mit dem zutun dass ich dann die Applikation nicht starten kann?
Folgende Assemblies landen bei mir im bin/debug/ ordner (oder eben im bin/release):
Controls, KSR (App), Resources, Products
im manifest der Applikation sind alle Assemblies hinterlegt (falls das überhaupt nötig wäre).
was habe ich vergessen?
Danke & sonnige Grüsse aus der Schweiz
-
Hi,
so Leid es mir tut das sagen zu müssen, aber bei mir funktioniert es einwandfrei.
Ich hab versucht deine Projektstruktur nachzubauen:
1. Projekt Controlls wird als Klassenbibliothek kompiliert und beinhaltet die Exports für MEF.
2. Projekt KSR ist die eigentliche WPF Anwendung und beinhaltet die Imports für MEF.
3. Projekt Resources wird als Klassenbibliothek kompiliert und beinhaltet die ResourceDictionaries, welche im Projekt KSR verwendet werden.
Wenn ich alle drei Assemblies in ein beliebiges Verzeichnis verschiebe und starte, kann ich die KSR WPF Anwendung starten und über die Konfiguration
die Sprache wechseln.
Die Projektstruktur im Überblick:
Der Code ist wie folgt:
Projekt Controls:
ControlDeutsch.cs:
[Export(typeof(ILanguage))] public class ControlDeutsch : ILanguage { private ResourceDictionary _resourceDictionary; public string CultureCode { get { return "de-DE"; } } public ControlDeutsch() { _resourceDictionary = new ResourceDictionary(); _resourceDictionary.Source = new Uri("pack://application:,,,/Resources;component/ResourceDictionary_de-DE.xaml", UriKind.Absolute); } public System.Windows.ResourceDictionary ResourceDictionary { get { return _resourceDictionary; } } }
ControlEnglish.cs:
[Export(typeof(ILanguage))] public class ControlEnglish : ILanguage { private ResourceDictionary _resourceDictionary; public string CultureCode { get { return "en-US"; } } public ControlEnglish() { _resourceDictionary = new ResourceDictionary(); _resourceDictionary.Source = new Uri("pack://application:,,,/Resources;component/ResourceDictionary_en-US.xaml", UriKind.Absolute); } public System.Windows.ResourceDictionary ResourceDictionary { get { return _resourceDictionary; } } }
Projekt KSR:
ILanguage.cs:public interface ILanguage { string CultureCode { get; } ResourceDictionary ResourceDictionary { get; } }
App.xaml.cs:
public partial class App : Application { [ImportMany(typeof(ILanguage))] public IEnumerable<ILanguage> Languages { get; set; } protected override void OnStartup(StartupEventArgs e) { ImportLanguages(); SetLanguage(Settings.Default.Language); } private void ImportLanguages() { var catalog = new DirectoryCatalog("."); CompositionContainer container = new CompositionContainer(catalog); container.ComposeParts(this); } private void SetLanguage(string cultureCode) { if (Languages == null) return; var language = Languages.Where(l => l.CultureCode == cultureCode).FirstOrDefault(); if (language == null) return; Resources.MergedDictionaries.Add(language.ResourceDictionary); Thread.CurrentThread.CurrentCulture = new CultureInfo(cultureCode); Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultureCode); } }
MainWindow.xaml:
<Window x:Class="KSR.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid Grid.Row="1"> <Label x:Name="lblLanguage" Content="{DynamicResource applicationText}" VerticalAlignment="Center" HorizontalAlignment="Center" /> </Grid> </Grid> </Window>
Projekt Resources:
ResourceDictionary_de-DE.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib"> <system:String x:Key="applicationText">Das ist der Text in deutsch</system:String> </ResourceDictionary>
ResourceDictionary_en-US.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib"> <system:String x:Key="applicationText">This is the text in english</system:String> </ResourceDictionary>
In der App.config in KSR habe ich eine Einstellung "Language" für den CultureCode der anzuzeigenden Sprache. Dies wird in App.xml.cs ausgewertet und das entsprechende ResourceDictionary gemerged.
Vielleicht fällt dir beim durchsehen des Codes was auf, das dir für dein Projekt weiterhilft.
Gruß
JohSu
-
Hi JohSu,
vielen Dank für deine Mühe.
Jedoch sind mir ein paar Sachen noch unklar.
weshalb z.b. muss eine referenz auf das KSR Projekt von Controls aus gemacht werden ?
aktuell habe ich es genau umgekehrt.muss in jedem control ein resourcedicionary angehängt werden?
geschieht dies nicht bereits auf der KSR ebene?Danke & Grüsse
-
Hi,
KSR ist innerhalb von Controls referenziert, da sich das Interface ILanguage in KSR befindet. ControlDeutsch.cs und ControlEnglish.cs implmentieren ILanguage.
Resource muss nicht zwingend in Controls referenziert sein, es funktioniert wunderbar ohne, solange alle Assemblies in einem Verzeichnis liegen.
Zum Zeitpunkt der Projekterstellung, habe ich im Aufruf für den Catalog auf das bin/Debug Verzeichnis von Controls verwießen:
var catalog = new DirectoryCatalog(@"<Projektverzeichnis von Controls>"); // statt "."
Das bedeutet zum Zeitpunkt der Entwicklung waren Controls, KSR und Resources je in einem eigenen Verzeichnis.
Wenn ich Resources nicht innerhalb von Controls referenziert hätte, hätte ich einen Laufzeitfehler bekommen, da z.B. ControlDeutsch.cs das ResourceDirctionary in Resources bei der Instanzierung lädt aber Resources nicht finden kann, da es sich in einem anderen Verzeichnis befindet.
public ControlDeutsch() { _resourceDictionary = new ResourceDictionary(); _resourceDictionary.Source = new Uri("pack://application:,,,/Resources;component/ResourceDictionary_de-DE.xaml", UriKind.Absolute); }
Sobald ich aber Resources in Controls referenziere wird eine Kopie von Resouces im Build Verzeichnis von Controls erstellt woduch sich beide Assemblies im gleichen Verzeichnis befinden und aufgelöst werden können.
Aber wie oben erwähnt war dies nur für die Entwicklung nötig, wenn du sicherstellst, dass alle Assemblies im gleichen Verzeichnis liegen ist die Referenzierung von Resources in Controls überflüssig.
Hoffe das war einigermaßen nachvollziehbar...
Gruß
JohSu
-
Hallo,
danke für deine Antowrt.
habe inzwischen die Lösung gefunden.
Es lag unter anderem am fehlenden VS 2012 Update Pack (aktuell 4).
dann musste ich eigentlich nur die Controls, BaseLib Libraries per Buil-Script an einen separaten Ort kopieren lassen und von dort konsumieren.
Etwas speziell ist die nötige Referenzierung im App.xaml - dort muss nebst dem Generic.xaml vom Controls Projekt, die einzelnen Sprachresourcen referenziert werden die in den Resource.dll liegen.
Komisch - aber funktioniert so für mich.
Danke & Gruess
- Als Antwort markiert Ionut DumaModerator Donnerstag, 10. Juli 2014 14:23