UWP app crashes when using Esri (changing name of assembly fixes this)

947
3
04-16-2020 06:32 AM
AndreasSztybryc
New Contributor

We are experiencing an UWP issue related to Esri Runtime and Toolkit and having UWP libraries.

The issue occurs with Visual Studio 2019 (16.3.9, but newer versions show the same behavior as well).

Attached is a sample project. There is an UWP executable “esriuwp” that uses a class library “ClassLibrary1” that provides a user control that contains a simple Map Control. Nothing fancy.

The problem with this setup is: The application crashes when build this way.

Now it gets stranger than this. When I go to the properties of “ClassLibrary1” and change “Assembly name” and “Default namespace” from “ClassLibrary1” to “FClassLibrary1”, save the solution, exit it, delete obj and bin for both projects, re-open the solution, restore nuget and rebuild the projects again, everything will work as expected.

The details are: “ClassLibrary1” has a nuget Package to “Esri.ArcGISRuntime.Toolkit”, this is important. While this repro code does not necessarily need it, our production does.  (If we would reference only the UWP runtime, the issue would not occur). The “esriuwp” executable project reference only “ClassLibrary1” and has no explicit dependency to Esri.

When the executable (not the class library!) is build, the compiler creates a file called “XamlTypeInfo.g.cs”. With “ClassLibrary1” called “ClassLibrary1”, the “OtherProviders” property is generated in this way:

private global::System.Collections.Generic.List<global::Windows.UI.Xaml.Markup.IXamlMetadataProvider> OtherProviders
{
	get
	{
		if(_otherProviders == null)
		{
			var otherProviders = new global::System.Collections.Generic.List<global::Windows.UI.Xaml.Markup.IXamlMetadataProvider>();
			global::Windows.UI.Xaml.Markup.IXamlMetadataProvider provider;
			provider = new global::ClassLibrary1.ClassLibrary1_XamlTypeInfo.XamlMetaDataProvider() as global::Windows.UI.Xaml.Markup.IXamlMetadataProvider;
			otherProviders.Add(provider); 
			provider = new global::Esri.ArcGISRuntime.Esri_ArcGISRuntime_Universal_XamlTypeInfo.XamlMetaDataProvider() as global::Windows.UI.Xaml.Markup.IXamlMetadataProvider;
			otherProviders.Add(provider); 
			provider = new global::Esri.ArcGISRuntime.Toolkit.Esri_ArcGISRuntime_Toolkit_XamlTypeInfo.XamlMetaDataProvider() as global::Windows.UI.Xaml.Markup.IXamlMetadataProvider;
			otherProviders.Add(provider); 
			_otherProviders = otherProviders;
		}
		return _otherProviders;
	}
}

Three providers are created, ClassLibrary1 is first.

However, when „ClassLibrary1“ is renamed (Assembly name and Default namespace [although Default namespace is only for clarity]) to “FClassLibrary1”, the OtherProviders property looks similar, but FClassLibrary1 comes last now

private global::System.Collections.Generic.List<global::Windows.UI.Xaml.Markup.IXamlMetadataProvider> OtherProviders
{
	get
	{
		if(_otherProviders == null)
		{
			var otherProviders = new global::System.Collections.Generic.List<global::Windows.UI.Xaml.Markup.IXamlMetadataProvider>();
			global::Windows.UI.Xaml.Markup.IXamlMetadataProvider provider;
			provider = new global::Esri.ArcGISRuntime.Esri_ArcGISRuntime_Universal_XamlTypeInfo.XamlMetaDataProvider() as global::Windows.UI.Xaml.Markup.IXamlMetadataProvider;
			otherProviders.Add(provider); 
			provider = new global::Esri.ArcGISRuntime.Toolkit.Esri_ArcGISRuntime_Toolkit_XamlTypeInfo.XamlMetaDataProvider() as global::Windows.UI.Xaml.Markup.IXamlMetadataProvider;
			otherProviders.Add(provider); 
			provider = new global::FClassLibrary1.ClassLibrary1_XamlTypeInfo.XamlMetaDataProvider() as global::Windows.UI.Xaml.Markup.IXamlMetadataProvider;
			otherProviders.Add(provider); 
			_otherProviders = otherProviders;
		}
		return _otherProviders;
	}
}

The first version fails because looking up types often ends in „ClassLibrary1“, in which they exist but then fail to properly load.

Renaming changes the order in which UWP generates the type lookup and then everything is fine. Not referencing Toolkit but only ArcGisRuntime UWP effectively removes one of the three providers above (the Toolkit one) and when this happens “ClassLibrary1” loads fine even if it comes first.

Tags (2)
0 Kudos
3 Replies
dotMorten_esri
Esri Notable Contributor

What crash are you seeing?

0 Kudos
AndreasSztybryc
New Contributor

