Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Revit crashes when exiting add-in WPF application

9 REPLIES 9
SOLVED
Reply
Message 1 of 10
Anonymous
2233 Views, 9 Replies

Revit crashes when exiting add-in WPF application

I try developing a Revit-addin in Revit 2019 using WPF for the GUI using following minimalized code:

[STAThread]
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
    currentDocument = commandData.Application.ActiveUIDocument.Document;
    RevitInterface.document = currentDocument;

    MessageBox.Show("start application");
    var application = new Application();
    application.Exit += ApplicationExit;
    int returnCode = application.Run(new Window());

 

    MessageBox.Show("application returned with: " + returnCode.ToString());

    return Result.Succeeded;
}

 

private void ApplicationExit(object sender, ExitEventArgs e)
{
    MessageBox.Show("exit event");
}

 

When running this minimal example as an .exe it works fine, but when I try using it from Revit as add-in, it always crashes Revit when exiting. The order of events/outputs is:
- "start application"
- <I close the window by clicking "X" in the top right>
- "exit event"
- <Revit crashes with Popup "Encountered an improper argument">
- "application returned with: 0"

- Afterwards a zombie Revit.exe process remains which needs to be killed before restarting Revit

I already tried the following:
- Removing all add-ins except for my own from  C:\ProgramData\Autodesk\Revit\Addins\2019

- Trying it with Revit 2020
- Trying it from another computer
- Closing the application via application.Shutdown() instead of closing the last window

Do you have some ideas how I still can stay the course using WPF for the add-in GUI? I do prefer it over Windows Forms quite a bit.

9 REPLIES 9
Message 2 of 10
jeremytammik
in reply to: Anonymous

Yes.

   

First of all, I hope that you are aware that you cannot access the Revit API anywhere at all, ever, except within a valid Revit API context:

 

https://thebuildingcoder.typepad.com/blog/2015/12/external-event-and-10-year-forum-anniversary.html#...

  

Such a context is provided by Revit events, so all your code should run within a Revit event handler. One typical event handler is the external command `Execute` method.

  

Now, I see that your sample is not using the Revit API. On the other hand, it is trying to do things in the user interface, such as display a message at an unexpected (for Revit) point in time.

  

Just do not, and all your problems will (hopefully) be solved.

  

To make things easier, you could base your first add-ins on existing working samples.

  

Good luck and have fun!

  



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 3 of 10
Anonymous
in reply to: jeremytammik

Thank you for the effort to again answer a question to a "topic that has probably come up and been answered a few hundred times in the past" ^^.


However even with your link and your suggestions my problem remains. I now tried the following setup:

 

using System;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;


namespace eqdb_revit_addin
{
    [Transaction(TransactionMode.Manual)]
    public class AddinEntryPoint : IExternalCommand
    {


        // This is the entry point in which the add-in starts:
        [STAThread]
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {

            IExternalEventHandler eventHandler = new MyExternalEvent();
            ExternalEvent externalEvent = ExternalEvent.Create(eventHandler);
            externalEvent.Raise();

            return Result.Succeeded;
        }

    } // end class
} // end namespace

 

With MyExternalEvent derived from your link:

using System.Windows;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;

class MyExternalEvent : IExternalEventHandler
{
    public void Execute(UIApplication uiapp)
    {
        UIDocument uidoc = uiapp.ActiveUIDocument;
        if( null == uidoc )
        {
             return; // no document, nothing to do
        }
        Document doc = uidoc.Document;
        using( Transaction tx = new Transaction(doc))
        {
            tx.Start("MyEvent");
            var application = new Application();
            int returnCode = application.Run(new Window());
            tx.Commit();
        }
    }
    public string GetName()
    {
        return "my event";
    }
}

 

Of course the question remains what I am still missing but I'm also asking myself if the Execute() Method in my AddinEntryPoint has not already been just that Revit event handler that you mentioned.

Message 4 of 10
stever66
in reply to: Anonymous

You might try using modal dialog boxes, at least to start with.

 

Use MessageBox.ShowDialog instead of MessageBox.Show.

 

 

Message 5 of 10
Anonymous
in reply to: stever66

Thank you for your suggestion.

In the meantime I checked out some additional templates as suggested by Jeremy Tammik and found out that these appearantly do not create their own WPF Application. It seems like my suspicion was true in the sense that Revit already has its own Application running (I would not be surprised if Revit was also written with WPF). Maybe creating a new Application and shutting it down kills Revit's Application aswell.

 

Opening an empty window without creating a new Application around it did finally work for me! Revit survives closing that one.

 

Now i got a new issue:
If I create new Window by instantiating a custom class of mine which inherits from Window, the add-in crashes immediately without even executing the first line of the constructor. I get an error message like:
"Revit encountered System.IO.FileNotFoundException: The file or assembly "System.Collections,...." or a dependency of it has not been found. The system cannot find the file specified."
Here are my imports:
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;

 

