diff --git a/src/Windows/Avalonia.Win32/Automation/AutomationNode.cs b/src/Windows/Avalonia.Win32/Automation/AutomationNode.cs index 70e415aff1..29ab2cea3a 100644 --- a/src/Windows/Avalonia.Win32/Automation/AutomationNode.cs +++ b/src/Windows/Avalonia.Win32/Automation/AutomationNode.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Runtime.CompilerServices; @@ -16,6 +17,7 @@ using AAP = Avalonia.Automation.Provider; namespace Avalonia.Win32.Automation { [ComVisible(true)] + [RequiresUnreferencedCode("Requires .NET COM interop")] internal partial class AutomationNode : MarshalByRefObject, IRawElementProviderSimple, IRawElementProviderSimple2, diff --git a/src/Windows/Avalonia.Win32/Automation/RootAutomationNode.cs b/src/Windows/Avalonia.Win32/Automation/RootAutomationNode.cs index 1ec0ee9e2e..b732c4169f 100644 --- a/src/Windows/Avalonia.Win32/Automation/RootAutomationNode.cs +++ b/src/Windows/Avalonia.Win32/Automation/RootAutomationNode.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using Avalonia.Automation.Peers; using Avalonia.Automation.Provider; @@ -9,6 +10,7 @@ using Avalonia.Win32.Interop.Automation; namespace Avalonia.Win32.Automation { + [RequiresUnreferencedCode("Requires .NET COM interop")] internal class RootAutomationNode : AutomationNode, IRawElementProviderFragmentRoot { diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj index 00ce309519..e69e0ee219 100644 --- a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj +++ b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj @@ -21,8 +21,8 @@ + - CA1416 - $(NoWarn),CA1416 + $(NoWarn);CA1416 diff --git a/src/Windows/Avalonia.Win32/DataObject.cs b/src/Windows/Avalonia.Win32/DataObject.cs index 27560df35e..b7a567ea97 100644 --- a/src/Windows/Avalonia.Win32/DataObject.cs +++ b/src/Windows/Avalonia.Win32/DataObject.cs @@ -2,6 +2,7 @@ using System.Buffers; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Runtime.InteropServices; @@ -291,13 +292,16 @@ namespace Avalonia.Win32 return WriteBytesToHGlobal(ref hGlobal, SerializeObject(data)); } + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "We still use BinaryFormatter for WinForms dragndrop compatability")] private static byte[] SerializeObject(object data) { using (var ms = new MemoryStream()) { ms.Write(SerializedObjectGUID, 0, SerializedObjectGUID.Length); BinaryFormatter binaryFormatter = new BinaryFormatter(); +#pragma warning disable SYSLIB0011 // Type or member is obsolete binaryFormatter.Serialize(ms, data); +#pragma warning restore SYSLIB0011 // Type or member is obsolete return ms.ToArray(); } } diff --git a/src/Windows/Avalonia.Win32/Interop/Automation/UiaCoreTypesApi.cs b/src/Windows/Avalonia.Win32/Interop/Automation/UiaCoreTypesApi.cs index 4375b2fde1..966f996a91 100644 --- a/src/Windows/Avalonia.Win32/Interop/Automation/UiaCoreTypesApi.cs +++ b/src/Windows/Avalonia.Win32/Interop/Automation/UiaCoreTypesApi.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; namespace Avalonia.Win32.Interop.Automation @@ -21,11 +22,15 @@ namespace Avalonia.Win32.Interop.Automation internal const int UIA_E_NOCLICKABLEPOINT = unchecked((int)0x80040202); internal const int UIA_E_PROXYASSEMBLYNOTLOADED = unchecked((int)0x80040203); + private static bool? s_isNetComInteropAvailable; + internal static bool IsNetComInteropAvailable => s_isNetComInteropAvailable ??= GetIsNetComInteropAvailable(); + internal static int UiaLookupId(AutomationIdType type, ref Guid guid) { return RawUiaLookupId( type, ref guid ); } + [RequiresUnreferencedCode("Requires .NET COM interop")] internal static object UiaGetReservedNotSupportedValue() { object notSupportedValue; @@ -33,6 +38,7 @@ namespace Avalonia.Win32.Interop.Automation return notSupportedValue; } + [RequiresUnreferencedCode("Requires .NET COM interop")] internal static object UiaGetReservedMixedAttributeValue() { object mixedAttributeValue; @@ -49,6 +55,19 @@ namespace Avalonia.Win32.Interop.Automation Marshal.ThrowExceptionForHR(hr, (IntPtr)(-1)); } + + private static bool GetIsNetComInteropAvailable() + { +#if NET6_0_OR_GREATER + if (!System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported) + { + return false; + } +#endif + + var comConfig = AppContext.GetData("System.Runtime.InteropServices.BuiltInComInterop.IsSupported"); + return comConfig == null || bool.Parse(comConfig.ToString()); + } [DllImport("UIAutomationCore.dll", EntryPoint = "UiaLookupId", CharSet = CharSet.Unicode)] private static extern int RawUiaLookupId(AutomationIdType type, ref Guid guid); diff --git a/src/Windows/Avalonia.Win32/NonPumpingSyncContext.cs b/src/Windows/Avalonia.Win32/NonPumpingSyncContext.cs index 5577664cc4..f295dd7394 100644 --- a/src/Windows/Avalonia.Win32/NonPumpingSyncContext.cs +++ b/src/Windows/Avalonia.Win32/NonPumpingSyncContext.cs @@ -20,8 +20,10 @@ namespace Avalonia.Win32 public override void Post(SendOrPostCallback d, object state) => _inner.Post(d, state); public override void Send(SendOrPostCallback d, object state) => _inner.Send(d, state); - + +#if !NET6_0_OR_GREATER [PrePrepareMethod] +#endif public override int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) { return UnmanagedMethods.WaitForMultipleObjectsEx(waitHandles.Length, waitHandles, waitAll, diff --git a/src/Windows/Avalonia.Win32/OleDataObject.cs b/src/Windows/Avalonia.Win32/OleDataObject.cs index 90992d803f..79b55e4f77 100644 --- a/src/Windows/Avalonia.Win32/OleDataObject.cs +++ b/src/Windows/Avalonia.Win32/OleDataObject.cs @@ -1,6 +1,7 @@ using System; using System.Buffers; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Runtime.InteropServices; @@ -49,6 +50,7 @@ namespace Avalonia.Win32 return GetDataFromOleHGLOBAL(dataFormat, DVASPECT.DVASPECT_CONTENT); } + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "We still use BinaryFormatter for WinForms dragndrop compatability")] private unsafe object GetDataFromOleHGLOBAL(string format, DVASPECT aspect) { var formatEtc = new Interop.FORMATETC(); @@ -77,7 +79,9 @@ namespace Avalonia.Win32 { ms.Position = DataObject.SerializedObjectGUID.Length; BinaryFormatter binaryFormatter = new BinaryFormatter(); +#pragma warning disable SYSLIB0011 // Type or member is obsolete return binaryFormatter.Deserialize(ms); +#pragma warning restore SYSLIB0011 // Type or member is obsolete } } return data; diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 08762f7d9f..5537a0b704 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -21,6 +21,8 @@ namespace Avalonia.Win32 { [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Using Win32 naming for consistency.")] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "We do .NET COM interop availability checks")] + [UnconditionalSuppressMessage("Trimming", "IL2050", Justification = "We do .NET COM interop availability checks")] protected virtual unsafe IntPtr AppWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) { const double wheelDelta = 120.0; @@ -83,7 +85,10 @@ namespace Avalonia.Win32 case WindowsMessage.WM_DESTROY: { - UiaCoreProviderApi.UiaReturnRawElementProvider(_hwnd, IntPtr.Zero, IntPtr.Zero, null); + if (UiaCoreTypesApi.IsNetComInteropAvailable) + { + UiaCoreProviderApi.UiaReturnRawElementProvider(_hwnd, IntPtr.Zero, IntPtr.Zero, null); + } // We need to release IMM context and state to avoid leaks. if (Imm32InputMethod.Current.HWND == _hwnd) @@ -707,7 +712,7 @@ namespace Avalonia.Win32 break; case WindowsMessage.WM_GETOBJECT: - if ((long)lParam == UiaRootObjectId) + if ((long)lParam == UiaRootObjectId && UiaCoreTypesApi.IsNetComInteropAvailable) { var peer = ControlAutomationPeer.CreatePeerForElement((Control)_owner); var node = AutomationNode.GetOrCreate(peer);