That is not easy to answer. Attaching only a managed debugger fails with an unhandled Win32 exception. Debugging in mixed mode does not help alot too. We suspect this might be a mix of Microsoft's Xaml compiler and the way the Esri Assemblies were created.

With mixed mode you see an unhandled exception in Windows.Ui.Xaml.dll. It fails resolving the Xaml control, where the Map was placed.

There is no clear stack trace entry caused by esri but there might be some hints to it because as I mentioned, not having the toolkit generates a similar code by the Xaml compiler that does not fail.

The stack trace of the exception is

 	KernelBase.dll!RaiseFailFastException()	Unknown
 	combase.dll!RoFailFastWithErrorContextInternal2(HRESULT hrError, unsigned long cStowedExceptions, _STOWED_EXCEPTION_INFORMATION_V2 * * aStowedExceptionPointers) Line 1423	C++
 	Windows.UI.Xaml.dll!XamlBinaryMetadataReader2::LoadProperty(unsigned int index) Line 414	C++
 	Windows.UI.Xaml.dll!XamlBinaryMetadataReader2::GetProperty(const unsigned int index, std::shared_ptr<XamlProperty> & result) Line 609	C++
 	[Inline Frame] Windows.UI.Xaml.dll!XamlBinaryMetadataReader2::GetProperty(const PersistedXamlNode2 &) Line 671	C++
 	Windows.UI.Xaml.dll!XamlBinaryFormatSubReader2::ReadXamlProperty() Line 784	C++
 	[Inline Frame] Windows.UI.Xaml.dll!XamlBinaryFormatSubReader2::ReadSetValueConstantNode() Line 485	C++
 	Windows.UI.Xaml.dll!XamlBinaryFormatSubReader2::TryRead(ObjectWriterNode & currentXamlNode) Line 202	C++
 	Windows.UI.Xaml.dll!XamlBinaryFormatSubReader2::TryReadHRESULT(ObjectWriterNode & currentXamlNode, bool * endOfStream) Line 38	C++
 	Windows.UI.Xaml.dll!CParser::LoadXamlCore(CCoreServices * pCore, const CParserSettings & parserSettings, const Parser::XamlBuffer & buffer, CDependencyObject * * ppDependencyObject, const xstring_ptr_view & strSourceAssemblyName, const std::array<unsigned char,64> &) Line 281	C++
 	[Inline Frame] Windows.UI.Xaml.dll!CParser::LoadXaml(CCoreServices * ppDependencyObject, const CParserSettings &) Line 46	C++
 	Windows.UI.Xaml.dll!CCoreServices::ParseXamlWithExistingFrameworkRoot(const Parser::XamlBuffer & buffer, CDependencyObject * pExistingFrameworkRoot, const xstring_ptr_view & strSourceAssemblyName, const xstring_ptr_view & strXamlResourceUri, CDependencyObject * * ppDependencyObject) Line 4020	C++
 	Windows.UI.Xaml.dll!CApplication::LoadComponent(CCoreServices * pCore, CDependencyObject * pComponent, IPALUri * pUri) Line 507	C++
 	Windows.UI.Xaml.dll!Application_LoadComponent(CCoreServices * pCore, CDependencyObject * pComponent, const xstring_ptr & strUri, ComponentResourceLocation::Enum resourceLocation) Line 411	C++
 	Windows.UI.Xaml.dll!DirectUI::FrameworkApplication::LoadComponent(IInspectable * pComponent, const xstring_ptr & strUri, Windows::UI::Xaml::Controls::Primitives::ComponentResourceLocation resourceLocation) Line 506	C++
 	Windows.UI.Xaml.dll!DirectUI::FrameworkApplicationFactory::LoadComponentWithResourceLocationImpl(IInspectable * pComponent, Windows::Foundation::IUriRuntimeClass * pUri, Windows::UI::Xaml::Controls::Primitives::ComponentResourceLocation resourceLocation) Line 458	C++
