IoC does not initialize on Win7 / XP

I had a rather strange problem trying to run a WPF application on Win7 / XP. The WPF application targets .NET 4.0, and it references Caliburn.Micro 1.5.2 and Autofac 3.1.0 .

I am going to start with a summary of the problem, and then I will give details about what I have.

Overview

In my dev workstation I have Windows 8 and Visual Studio 2012. I use Caliburn and Autofac as described in this post (basically a simplified version of this ).

When I create and run the application in my dev machine, everything goes as expected. However, when I take the binaries and execute them on a Windows 7 / XP machine, I get the following error with a long stacktrace:

System.InvalidOperationException: IoC is not initialized 

The only difference I see between environments (other than the OS) is that my dev workstation has .NET 4.5, while Win7 / XP has .NET 4.0.

DETAILS

I was able to reproduce the problem with a simple application. Decision:

enter image description here

ShellViewModel is just an empty Conductor<Screen> . ShellView has only a TextBlock .

App.xaml follows App.xaml recommendations:

 <Application x:Class="WpfApplication2.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication2"> <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary> <local:Bootstrapper x:Key="bootstrapper" /> </ResourceDictionary> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> </Application> 

App.xaml.cs code App.xaml.cs been modified to detect and display exceptions:

 public partial class App : Application { public App () { // hook on error before app really starts AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); try { this.InitializeComponent(); } catch (Exception e) { MessageBox.Show(e.ToString()); throw; } } public static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { MessageBox.Show(((Exception)e.ExceptionObject).ToString()); } } 

The interesting part is Bootstrapper . As said, I have an application that works with Caliburn and Autofac, that works with Bootstrapper , similar to the one described here . For example, I created a simplified version:

 public class Bootstrapper : Bootstrapper<ShellViewModel> { private IContainer container; protected IContainer Container { get { return this.container; } } protected override object GetInstance(Type serviceType, string key) { if (string.IsNullOrWhiteSpace(key)) { if (container.IsRegistered(serviceType)) return container.Resolve(serviceType); } else { if (container.IsRegisteredWithName(key, serviceType)) container.ResolveNamed(key, serviceType); } throw new Exception(string.Format("Could not locate any instances of contract {0}.", key ?? serviceType.Name)); } protected override IEnumerable<object> GetAllInstances(Type serviceType) { return this.Container.Resolve(typeof(IEnumerable<>).MakeGenericType(serviceType)) as IEnumerable<object>; } protected override void BuildUp(object instance) { this.Container.InjectProperties(instance); } protected override void Configure() { var builder = new ContainerBuilder(); builder.RegisterType<ShellViewModel>(); builder.RegisterAssemblyTypes(this.GetType().Assembly); builder.RegisterType<WindowManager>() .As<IWindowManager>() .SingleInstance(); builder.RegisterType<EventAggregator>() .As<IEventAggregator>() .SingleInstance(); this.container = builder.Build(); } } 

On my workstation, this works fine:

enter image description here

I set some breakpoints in the Bootstrapper GetInstance methods and they hit correctly.

Then I took the binaries (bin / Debug) and tried to run them on a Windows XP / 7 virtual machine. The application does not start, and I get the following exception:

 System.InvalidOperationException: IoC is not initialized. at Caliburn.Micro.IoC.<.cctor>b__0(Type service, String key) in c:\Users\Rob\Documents\CodePlex\caliburnmicro\src\Caliburn.Micro.Silverlight\IoC.cs:line 13 at Caliburn.Micro.IoC.Get[T](String key) in c:\Users\Rob\Documents\CodePlex\caliburnmicro\src\Caliburn.Micro.Silverlight\IoC.cs:line 32 at Caliburn.Micro.BootstrapperBase.DisplayRootViewFor(Type viewModelType, IDictionary`2 settings) in c:\Users\Rob\Documents\CodePlex\caliburnmicro\src\Caliburn.Micro.Silverlight\Bootstrapper.cs:line 254 at Caliburn.Micro.BootstrapperBase.DisplayRootViewFor[TViewModel](IDictionary`2 settings) in c:\Users\Rob\Documents\CodePlex\caliburnmicro\src\Caliburn.Micro.Silverlight\Bootstrapper.cs:line 264 at Caliburn.Micro.Bootstrapper`1.OnStartup(Object sender, StartupEventArgs e) in c:\Users\Rob\Documents\CodePlex\caliburnmicro\src\Caliburn.Micro.Silverlight\Bootstrapper.cs:line 288 at System.Windows.Application.OnStartup(StartupEventArgs e) at System.Windows.Application.<.ctor>b__1(Object unused) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler) at System.Windows.Threading.DispatcherOperation.InvokeImpl() at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state) at System.Threading.ExecutionContext.runTryCode(Object userData) at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Windows.Threading.DispatcherOperation.Invoke() at System.Windows.Threading.Dispatcher.ProcessQueue() at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler) at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) at MS.Win32.UnsafeNativeMethods.MessageBox(HandleRef hWnd, String text, String caption, Int32 type) at System.Windows.MessageBox.ShowCore(IntPtr owner, String messageBoxText, String caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options) at System.Windows.MessageBox.Show(String messageBoxText) at WpfApplication2.App..ctor() in c:\Users\Public\Projetos\Outros\WpfApplication3\WpfApplication2\App.xaml.cs:line 27 at WpfApplication2.App.Main() in c:\Users\Public\Projetos\Outros\WpfApplication3\WpfApplication2\obj\Debug\App.g.cs:line 0 

This message is the expected behavior when the IoC class is called before it is initialized, as we can see in the Caliburn source . However, the IoC correctly initialized immediately after invoking Bootstrapper on Configure . See BootstrapperBase.StartRuntime Method in Source .

If I remove all dependency injection logic from Bootstrapper, the application works fine on Win XP / 7.

I spent some time trying to find what exactly caused this behavior. I removed everything from Bootstrapper , and after some attempts, all it takes to cause the problem:

 public class Bootstrapper : Bootstrapper<ShellViewModel> { protected override void Configure() { var builder = new ContainerBuilder(); builder.RegisterType<ShellViewModel>(); } } 

If I comment on the line builder.RegisterType<ShellViewModel>(); The application is running.

Conclusion: The simple act of registering something in an Autofac ContainerBuilder causes behavior. I donโ€™t even need to use it. I am completely puzzled by this.

I spent hours on this problem. I really want to use Caliburn and Autofac because I like them. If anyone could shed light on this, I would appreciate it.

UPDATE

I noticed that if I make a call to MessageBox.Show in the Bootstrapper.Configure method, the observed behavior ("IoC is not initialized") will even debug with VS2012 in my Win8:

 public class Bootstrapper : Bootstrapper<ShellViewModel> { protected override void Configure() { MessageBox.Show("Configure"); } } 

I think about it, but I donโ€™t know what that means.

UPDATE

Link for an example application.

UPDATE

After analyzing the observed behavior, I came to the conclusion (as Sniffer did) that the cause of the "IoC was not initialized" error was not an injection of dependencies, but a call to MessageBox.Show before the Bootstrapper started.

I changed the MessageBox.Show routines to Nlog to write errors to the file, and with that I was able to track the real exception. The real problem is that Autofac is PCL-targeted and in order for it to work with the .NET 4.0 Client Profile, I need to install update 4.0.3 on the target machine .

However, setting aside the original problem, there is actually a problem with Caliburn. Calling MessageBox.Show before initializing Bootstrapper launches a completely new application launch process that occurs between IoC configurations, throwing an observed exception.

I believe that the current issue deviated from the original goal, and I think that it should be closed. I will create a new question that addresses the issue of Caliburn.Micro in an environment that is not affected by my specific application issues.

+4
source share
2 answers

Ok, I ran your code on my XP machine and ran into a problem with your last update, the one in which you used the MessageBox class, and this caused problems on your Windows 8 machine, but the previous code in which you create a new container and register ShellViewModel , which, as you said, caused problems on your win 7 / xp machine, did not , which caused me any problems (it compiled and works fine).

Now I was wondering why using the MessageBox.Show() method inside the Configure method throws this exception, and I kind of understood the reason for this, and it boils down to the following:

  • Caliburn.Micro (CM from here after) The Bootstrapper<TRootModel> calls Start()
  • Start() calls StartRuntime()
  • StartRuntime() calls in this particular order: Configure() then IoC.Get = GetInstance , and then IoC.GetAllInstances = GetAllInstances; and then IoC.BuildUp = BuildUp;
  • When StartRuntime() calls Configure() , your code is executed, in particular MessageBox.Show() , which is a system function that requires (necessarily) that each message window has a default owner and owner window - this is the current active window applications.
  • Now at this stage part of the system code is executed, I donโ€™t know what is being executed, but the piece of code that is executed by the system calls the OnStartup() method, which overrides the CM in the bootloader and uses it to display the view for the TRootModel of your choice.
  • For Caliburn to display the view for this TRootModel , it needs an IWindowManager instance and for it to use (you found out) our favorite IoC , which, as you see in step 3, is not initialized yet , it still adheres to this Configure() method and does not moves.

Summary: The code with the container configuration works without problems on my Win XP machine, but the code with MessageBox.Show() by the Configure() method does not override> and I gave you a detailed explanation of the reason.

+1
source

use this code to show a message from the bootloader:

 Execute.OnUIThread(() => { MessageBox.Show(m); }); 

Also continue executing this line if an error occurs in Configure:

 DisplayRootViewFor<MainViewModel>(); 
0
source

Source: https://habr.com/ru/post/1491182/


All Articles