diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj index 8627c32bddd..8dfa1c1a6ae 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj +++ b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj @@ -85,6 +85,9 @@ Shared\MS\Internal\ResourceIDHelper.cs + + Shared\MS\Internal\ReflectionUtils.cs + Shared\MS\Internal\SecurityHelper.cs diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontCache/FontSource.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontCache/FontSource.cs index 795e3baa52e..4e19fc8aa08 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontCache/FontSource.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontCache/FontSource.cs @@ -355,8 +355,8 @@ private Stream GetCompositeFontResourceStream() { string fontFilename = _fontUri.OriginalString.Substring(_fontUri.OriginalString.LastIndexOf('/') + 1).ToLowerInvariant(); - var fontResourceAssembly = Assembly.GetExecutingAssembly(); - ResourceManager rm = new ResourceManager($"{fontResourceAssembly.GetName().Name}.g", fontResourceAssembly); + Assembly fontResourceAssembly = Assembly.GetExecutingAssembly(); + ResourceManager rm = new($"{ReflectionUtils.GetAssemblyPartialName(fontResourceAssembly)}.g", fontResourceAssembly); return rm?.GetStream($"fonts/{fontFilename}"); } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Resources/ResourceManagerWrapper.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Resources/ResourceManagerWrapper.cs index af85e23588f..834ddd5ead3 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Resources/ResourceManagerWrapper.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Resources/ResourceManagerWrapper.cs @@ -232,11 +232,10 @@ private ResourceSet ResourceSet { if (_resourceSet == null) { - string manifestResourceName; + //"$(AssemblyShortname).unlocalizable.g" + string manifestResourceName = $"{ReflectionUtils.GetAssemblyPartialName(_assembly)}{UnLocalizableResourceNameSuffix}"; + ResourceManager manager = new(manifestResourceName, _assembly); - manifestResourceName = SafeSecurityHelper.GetAssemblyPartialName(_assembly) + UnLocalizableResourceNameSuffix; - - ResourceManager manager = new ResourceManager(manifestResourceName, this._assembly); _resourceSet = manager.GetResourceSet(CultureInfo.InvariantCulture, true, false); } @@ -254,11 +253,9 @@ private ResourceManager ResourceManager { if (_resourceManager == null) { - string baseResourceName; // Our build system always generate a resource base name "$(AssemblyShortname).g" - - baseResourceName = SafeSecurityHelper.GetAssemblyPartialName(_assembly) + LocalizableResourceNameSuffix; - - _resourceManager = new ResourceManager(baseResourceName, this._assembly); + // Our build system always generate a resource base name "$(AssemblyShortname).g" + string baseResourceName = $"{ReflectionUtils.GetAssemblyPartialName(_assembly)}{LocalizableResourceNameSuffix}"; + _resourceManager = new ResourceManager(baseResourceName, _assembly); } return _resourceManager; diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/InterOp/HwndSourceParameters.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/InterOp/HwndSourceParameters.cs index fb2aa4183e6..d944f4d3c73 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/InterOp/HwndSourceParameters.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/InterOp/HwndSourceParameters.cs @@ -1,9 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. -using MS.Win32; using System.Windows.Input; +using System.Reflection; +using MS.Internal; +using MS.Win32; namespace System.Windows.Interop { @@ -418,7 +419,7 @@ internal static bool PlatformSupportsTransparentChildWindows /// Not intended to be tested outside test code internal static void SetPlatformSupportsTransparentChildWindowsForTestingOnly(bool value) { - if (string.Equals(System.Reflection.Assembly.GetEntryAssembly().GetName().Name, "drthwndsource", StringComparison.CurrentCultureIgnoreCase)) + if (ReflectionUtils.GetAssemblyPartialName(Assembly.GetEntryAssembly()).Equals("drthwndsource", StringComparison.CurrentCultureIgnoreCase)) { _platformSupportsTransparentChildWindows = value; } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Navigation/BaseUriHelper.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Navigation/BaseUriHelper.cs index 24647b3e6b3..a2fc6535482 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Navigation/BaseUriHelper.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Navigation/BaseUriHelper.cs @@ -327,7 +327,7 @@ static internal bool IsComponentEntryAssembly(string component) if (assembly != null) { - return (string.Equals(SafeSecurityHelper.GetAssemblyPartialName(assembly), assemblyName, StringComparison.OrdinalIgnoreCase)); + return ReflectionUtils.GetAssemblyPartialName(assembly).Equals(assemblyName, StringComparison.OrdinalIgnoreCase); } else { diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/DocumentsTrace.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/DocumentsTrace.cs index 1b977241a23..6e540a56085 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/DocumentsTrace.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/DocumentsTrace.cs @@ -117,8 +117,8 @@ static DocumentsTrace() public DocumentsTrace(string switchName) { #if DEBUG - string name = SafeSecurityHelper.GetAssemblyPartialName( Assembly.GetCallingAssembly() ); - _switch = new BooleanSwitch(switchName, $"[{name}]"); + ReadOnlySpan shortAssemblyName = ReflectionUtils.GetAssemblyPartialName(Assembly.GetCallingAssembly()); + _switch = new BooleanSwitch(switchName, $"[{shortAssemblyName}]"); #endif } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Baml2006/Baml2006Reader.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Baml2006/Baml2006Reader.cs index e2486208748..f44ff2cf32e 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Baml2006/Baml2006Reader.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Baml2006/Baml2006Reader.cs @@ -12,6 +12,7 @@ using System.Globalization; using XamlReaderHelper = System.Windows.Markup.XamlReaderHelper; using System.Runtime.CompilerServices; +using MS.Internal; namespace System.Windows.Baml2006 { @@ -2105,11 +2106,9 @@ private string Logic_GetFullXmlns(string uriInput) // Providing the assembly short name may lead to ambiguity between two versions of the same assembly, but we need to // keep it this way since it is exposed publicly via the Namespace property, Baml2006ReaderInternal provides the full Assembly name. - // We need to avoid Assembly.GetName() so we run in PartialTrust without asserting. internal virtual ReadOnlySpan GetAssemblyNameForNamespace(Assembly assembly) { - string assemblyLongName = assembly.FullName; - return assemblyLongName.AsSpan(0, assemblyLongName.IndexOf(',')); + return ReflectionUtils.GetAssemblyPartialName(assembly); } // (prefix, namespaceUri) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Baml2006/Baml2006ReaderInternal.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Baml2006/Baml2006ReaderInternal.cs index 3fcb932335a..b5b27fd8a01 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Baml2006/Baml2006ReaderInternal.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Baml2006/Baml2006ReaderInternal.cs @@ -34,9 +34,9 @@ internal Baml2006ReaderInternal( #endregion // Return the full assembly name, this includes the assembly version - internal override ReadOnlySpan GetAssemblyNameForNamespace(Assembly asm) + internal override ReadOnlySpan GetAssemblyNameForNamespace(Assembly assembly) { - return asm.FullName; + return assembly.FullName; } // When processing ResourceDictionary.Source we may find a Uri that references the diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Primitives/MarkupWriter.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Primitives/MarkupWriter.cs index 7d405f33707..a9fbbee4e27 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Primitives/MarkupWriter.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Primitives/MarkupWriter.cs @@ -1,17 +1,17 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. // // Contents: XAML writer // +using System.Xml.Serialization; using System.ComponentModel; -using System.Reflection; using System.Collections; +using System.Reflection; +using MS.Internal; using System.Text; using System.Xml; -using System.Xml.Serialization; namespace System.Windows.Markup.Primitives { @@ -1610,14 +1610,14 @@ public static string GetNamespaceUriFor(Type type) { if (type.Namespace == null) { - result = $"{clrUriPrefix};assembly={type.Assembly.GetName().Name}"; + result = $"{clrUriPrefix};assembly={ReflectionUtils.GetAssemblyPartialName(type.Assembly)}"; } else { Dictionary namespaceToUri = GetMappingsFor(type.Assembly); if (!namespaceToUri.TryGetValue(type.Namespace, out result)) { - result = $"{clrUriPrefix}{type.Namespace};assembly={type.Assembly.GetName().Name}"; + result = $"{clrUriPrefix}{type.Namespace};assembly={ReflectionUtils.GetAssemblyPartialName(type.Assembly)}"; } } } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/XamlTypeMapper.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/XamlTypeMapper.cs index ad62adecc06..48988657ccf 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/XamlTypeMapper.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/XamlTypeMapper.cs @@ -2481,7 +2481,7 @@ private static bool IsFriendAssembly(Assembly assembly) private static bool IsInternalAllowedOnType(Type type) { - bool isInternalAllowed = ReflectionHelper.LocalAssemblyName == type.Assembly.GetName().Name || + bool isInternalAllowed = ReflectionHelper.LocalAssemblyName == ReflectionUtils.GetAssemblyPartialName(type.Assembly) || IsFriendAssembly(type.Assembly); _hasInternals = _hasInternals || isInternalAllowed; return isInternalAllowed; diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/SystemResources.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/SystemResources.cs index 62bd88447cb..2250e03c903 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/SystemResources.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/SystemResources.cs @@ -571,7 +571,7 @@ internal ResourceDictionaries(Assembly assembly) } else { - _assemblyName = SafeSecurityHelper.GetAssemblyPartialName(assembly); + _assemblyName = ReflectionUtils.GetAssemblyPartialName(assembly).ToString(); } } @@ -786,7 +786,7 @@ private void LoadExternalAssembly(bool classic, bool generic, out Assembly assem } assemblyName = sb.ToString(); - string fullName = SafeSecurityHelper.GetFullAssemblyNameFromPartialName(_assembly, assemblyName); + string fullName = ReflectionUtils.GetFullAssemblyNameFromPartialName(_assembly, assemblyName); assembly = null; try diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/ReflectionUtils.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/ReflectionUtils.cs new file mode 100644 index 00000000000..ef7fa223ce6 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/ReflectionUtils.cs @@ -0,0 +1,84 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable + +using System.Runtime.CompilerServices; +using System.Reflection.Metadata; +using System.Reflection; +using System; + +namespace MS.Internal +{ + /// + /// Provides utilities for working with reflection efficiently. + /// + internal static class ReflectionUtils + { +#if !NETFX + /// + /// Retrieves the full assembly name by combining the passed in + /// with everything else from . + /// + internal static string GetFullAssemblyNameFromPartialName(Assembly assembly, string partialName) + { + ArgumentNullException.ThrowIfNull(assembly, nameof(assembly)); + string? fullName = assembly.FullName; + ArgumentNullException.ThrowIfNull(fullName, nameof(Assembly.FullName)); + + AssemblyName name = new(fullName) { Name = partialName }; + return name.FullName; + } +#endif + + /// + /// Given an , returns the partial/simple name of the assembly. + /// +#if !NETFX + internal static ReadOnlySpan GetAssemblyPartialName(Assembly assembly) +#else + internal static string GetAssemblyPartialName(Assembly assembly) +#endif + { +#if !NETFX + ArgumentNullException.ThrowIfNull(assembly, nameof(assembly)); + // We know that the input is trusted (it will be properly escaped, with ", " between tokens etc.) + // So we can allow ourselves to do a little trick, where we just find the first separator + // You cannot load an assembly (or define) where name is empty, it needs to be at least 1 character + // But we will keep this for consistency of the previous function, maybe I've missed a class + ReadOnlySpan fullName = assembly.FullName; + if (fullName.IsEmpty) + return ReadOnlySpan.Empty; + + ReadOnlySpan nameSlice = fullName; + // Skip any escaped commas in the name if present + int escapedComma = fullName.LastIndexOf("\\,", StringComparison.Ordinal); + if (escapedComma != -1) + nameSlice = nameSlice.Slice(escapedComma + 2); + + // Find the real ending of the name section + int commaIndex = nameSlice.IndexOf(','); + if (commaIndex != -1) + fullName = fullName.Slice(0, fullName.Length - nameSlice.Length + commaIndex); + + // Check if we need to unescape, this is very rare case so we can just do it the dirty way + if (escapedComma != -1 || fullName.Contains('\\')) + UnescapeDirty(ref fullName); + + // Since having "," or "=" in the assembly name is very rare, we don't want to inline + // and we will fallback to the runtime implementation to handle such case for us + [MethodImpl(MethodImplOptions.NoInlining)] + static void UnescapeDirty(ref ReadOnlySpan dirtyName) + { + dirtyName = !AssemblyNameInfo.TryParse(dirtyName, out AssemblyNameInfo? result) ? ReadOnlySpan.Empty : result.Name; + } + + return fullName; +#else + AssemblyName name = new(assembly.FullName); + return name.Name ?? string.Empty; +#endif + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/SafeSecurityHelper.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/SafeSecurityHelper.cs index d2e70152c82..dc2e66b87ac 100644 --- a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/SafeSecurityHelper.cs +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/SafeSecurityHelper.cs @@ -58,39 +58,7 @@ internal static void TransformLocalRectToScreen(HandleRef hwnd, ref NativeMethod } #endif -#if PRESENTATION_CORE || PRESENTATIONFRAMEWORK ||REACHFRAMEWORK || DEBUG - -#if !WINDOWS_BASE && !SYSTEM_XAML - /// - /// Given an assembly, returns the partial name of the assembly. - /// - internal static string GetAssemblyPartialName(Assembly assembly) - { - AssemblyName name = new AssemblyName(assembly.FullName); - string partialName = name.Name; - return partialName ?? string.Empty; - } -#endif - -#endif - #if PRESENTATIONFRAMEWORK - - /// - /// Get the full assembly name by combining the partial name passed in - /// with everything else from proto assembly. - /// - internal static string GetFullAssemblyNameFromPartialName( - Assembly protoAssembly, - string partialName) - { - AssemblyName name = new AssemblyName(protoAssembly.FullName) - { - Name = partialName - }; - return name.FullName; - } - internal static Point ClientToScreen(UIElement relativeTo, Point point) { GeneralTransform transform; diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/ReflectionHelper.cs b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/ReflectionHelper.cs index 26e3d2bbdcc..a870be17172 100644 --- a/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/ReflectionHelper.cs +++ b/src/Microsoft.DotNet.Wpf/src/Shared/System/Windows/Markup/ReflectionHelper.cs @@ -504,7 +504,7 @@ internal static bool IsFriendAssembly(Assembly sourceAssembly) #if PBTCOMPILER internal static bool IsInternalAllowedOnType(Type type) { - return ((LocalAssemblyName == type.Assembly.GetName().Name) || IsFriendAssembly(type.Assembly)); + return LocalAssemblyName == ReflectionUtils.GetAssemblyPartialName(type.Assembly) || IsFriendAssembly(type.Assembly); } #endif diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System.Xaml.csproj b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System.Xaml.csproj index 3c58459914b..7bbbb42c222 100644 --- a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System.Xaml.csproj +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System.Xaml.csproj @@ -24,6 +24,9 @@ Common\WPF\MS\Internal\Xaml\Parser\SpecialBracketCharacters.cs + + Common\WPF\MS\Internal\ReflectionUtils.cs + Common\WPF\MS\Internal\SafeSecurityHelper.cs diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XmlNsInfo.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XmlNsInfo.cs index be558a9ee72..db1df2be05b 100644 --- a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XmlNsInfo.cs +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XmlNsInfo.cs @@ -12,6 +12,8 @@ using System.Windows.Markup; using System.Xaml.Schema; +using MS.Internal; + namespace System.Xaml.MS.Impl { class XmlNsInfo @@ -223,8 +225,7 @@ ConcurrentDictionary> LoadClrToXmlNs() xmlNamespaceList.Add(nsDef.XmlNamespace); } - string assemblyName = _fullyQualifyAssemblyName ? - assembly.FullName : XamlSchemaContext.GetAssemblyShortName(assembly); + string assemblyName = _fullyQualifyAssemblyName ? assembly.FullName : ReflectionUtils.GetAssemblyPartialName(assembly).ToString(); foreach (KeyValuePair> clrToXmlNs in result) { // Sort namespaces in preference order diff --git a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlSchemaContext.cs b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlSchemaContext.cs index 341dbbd63f0..cd3e66af26c 100644 --- a/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlSchemaContext.cs +++ b/src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlSchemaContext.cs @@ -8,6 +8,7 @@ using System.Collections.ObjectModel; using System.Reflection; using System.Text; +using MS.Internal; using System.Threading; using System.Xaml.MS.Impl; using System.Xaml.Schema; @@ -786,7 +787,6 @@ internal bool AreInternalsVisibleTo(Assembly fromAssembly, Assembly toAssembly) return false; } - // Not using Assembly.GetName() because it doesn't work in partial-trust AssemblyName toAssemblyName = new AssemblyName(toAssembly.FullName); foreach (AssemblyName friend in friends) { @@ -1042,8 +1042,7 @@ private ReadOnlyCollection GetXmlNsMappings(Assembly assembly, string cl if (!assemblyMappings.TryGetValue(clrNs, out result)) { - string assemblyName = FullyQualifyAssemblyNamesInClrNamespaces ? - assembly.FullName : GetAssemblyShortName(assembly); + string assemblyName = FullyQualifyAssemblyNamesInClrNamespaces ? assembly.FullName : ReflectionUtils.GetAssemblyPartialName(assembly).ToString(); string xmlns = ClrNamespaceUriParser.GetUri(clrNs, assemblyName); List list = new List(); list.Add(xmlns); @@ -1202,14 +1201,6 @@ bool UpdateNamespaceByUriList(XmlNsInfo nsInfo) #region Helper Methods - // Given an assembly, return the assembly short name. We need to avoid Assembly.GetName() so we run in PartialTrust without asserting. - internal static string GetAssemblyShortName(Assembly assembly) - { - string assemblyLongName = assembly.FullName; - string assemblyShortName = assemblyLongName.Substring(0, assemblyLongName.IndexOf(',')); - return assemblyShortName; - } - internal static ConcurrentDictionary CreateDictionary() { return new ConcurrentDictionary(ConcurrencyLevel, DictionaryCapacity); diff --git a/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/SplashScreen.cs b/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/SplashScreen.cs index 48f0eb8fdde..cd5f3dc095f 100644 --- a/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/SplashScreen.cs +++ b/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/SplashScreen.cs @@ -54,8 +54,7 @@ public SplashScreen(Assembly resourceAssembly, string resourceName) _resourceName = resourceName.ToLowerInvariant(); _hInstance = (HINSTANCE)Marshal.GetHINSTANCE(resourceAssembly.ManifestModule); - AssemblyName name = new(resourceAssembly.FullName); - _resourceManager = new ResourceManager($"{name.Name}.g", resourceAssembly); + _resourceManager = new ResourceManager($"{ReflectionUtils.GetAssemblyPartialName(resourceAssembly)}.g", resourceAssembly); } public void Show(bool autoClose) diff --git a/src/Microsoft.DotNet.Wpf/src/WindowsBase/WindowsBase.csproj b/src/Microsoft.DotNet.Wpf/src/WindowsBase/WindowsBase.csproj index 9910284e9b2..ab69121ca5b 100644 --- a/src/Microsoft.DotNet.Wpf/src/WindowsBase/WindowsBase.csproj +++ b/src/Microsoft.DotNet.Wpf/src/WindowsBase/WindowsBase.csproj @@ -34,6 +34,7 @@ +