Eto Revit Plug-in conflicts with Rhino.Inside APICodePack version

Hi!

We built a ETO plug-in in Revit that uses:
Eto.Platform.Wpf v2.6.0
Extended.Wpf.Toolkit v3.6.0
Windows7APICodePack-Core v1.1.0
Windows&APICodePath-Shell v1.1.0

Backgroun:

Last year, we noticed a conflict between our Eto’s spinner with Rhino.Inside. By creating a spinner (but not other drawables), it prevents Rhino.Inside to innitiate it’s UI completely. We figured out the culprite being the spinner object and eliminated it from our plug-in and that seemed to appease the conflict between our standalown ETO with Rhino.Inside’s embedded ETO … until now…

Current Problem

Recently we had user report loading our plug-in causes one specific command, BlockEdit, to fail in Rhino.Inside. The failure is manifested as the “BlockEdit” dialog not showing up; Rhino freezes for half a second and continues as if the command was canceled.

Our user reported getting a

dll conflict: Microsoft.Windows.APICodePack 1.1.4.0 vs 1.1.0.0

when opening Rhino.Inside.

Curiously, other dialog pop-ups in Rhino.Inside, such as BlockManager, are NOT affected by this.


(The blue box is our plug-in. It is loaded here.)

image (31)
(This Screenshot was created after unloading our plug-in)

These two dialogs are created differently somehow — BlockManager dialog has a Rhino Logo on the upper left corner while BlockEdit dialog has a Revit logo on the upper left corner.

We have confirmed this on our end, and this happens in All versions of Revit from 2019 to 2023, before we run any commands in our plug-in to actually display Eto UI.

However, in our tests we have not been able to elicit this error message in Rhino.Inside. Our Rhino.Inside simply cancels the command without raising an error. This is true when running in all versions of Revit and in-and-out-of Debug mode.

Curiously, we managed to produce an equivalent error in our plug-in during one of our rebuild attempts. This time, our plug-in FAILED to load into revit and Rhino.Inside’s BlockEdit completed SUCCESSFULLY with the correct UI showing up. Here is the detailed error message:

System.InvalidOperationException
HResult=0x80131509
Message=Could not detect platform. Are you missing a platform assembly?
Source=Eto
StackTrace:
at Eto.Platform.get_Detect()
at Eto.Forms.Application…ctor()
at CSRevitPlugin.SolemmaApplication.OnStartup(UIControlledApplication application) in C:\Users.…Application.cs:line 41
at Autodesk.Revit.UI.RevitManagedAppStartupAgency.RevitManagedAppStartup(UIControlledApplication pControlledApplication, AString* assemblyName, AString* className, AString* exceptionName, AString* exceptionMessage)

Inner Exception 1:
InvalidOperationException: Error creating instance of platform type ‘Eto.Wpf.Platform, Eto.Wpf’

Inner Exception 2:
TargetInvocationException: Exception has been thrown by the target of an invocation.

Inner Exception 3:
FileNotFoundException: Could not load file or assembly 'Microsoft.WindowsAPICodePack, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ or one of its dependencies. The system cannot find the file specified.

Although we are getting the error report from a different side, it is consistantly related to dll conflict: Microsoft.Windows.APICodePack 1.1.4.0 vs 1.1.0.0 where our Eto is expecting 1.1.0.0 while Rhino.Inside expect 1.1.4.0. The error probably arises on whoever loaded later in the process.

In trying to resolve / isolate the conflict, we tried:

not attaching Eto’s window to Revit’s window

instead of:
dialog.ShowModal(WpfHelpers.ToEtoWindow(commandData.Application.MainWindowHandle));
we simply called ShowModal:
dialog.ShowModal();

not innitiating Eto.Application

we still loaded Eto’s dll but didn’t call any of the functions and did NOT innitiate a new instance of Eto.Application.Application when plug-in is loaded.

Neither of these solved the conflict. Thus our conconclusion is as long as Eto was loaded, it prevents Rhino.Inside from opening up the BlockEdit dialog (and perhaps others).

@curtisw we are wondering if you have any insight on this and how can we resolve the conflict between the dependencies.

bonus!
Error message we got last-time when we had the spinner conflict

[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeInitializationException: The type initializer for ‘Eto.Wpf.Drawing.PenHandler’ threw an exception. —> System.ArgumentException: ‘brush’ property was already registered by ‘Pen’.
at System.Windows.DependencyProperty.RegisterCommon(String name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata, ValidateValueCallback validateValueCallback)
at System.Windows.DependencyProperty.Register(String name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback)
at System.Windows.DependencyProperty.Register(String name, Type propertyType, Type ownerType)
at Eto.Wpf.Drawing.PenHandler…cctor()
— End of inner exception stack trace —
at Eto.Wpf.Drawing.PenHandler.Create(Brush brush, Single thickness)
at Eto.Forms.ThemedControls.ThemedSpinnerHandler.HandlePaint(Object sender, PaintEventArgs e)
at Eto.Forms.Drawable.OnPaint(PaintEventArgs e)
at Eto.Forms.Drawable.Callback.OnPaint(Drawable widget, PaintEventArgs e)
at Eto.Wpf.Forms.Controls.DrawableHandler.EtoMainCanvas.OnRender(DrawingContext dc)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Grid.ArrangeOverride(Size arrangeSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Border.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Grid.ArrangeOverride(Size arrangeSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Border.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Grid.ArrangeOverride(Size arrangeSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Border.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Border.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Border.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Border.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Border.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Border.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Border.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Border.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.DockPanel.ArrangeOverride(Size arrangeSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.DockPanel.ArrangeOverride(Size arrangeSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.DockPanel.ArrangeOverride(Size arrangeSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at MS.Internal.Helper.ArrangeElementWithSingleChild(UIElement element, Size arrangeSize)
at System.Windows.Controls.ContentPresenter.ArrangeOverride(Size arrangeSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Decorator.ArrangeOverride(Size arrangeSize)
at System.Windows.Documents.AdornerDecorator.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Border.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Window.ArrangeOverride(Size arrangeBounds)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.ContextLayoutManager.UpdateLayout()
at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
[END ERROR]

Hey @Demi,

The problem you are running into is that you are using assemblies that are different that those that ship with Rhino. One complication being that Rhino uses a strongly-named version of Eto, whereas the public Eto nuget packages are not strong named.

In order for your plugin to work nicely with Rhino, you’ll need to ensure you use the same versions that Rhino uses. One thing might help is updating to Eto 2.7.1, which is (mostly) the same version that ships with Rhino 7 currently. Additionally you could potentially use Eto.dll and Eto.Wpf.dll from the RhinoCommon and RhinoWindows nuget packages instead.

Hope this helps!

Thank you for the suggestion, we will give it a try.
I wonder how it works legally to distribute Rhino’s Eto as that isn’t technically publicly available. :thinking: