Search code examples
autodeskrevit-apirevit

Close ActiveUIDocument using Revit API(2014) from Idling Event Handler


Is there any way to close ActiveUIDocument using Revit API? I have created a separate addin to close the ActiveUIDocument which works from the Revit GUI but when i try to call that addin from Idling event handler, nothing happens. Please help.

Below is the code for my addin:

private void CloseDoc(object obj)
{
     SendKeys.SendWait("^{F4}");
}

public Result Execute(ExternalCommandData commandData, ref string message, Autodesk.Revit.DB.ElementSet elements)
{
     Threadpool.QueueUserWorkItem(new WaitCallback(Close));
     return Result.Succeeded;      
}

Code used to call addin from within Idling event handler :

     RevitCommandId id_built_in = RevitCommandId.LookupPostableCommandId(PostableCommand.SheetIssuesOrRevisions);
     RevitCommandId addinID = RevitCommandId.LookupCommandId("1869A8A1-A239-41CF-9A79-96234D92DEF4");
     app.PostCommand(addinID);

Addinn Manifest file:

<?xml version="1.0"?>
<RevitAddIns>
  <AddIn Type="Command">
    <Assembly>AddinExternalLauncher.dll</Assembly>
    <ClientId>1869A8A1-A239-41CF-9A79-96234D92DEF4</ClientId>
    <FullClassName>AddinExternalLauncher.AddinLauncher</FullClassName>
    <Text>Addin External Launcher</Text>
    <Description></Description>
    <VisibilityMode>AlwaysVisible</VisibilityMode>
    <VendorId>ADSK</VendorId>
    <VendorDescription>Autodesk, www.autodesk.com</VendorDescription>
  </AddIn>
</RevitAddIns>

Last few lines of Journal Output after calling addin:

' 1:< total bytes expanded: 35414988 
' 1:< ;EES;0;0;86;0;0;0;0;0;14; 
' 1:<  0 ModelServerState "Destroyed": Current server = "Not Queried", Model server = "", Model server state = "Not Applicable" 
' 1:<   System (MB) [Available /  Total ]  [Revit Memory Usage (MB)   ] 
' 1:< RAM Statistics:     3385 /     8040       623=InUse      629=Peak  
' 1:< VM  Statistics:  8384617 /  8388607       536=InUse      542=Peak  
 ' 1:< ::9:: Delta VM: Avail -13 -> 8384597 MB, Used +28 -> 564 MB, Peak +21 -> 564 MB; RAM: Avail -26 -> 3360 MB, Used +41 -> 664 MB, Peak +36 -> 665 MB 
 'E 24-Aug-2016 15:02:28.961;   1:< 
 ' [Jrn.File Input Information] COMMON.FILE_INPUT.FILE_TYPE: .rvt 013144064.000000
' 0:< The Idling event callback used 53 seconds 
' 3:< ::10:: Delta VM: Avail -20 -> 8384577 MB, Used +6 -> 570 MB, Peak +6 -> 570 MB; RAM: Avail -2 -> 3358 MB, Used +3 -> 667 MB, Peak +1 -> 667 MB 
'  0.114085      4:<<From Parking Area: ;PERF;MISC;generating greps 
' 0:< ::10:: Delta VM: Avail +5 -> 8384583 MB, Used -13 -> 558 MB; RAM: Avail +2 -> 3361 MB, Used -7 -> 661 MB, Peak +0 -> 668 MB 
'  0.372841   1:<<;PERF;MISC;drawing/ALL_GAPS   0.258756/TurnOff_GAPs 74% 
'C 24-Aug-2016 15:02:29.386;   0:< idle0_doc 
'H 24-Aug-2016 15:02:29.386;   0:< 
Jrn.Directive "AllowPressAndDrag"  _
        , 1
' 0:< <<Begin build CT>>
'
'Edit mode: IDR_COMMON
'Command: ID_BUTTON_SELECT
'Category: 0
'Bar list: 
'   Dialog_Revit_DynamicLabelDBar
'   Dialog_Essentials_FilterSelectionNew
'Presenter list: 
'   PP_DebugTab_Binding_Demo
'Product: Architecture
'
'
'***********************************************************
'***********************************************************
'<<End build CT>> 

Solution

  • Why not directly call your method from the Idling handler?

    private void ApplicationOnIdling(object sender, IdlingEventArgs idlingEventArgs)
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(Close));
    }
    

    And while you're at it, why not use a Task instead of ThreadPool?

    Task.Run(() => SendKeys.SendWait("^{F4}"));
    

    It accomplishes the same thing, and is cleaner than having an extra method with an unused parameter.