IExternalEventHandler crash when Raise()

Hi everyone,

I am trying to use External Event Handler and following the topic from pyRevitMEP’s author. But my Revit always crashes after hitting the button event. Could you please have a look up? Thank you

Link: [[Revit API] Simple Modeless Form (External Event Handler) in pyRevit – Python HVAC]
Source code:

test.xaml

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 Title="Delete things:" Height="150" Width="300" ShowInTaskbar="False" Topmost="True"
 WindowStartupLocation="CenterScreen" ScrollViewer.VerticalScrollBarVisibility="Disabled" HorizontalContentAlignment="Center">
    <StackPanel Margin="20" HorizontalAlignment="Stretch">
        <TextBlock x:Name="simple_text" Text="" Grid.Column="0" HorizontalAlignment="Center" FontWeight="Bold"/>
        <Button Content="Delete selected elements" Height="30" Margin="10,10" Click="delete_click"/>
    </StackPanel>
</Window>

image

script.py

# noinspection PyUnresolvedReferences
from Autodesk.Revit.UI import IExternalEventHandler, ExternalEvent
# noinspection PyUnresolvedReferences
from Autodesk.Revit.DB import Transaction
# noinspection PyUnresolvedReferences
from Autodesk.Revit.Exceptions import InvalidOperationException
from pyrevit import HOST_APP, engine
from pyrevit.forms import WPFWindow

__doc__ = "A simple modeless form sample"
__title__ = "Modeless Form"
__author__ = "Cyril Waechter"

uidoc = __revit__.ActiveUIDocument
app = HOST_APP.app
uiapp = HOST_APP.uiapp
doc = uidoc.Document
activeView = doc.ActiveView


# Simple function we want to run
def delete_elements():
    t = Transaction(doc, "Failing script")
    t.Start()
    for elid in uidoc.Selection.GetElementIds():
        print(elid)
        doc.Delete(elid)
    t.Commit()


# Create a subclass of IExternalEventHandler
class SimpleEventHandler(IExternalEventHandler):
    """
    Simple IExternalEventHandler sample
    """

    # __init__ is used to make function from outside of the class to be executed by the handler. \
    # Instructions could be simply written under Execute method only
    def __init__(self, do_this):
        self.do_this = do_this

    # Execute method run in Revit API environment.
    def Execute(self, uiapp):
        try:
            self.do_this()
        except InvalidOperationException:
            # If you don't catch this exeption Revit may crash.
            print("InvalidOperationException catched")

    def GetName(self):
        return "simple function executed by an IExternalEventHandler in a Form"


# Now we need to make an instance of this handler. Moreover, it shows that the same class could be used to for
# different functions using different handler class instances
simple_event_handler = SimpleEventHandler(delete_elements)
# We now need to create the ExternalEvent
ext_event = ExternalEvent.Create(simple_event_handler)


# A simple WPF form used to call the ExternalEvent
class ModelessForm(WPFWindow):
    """
    Simple modeless form sample
    """

    def __init__(self, xaml_file_name):
        WPFWindow.__init__(self, xaml_file_name)
        self.simple_text.Text = "Hello World"
        self.Show()

    def delete_click(self, sender, e):
        # This Raise() method launch a signal to Revit to tell him you want to do something in the API context
        ext_event.Raise()


# Let's launch our beautiful and useful form !
xaml_file_path = r"test.xaml"
modeless_form = ModelessForm(xaml_file_path)

Thanks a lot!
Tien

just recognize that we need to add

engine:
  persistent: true

to the bundle.yaml file or delete the bundle.yaml file

1 Like

Thanks for this post. I tied this bundle.yaml edit to include persistent: true and it fixed Revit crash . I am curious why this line that was already in my script didnt prevent Revit crash since it seems to do the same thing
__persistentengine__ = True
Anyway for other users, the bundle.yaml edit stopped the Revit crashing but the above line in code did not help.