>	Windows.UI.Xaml.dll!DirectUI::FrameworkApplicationFactory::LoadComponentWithResourceLocation(IInspectable * pComponent, Windows::Foundation::IUriRuntimeClass * pResourceLocator, Windows::UI::Xaml::Controls::Primitives::ComponentResourceLocation componentResourceLocation) Line 724	C++
 	Windows.UI.Xaml.dll!DirectUI::FrameworkApplicationFactory::LoadComponentWithResourceLocation(IInspectable * pComponent, Windows::Foundation::IUriRuntimeClass * pResourceLocator, Windows::UI::Xaml::Controls::Primitives::ComponentResourceLocation componentResourceLocation) Line 715	C++
 	[Managed to Native Transition]	
 	ClassLibrary1.dll!esriuwp.MyUserControl1.InitializeComponent() Line 35	C#
 	ClassLibrary1.dll!esriuwp.MyUserControl1.MyUserControl1() Line 24	C#
 	esriuwp.exe!esriuwp.esriuwp_XamlTypeInfo.XamlTypeInfoProvider.Activate_0_MyUserControl1() Line 312	C#
 	esriuwp.exe!esriuwp.esriuwp_XamlTypeInfo.XamlUserType.ActivateInstance() Line 1562	C#
 	[Native to Managed Transition]	
 	Windows.UI.Xaml.dll!DirectUI::ActivationAPI::ActivateInstance(const CClassInfo * pType, IInspectable * pOuter, IInspectable * * ppInstance) Line 42	C++
 	[Inline Frame] Windows.UI.Xaml.dll!DirectUI::ActivationAPI::ActivateInstance(const CClassInfo *) Line 26	C++
 	Windows.UI.Xaml.dll!DirectUI::XamlParserCallbacks::XamlManagedRuntimeRPInvokes_CreateInstance(XamlTypeToken tokType, XamlQualifiedObject * pqoInstance) Line 101	C++
 	[Inline Frame] Windows.UI.Xaml.dll!CFxCallbacks::XamlManagedRuntimeRPInvokes_CreateInstance(XamlTypeToken) Line 1213	C++
 	Windows.UI.Xaml.dll!XamlManagedRuntime::CreateInstance(const XamlTypeToken & inXamlType, std::shared_ptr<XamlQualifiedObject> & returnQo) Line 40	C++
 	[Inline Frame] Windows.UI.Xaml.dll!XamlType::CreateInstance(std::shared_ptr<XamlQualifiedObject> &) Line 39	C++
 	[Inline Frame] Windows.UI.Xaml.dll!ObjectWriterRuntime::CreateTypeImpl(const XamlLineInfo &) Line 76	C++
 	[Inline Frame] Windows.UI.Xaml.dll!ObjectWriterCommonRuntime::CreateType(const XamlLineInfo & lineInfo, const std::shared_ptr<XamlType> &) Line 116	C++
 	Windows.UI.Xaml.dll!BinaryFormatObjectWriter::CreateInstanceFromType(const ObjectWriterNode & node) Line 418	C++
 	Windows.UI.Xaml.dll!BinaryFormatObjectWriter::WriteNode(const ObjectWriterNode & inNode) Line 132	C++
 	Windows.UI.Xaml.dll!CParser::LoadXamlCore(CCoreServices * pCore, const CParserSettings & parserSettings, const Parser::XamlBuffer & buffer, CDependencyObject * * ppDependencyObject, const xstring_ptr_view & strSourceAssemblyName, const std::array<unsigned char,64> &) Line 284	C++
 	[Inline Frame] Windows.UI.Xaml.dll!CParser::LoadXaml(CCoreServices * ppDependencyObject, const CParserSettings &) Line 46	C++
 	Windows.UI.Xaml.dll!CCoreServices::ParseXamlWithExistingFrameworkRoot(const Parser::XamlBuffer & buffer, CDependencyObject * pExistingFrameworkRoot, const xstring_ptr_view & strSourceAssemblyName, const xstring_ptr_view & strXamlResourceUri, CDependencyObject * * ppDependencyObject) Line 4020	C++
 	Windows.UI.Xaml.dll!CApplication::LoadComponent(CCoreServices * pCore, CDependencyObject * pComponent, IPALUri * pUri) Line 507	C++
 	Windows.UI.Xaml.dll!Application_LoadComponent(CCoreServices * pCore, CDependencyObject * pComponent, const xstring_ptr & strUri, ComponentResourceLocation::Enum resourceLocation) Line 411	C++
 	Windows.UI.Xaml.dll!DirectUI::FrameworkApplication::LoadComponent(IInspectable * pComponent, const xstring_ptr & strUri, Windows::UI::Xaml::Controls::Primitives::ComponentResourceLocation resourceLocation) Line 506	C++
 	Windows.UI.Xaml.dll!DirectUI::FrameworkApplicationFactory::LoadComponentWithResourceLocationImpl(IInspectable * pComponent, Windows::Foundation::IUriRuntimeClass * pUri, Windows::UI::Xaml::Controls::Primitives::ComponentResourceLocation resourceLocation) Line 458	C++
 	Windows.UI.Xaml.dll!DirectUI::FrameworkApplicationFactory::LoadComponentWithResourceLocation(IInspectable * pComponent, Windows::Foundation::IUriRuntimeClass * pResourceLocator, Windows::UI::Xaml::Controls::Primitives::ComponentResourceLocation componentResourceLocation) Line 724	C++
0 Kudos
AndreasSztybryc
New Contributor

Ok,

I can contribute more details to the problem but it gets weird.

The sample above works perfectly when I change the user control to instantiate the MapView the following way

    <Grid>
        <controls:MapView />
    </Grid>

But when I add the IsAttributionTextVisible to the declaration, we get the error that caused this thread to be created. It does not matter whether it is true or false, it just fails with:

    <Grid>
        <controls:MapView IsAttributionTextVisible="true" />
    </Grid>

I hope this helps.

0 Kudos