Custom Installer And XML Serialization There was an error generating the XML Document - FileNotFoundException

I've recently had an issue that's wasted an entire day of my life that I'd like to share.

We have some classes that serialize to XML. These work correctly in all scenarios. Or so I thought.

We have a .NET Custom Installation Action written in C#. During the installation process the custom action opens one of these classes, configured the properties of the class and then saves it as XML. The code works correctly when executed from a test Windows Form application however fails with the following error when it is executed from the installer or from InstallUtil.exe.

System.InvalidOperationException: There was an error generating the XML document. ---> System.IO.FileNotFoundException: Could not load file or assembly 'filename' or one of its dependencies. The system cannot find the file specified.

Very strange as the file specified is in the same directory as the custom action.

Looking at the code in the custom action it seems that the codebase is being set to C:\windows\Microsoft.NET\Framework\v2.0.50727 rather than the directory where the custom action dll is found. This must be an action by Windows Installer / InstallUtil.exe.

If you place the dlls in the C:\windows\Microsoft.NET\Framework\v2.0.50727 directory then everything works correctly.

This is obviously not ideal so the workaround we have implemented is to use the AssemblyResolve event - this is fired when .NET can't find an assembly and you can helpfully point it in the right direction, in this case we simply point it back to the directory in which the executing assembly is located and everything is back to normal!

AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);


/// <summary>
/// Workaround for the location of assemblies in the current directory
/// </summary>
/// <returns>The assembly loaded from the current directory.</returns>
Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    String AssemblyShortName = args.Name.Split(new string[] { "," }, StringSplitOptions.None)[0];
    String RootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    String AssemblyPath = String.Format(@"{0}\{1}.dll", RootPath, AssemblyShortName);
    return Assembly.LoadFrom(AssemblyPath);
}


Take a look at XIA Configuration - Server Documentation

Comments

Popular posts from this blog

Windows Server 2016, 2019, 2022, Windows 10 and Windows 11: Date and time "Some settings are managed by your organization".

TFTPD32 or TFTPD64 reports Bind error 10013 An attempt was made to access a socket in a way forbidden by its access permissions.

Windows Server 2019 desktop icons such as My Computer, Windows cannot access the specified device, path, or file.