Revit 2017 Add-In using Macro API

Revit 2017 Add-In using Macro API

Anonymous
Not applicable
1,761 Views
4 Replies
Message 1 of 5

Revit 2017 Add-In using Macro API

Anonymous
Not applicable

Hi All

 

I want to execute an existing macro from my custom add-in, but having issues with the macro assemblies to resolve the MacroManager classes and related objects.

 

I have deployed and altered the macro to use my own placeholder file instead, and implemented the macro as per Jeremy Tammik's post, described here Installing a Macro and Closing the Active Document. Thanks Jeremy!

 

As per the post, it seems like one have to add additional assemblies for RevitAPIMacros and RevitAPIUIMacros. I have done so but still unable to compile successfully?

 

Add-In Assemblies used...

RevitAPI
RevitAPIUI
RevitAPIMaros
RevitAPIUIMacros

 

Add-In Namespaces used...

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

 

 

Add-In Code Segment...

 

 

bool bModuleFound = false;
bool bMacroFound = false;
Autodesk.Revit.DB.Macros.MacroManager macroMgr = null;

try
{
	macroMgr = MacroManager.GetMacroManager(uiapp.Application);

	foreach (Autodesk.Revit.DB.Macros.MacroModule module in macroMgr)
	{
		Misc.WriteLog(" Search for module UiClose...");
		
                if (module.Name.Equals("UiClose"))
		{
			bModuleFound = true;
			Misc.WriteLog(" Module UiClose found");

			foreach (Autodesk.Revit.DB.Macros.Macro macro in module)
			{
				if (macro.Name.Equals("CloseActiveDocDemo"))
				{
					bMacroFound = true;
					Misc.WriteLog(" Macro CloseActiveDocDemo found");
					macro.Execute();
					Misc.WriteLog(" Macro CloseActiveDocDemo executed");
					break;
				}
			}
			break;
		}
	}
}
...
...

 

 

Any help appreciated.

 

Regards,

Zach.

0 Likes
1,762 Views
4 Replies
Replies (4)
Message 2 of 5

Troy_Gates
Advocate
Advocate

I haven't tried the process of launching a macro from an addin. But I have accomplished the same thing (loading placeholder model, then closing other model) using this method http://thebuildingcoder.typepad.com/blog/2010/10/closing-the-active-document-and-why-not-to.html

 

Steps:

 

1) Open placeholder model document

2) Close the original model document

3) Activate the new thread to send the Ctrl-F4 to the placeholder model (assuming no other models open)

 

 

 

 

0 Likes
Message 3 of 5

Anonymous
Not applicable

Hi Troy

 

Thx for the response.

 

Do you execute your macro manually via the Revit UI then, by accessing the macro manager?

 

PS. Noticed one can only close the last active document via the Revit UI, either using the Close menu option or by a custom created function like

a macro or external command.

 

PS2. The last active document cannot by closed via API, thus swopping it out with a placeholder one and making it the new active document will enable one to close the previous active one.

 

PS3. I have deployed a macro to perform the document swop out, works fine when executed from the Revit UI, but cannot get it to work executed from an add-in.

 

PS4. I then created a custom external command containing the logic to also perform a document swop out, also works fine when executed from the Revit UI, but does not work when executed from my add-in.

 

WiIl create a new post for that as it does not involve a macro anymore.

 

Regards,

Zach

0 Likes
Message 4 of 5

Troy_Gates
Advocate
Advocate

I am using it via an addin and not in a macro.

 

1) External Command that loads form that batch open/closes documents. Once the form has completed running the batch process (Steps 2 and 3 below), it starts the ThreadPool.QueueUserWorkItem and calls the method ClosePlaceHolder.

 

    public class BatchProcess : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elementSet)
        {
            try
            {
                BatchForm batchForm = new BatchForm(commandData.Application);
                if (batchForm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ClosePlaceholder));
                }
                
                return Result.Succeeded;
            }
            catch(Exception e)
            {
                TaskDialog.Show("Error", e.Message);
                return Result.Failed;
            }
        }

        private void ClosePlaceholder(object state)
        {
            try
            {
                SendKeys.SendWait("^{F4}");
            }
            catch
            {

            }
        }

    }

 

2) Some code from my batch process that opens placeholder model

 

uiapp.OpenAndActivateDocument(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\Placeholder.rvt");
Document placeholderDoc = uiapp.ActiveUIDocument.Document;

3) During the batch process, I open and close models using code like this. Once the batch is done I only have the Placeholder.rvt model open.

 

Document doc = uiapp.Application.OpenDocumentFile(modelPathOpen, openOptions);

doc.Close(false); // I use false to save because I already saved the model using doc.SaveAs() before closing

 

 

0 Likes
Message 5 of 5

Anonymous
Not applicable

Hi Troy

 

I did something similar, created 2 external commands.

 

The one just sends the F4 key stroke like yours, while the other compares the current active document with that of my placeholder file - if a match is not found the current active document is swopped out with the placeholder file and the previous active document closed.

 

Both external commands working fine using the Revit UI, but not when called from my addin.

 

I use the approach below to attempt to call the external command from my addin...

 

Below is the manifest of my custom external command addin:

 

<?xml version="1.0" encoding="utf-8"?>
<RevitAddIns>
	<AddIn Type="Command">
		<Name>Document Swop</Name> 
		<Description>Swop the active document</Description>
		<Text>Document Swop</Text>
    		<Assembly>C:\My Addins\DocumentSwop.dll</Assembly> 
    		<AddInId>21A8C920-ED49-434A-AACD-176784316B93</AddInId>
    		<FullClassName>AddIns.DocumentSwop</FullClassName>
		<VendorId>Vendor Name</VendorId>    
		<VendorDescription>Vendor Desc</VendorDescription>
  	</AddIn> 
</RevitAddIns>

 

The GUID represents the external command's manifest id, as seen above

 

private static string comIdCommandDocumentSwop = "21A8C920-ED49-434A-AACD-176784316B93";     

 

I then try to execute the external command by looking up its command id and execute it using the PostCommand method.

 

Having no luck as the command id returned is null, thus the command not executed.

 

try
{
	addinId = RevitCommandId.LookupCommandId(comIdCommandDocumentSwop);
}
catch (Exception ex)
{
	Misc.WriteLog(ex.Message);
}

if (addinId != null)
{
	try
	{
		uiapp.PostCommand(addinId);
	}
	catch (Exception ex)
	{
		Misc.WriteLog(ex.Message);
	}
}

 

Not sure if this is the correct approach, any ideas?

 

Regards,

Zach.

 

0 Likes