The confusing part for me is that there are absolutely no compile errors and creating the exact same window outside a Revit add-in context works flawlessly. Another similar custom window of mine shows the same behaviour.

Here is my .csproj:

<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">

    <PropertyGroup>
       <OutputType>Library</OutputType>
       <TargetFramework>netcoreapp3.1</TargetFramework>
       <UseWPF>true</UseWPF>
       <DebugType>portable</DebugType>
        <Platforms>x64</Platforms><!-- Only target x64 systems like the Revit APIs do -->
       <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
   </PropertyGroup>

 

    <ItemGroup>
       <Reference Include="RevitAPI">
          <HintPath>C:\Program Files\Autodesk\Revit 2019\RevitAPI.dll</HintPath>
          <Private>False</Private>
       </Reference>

       <Reference Include="RevitAPIUI">
          <HintPath>C:\Program Files\Autodesk\Revit 2019\RevitAPIUI.dll</HintPath>
          <Private>False</Private>
       </Reference>

       <!-- allows for ifc id generation: -->
       <Reference Include="RevitAPIIFC">
          <HintPath>C:\Autodesk\WI\Autodesk Revit 2019\x64\RVT\PF64\Autodesk\Root\RevitAPIIFC.dll</HintPath>
          <Private>False</Private>
       </Reference>
    </ItemGroup>

 

    <!-- packages installed via dotnet add package: -->
    <ItemGroup>
       <PackageReference Include="Dapper" Version="2.0.30" />
       <PackageReference Include="MySqlConnector" Version="0.61.0" />
    </ItemGroup>

</Project>

Message 6 of 10
stever66
in reply to: Anonymous

I managed to get a WPF usercontrol (or window, I'm really not sure which it is) to work inside one of my Revit Add-ins by following this intro:

 

https://spiderinnet.typepad.com/blog/2011/11/wpf-and-revit-addin-popup-wpf-window-from-external-comm...

 

There is also a part 2 and a part 3 which I haven't got to yet.

 

And I haven't managed to get any Revit API code to run from the WPF control yet.  Hopefully, that's next after I read parts 2 and 3, and some more from Jeremy's blogs, and any other info I can find. 

 

Right now the event handlers for my WPF are in the WPF control's code, which doesn't have access to my Revit API stuff.

 

Anyhow, you might try looking through the link.


P.S.  You do have Windows.xaml added as a reference, right?

 

 

Message 7 of 10
Moustafa_K
in reply to: Anonymous

I have managed to run WPF from Revit this way:

see this very minimal example.

see GIT here

WPFWindow.gif

basically you need to be aware of MVVM (Model View - View Model) structure, as this is the layer that communicates between the Interface (WPF Window) and the Revit works running on the back.

 

so this is what the sample does:

  • Create Revit Command Layer
    • Create a WPF Window
      • Create a Communication Layer( ModelView)
        • Register your Commands Action (used for binding Buttons"Controls" to the model View)
        • Register External Events, and Documents
    • Show WPF Window
    • Close Command (Return Result.Succeeded).

Now, as you have a button on a WPF thread that is connected to MVVM Layer,

  1. WPF will run smoothly in terms of Interface, and separated from Revit
  2. since you register External Events to the MV, then signals sent from the Button from the WPF interface to the MV layer, that will triggering the action.

However, there are some limitation to this:

for example, if you are running a very long process... the WPF window will be blocked till revit Finish its running works, hence, running a Progress bar on WPF doesn't work this way. Progress bar must be registered to a window that is running on a separate Thread from Revit.  Thread.Start(...) and ofcourse should be STAThread

 

I hope the above gives you some light on how this works.

 

Moustafa Khalil
Cropped-Sharp-Bim-500x125-Autodesk-1
Message 8 of 10
Anonymous
in reply to: stever66

Hey,
thank you for your tutorial suggestions. I will certainly have a look at it.
Currently I am not using xaml generated controls, but I am considering it. That's why I currently don't have a reference to Windows.xaml.

Message 9 of 10
Anonymous
in reply to: Moustafa_K

Thank you for your example very much aswell, Moustafa Khalil! It gives a very nice and compact insight on Revit WPF structure.

Message 10 of 10
Anonymous
in reply to: Anonymous

Now to give this thread an answer:


The basic problem I see through all the examples, lies in creating a new Application to Run() the window like:
var application = new Application();

var window = new MyWindow();
int returnCode = application.Run(window);

 

Instead Revit seems to bring its own application with it so you can just open your windows without creating a new Application like:
var window = new MyWindow();
window.Show();

 

I hope I will be able to troubleshoot my other problems aswell, but these don't contribute to the original question of this thread. I thank everybody who gave me hints and tipps.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report