Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revit crashes on UIView.Close() #64

Open
damirsib opened this issue Nov 21, 2017 · 2 comments
Open

Revit crashes on UIView.Close() #64

damirsib opened this issue Nov 21, 2017 · 2 comments
Assignees

Comments

@damirsib
Copy link

The following code crashes Revit:

try:
    user_active_view = uidoc.ActiveView

    views = [view for view in FilteredElementCollector(doc).WherePasses(ElementClassFilter(ViewPlan)) if view.IsValidObject and not view.IsTemplate and view.ViewType != ViewType.CeilingPlan]

    for view in views:
        uidoc.ActiveView = view

    uidoc.ActiveView = user_active_view

    for ui_view in uidoc.GetOpenUIViews():
        if ui_view.ViewId != uidoc.ActiveView.Id:
            ui_view.Close()
            
except Exception as exception:
    print exception.message

But C# code works fine:

[TransactionAttribute(TransactionMode.Manual)]
[RegenerationAttribute(RegenerationOption.Manual)]
public class CloseViews : IExternalCommand
{
    public Result Execute(
      ExternalCommandData commandData,
      ref string message,
      ElementSet elements)
    {
        UIApplication uiApp = commandData.Application;
        Document doc = uiApp.ActiveUIDocument.Document;
        UIDocument uidoc = uiApp.ActiveUIDocument;

        View user_active_view = uidoc.ActiveView;

        FilteredElementCollector view_plans = new FilteredElementCollector(doc).WherePasses(new ElementClassFilter(typeof(ViewPlan)));
        IEnumerable<View> views = view_plans.Cast<View>().ToList<View>().Where(view => view.IsValidObject && !view.IsTemplate && view.ViewType != ViewType.CeilingPlan);

        foreach (View view in views)
        {
            uidoc.ActiveView = view;
        }

        uidoc.ActiveView = user_active_view;
        foreach (UIView ui_view in uidoc.GetOpenUIViews())
        {
            if (ui_view.ViewId != uidoc.ActiveView.Id)
            {
                ui_view.Close();
            }
        }

        return Result.Succeeded;
    }
}
@eirannejad
Copy link
Contributor

eirannejad commented Feb 3, 2018

I did a whole series of tests troubleshooting this. Under RPS the script either crashes Revit or returns an illegal memory access inside Revit's UIFrameworks module. This part of the script is the cause of error:

for view in views:
        uidoc.ActiveView = view

It's activating a series of views in rapid succession. Revit regenerates all UIView objects wrapping the active View object every time there is a change in the state of open views. I've verified this by comparing object ids of UIView objects vs their associated ViewId.

I concluded that the crash is due to the UI complications of activating views, while an external command has a Modal or Non-Modal window open. The script runs fine in pyRevit and C# addon and this verifies that the error is definitely not an IronPython or CLR error.

The easy way to resolve this and similar GUI errors is to Hide and Unhide the RPS window. This IMHO should be the general practice when making UI changes to Revit in RPS.

Here is the revised script that works:

__window__.Hide()
user_active_view = uidoc.ActiveView

views = [view for view in FilteredElementCollector(doc).WherePasses(ElementClassFilter(ViewPlan))
         if view.IsValidObject and not view.IsTemplate and view.ViewType != ViewType.CeilingPlan]

for view in views:
    uidoc.ActiveView = view

uidoc.ActiveView = user_active_view

for ui_view in uidoc.GetOpenUIViews():
    if ui_view.ViewId != uidoc.ActiveView.Id:
        ui_view.Close()

__window__.Show()

Notes: Tested under Revit 2018.2

@eirannejad eirannejad self-assigned this Feb 3, 2018
@daren-thomas
Copy link
Member

I have just tested both versions and can confirm that

  1. the original version (without __window__.Hide()) crashes on my system too
  2. the proposed workaround by @eirannejad works on my system (doesn't crash)

I think this is ugly, but don't really see another way to do this...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants