1
votes

I have a WPF-Application with 3 xaml files: App.xaml, StartWindow.xaml and MainWindow.xaml. If I start the application, I want to show either StartWindow or MainWindow depending on a condition. My solution is to write a custom Main method in App.xaml.cs:

public static String DEBUG = "true";

[STAThread]
static void Main()
{
    App app = new App();
    if (/*condition*/)
        app.Run(new MainWindow());
    else
        app.Run(new StartWindow());
}

The App.xaml property build action is set to "Page". (I followed this guide: Guide, although it still works with StartupUri set to "MainWindow.xaml" and without App()).

The StartWindow constructor has following code:

public StartWindow()
{
    InitializeComponent();

    Task.Run(() =>
    {

        // Some initialization code
        Console.WriteLine(App.DEBUG);

        Application.Current.Dispatcher.Invoke(() =>
        {
            MainWindow mainWindow = new MainWindow();
            mainWindow.Show();
            this.Close();
        });
    });
}

This works perfectly fine on my development machine, but not on a different one (Virtual machine with same OS and target .NetFramework installed). If I set a Breakpoint after Console.WriteLine(App.DEBUG), it prints out the string on both environments, but the properties look different and also shortly after that it throws an exception:

Properties on breakpoint:

Properties

Exception (Text says "can't find ressource "mainwindow.xml""):

Exception

Properties on breakpoint on my development machine where it works:

Working

Why is it still looking for MainWindow.xml, or even stanger mainwindow.xaml? And why only on one machine?

1
You should try to decompile your application using ILSpy (github.com/icsharpcode/ILSpy/releases); this way, you'll be able to see what code was generated in InitializeComponent for instance. I already solved this kind of problems this way! - odalet
Thanks. The InitializeComponent() On StartWindow and MainWindow both look correct. They create a new Uri which point to startwindow.xaml and mainwindow.xaml respectively. The one in App has following code: base.StartupUri = new Uri("MainWindow.xaml", UriKind.Relative); if (!_contentLoaded) { _contentLoaded = true; Uri resourceLocater = new Uri("/...;component/app.xaml", UriKind.Relative); Application.LoadComponent(this, resourceLocater); } While it doesnt look correct at first, how can it work on one machine and not the other? - notan
Honestly, I d'ont explain myself how it can behave differently on 2 machines (Release vs Debug build?). What I did, trying to reproduce your problem - which I didn't - is to get rid of the StartupUri in app.xaml and to invoke InitializeComponent in App's constructor. Note that if you do nothing in app.xaml (no styles or resources), you can also decide not to call InitializeComponent at all! - odalet
On a side note, when you log App.DEBUG from StartWindow, this means nothing: because DEBUG is static, it only means the App class was successfully initialized... it does not even prove the App instance was created, though it was otherwise, StartWindow would not have been created. - odalet
Thaks for your help, i figured it out and posted an answer. - notan

1 Answers

0
votes

I figured it out:

In the // Some initialization code part of the code is a check for a specific value in a configuration file. The value was already correclty set on my development machine, in which case the programm didnt have to perform a write operation to a file to correct the value. On the other machine, this value wasnt correct (It's a path to a file). The program than tried to write to that file. The file is located under C:\ProgramData\PROGRAMNAME\, where apparently no writing was permitted. This resulted in the exception and the constructor not properly finishing.

I now store the files under ..\AppData\Local\PROGRAMNAME