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 2017 Add-In Executing a Custom External Command

4 REPLIES 4
Reply
Message 1 of 5
Anonymous
3274 Views, 4 Replies

Revit 2017 Add-In Executing a Custom External Command

Hi

 

Having some external command issues, seems like my command executes just fine from the Revit UI, but when executed from my add-in there seems to be no exceptions - but the desired result is not achieved.

 

Thanks to Jeremy Tammik's post Programmatic Custom Add-In External Command Launch  It seems like I am able to execute a custom external command using the UIApplication,.PostCommand by looking up the custom command's revit id using its description (manifest id)

 

Assemblies

 

RevitAPI
RevitAPIUI

 

 

Namespaces

 

using Autodesk.Revit.DB;
using Autodesk.Revit.UI;

 

 

Custom Addin for External Command...

 

[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.ReadOnly)]
public class DocumentSwop : IExternalCommand
{
  public static string filePlaceholderPath = @"\\someserver\C$\somedirectory\PlaceHolder.rvt";

	public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
	{
			Autodesk.Revit.UI.UIApplication uiapp = null;
			Autodesk.Revit.DB.Document doc = null;
			Autodesk.Revit.UI.UIDocument docPlaceHolder = null;
			string filePlaceholder = null;
			string fileRevitActive = null;
			int fileCompare = 0;

			message = "Velocity.Revit.AddIns.DocumentSwop...";

			try
			{
					// Assign UIApplication
					uiapp = commandData.Application;
					message += Environment.NewLine + "  UIApplication object assigned";

					if (uiapp != null)
					{
							message += Environment.NewLine + "  UIApplication not null";

							// Assign curren tactive document
							doc = uiapp.ActiveUIDocument.Document;
							message += Environment.NewLine + "  Current active document object assigned";

							if (doc != null)
							{
									message += Environment.NewLine + "  Document object not null";

									// Continue processing if placeholder file exists
									if (File.Exists(filePlaceholderPath))
									{
											message += Environment.NewLine + "  Placeholder file found in file system for " + filePlaceholderPath;

											// Assign filename of placeholder file
											filePlaceholder = System.IO.Path.GetFileName(filePlaceholderPath);
											message += Environment.NewLine + "  Placeholder File = " + filePlaceholder;

											// Assign filename of current active revit document
											fileRevitActive = doc.Title;
											message += Environment.NewLine + "  Revit Active Document = " + fileRevitActive;

											// Compare files
											fileCompare = String.Compare(filePlaceholder, fileRevitActive);
											message += Environment.NewLine + "  File Compare = " + fileCompare.ToString();

											// Perform document swop out if files dont match
											message += Environment.NewLine + "  Swop Active Document...";
											if (fileCompare != 0)
											{
													docPlaceHolder = uiapp.OpenAndActivateDocument(filePlaceholderPath);
													doc.Close(true);
											}                                
											message += Environment.NewLine + "  Swop Active Document completed";
									}

									message += Environment.NewLine + "Velocity.Revit.AddIns.DocumentSwop completed";
									return Autodesk.Revit.UI.Result.Succeeded;
							}
							else
							{
									message += Environment.NewLine + "  Document object could not be set";
									message += Environment.NewLine + "Velocity.Revit.AddIns.DocumentSwop completed";
									return Autodesk.Revit.UI.Result.Failed;
							}
					}
					else
					{
							message += Environment.NewLine + "  UIApplication object could not be set";
							message += Environment.NewLine + "Velocity.Revit.AddIns.DocumentSwop completed";
							return Autodesk.Revit.UI.Result.Failed;
					}
			}
			catch (Exception ex)
			{
					message += Environment.NewLine + "  Velocity.Revit.AddIns.DocumentSwop exception: " + ex.Message;
					message += Environment.NewLine + "Velocity.Revit.AddIns.DocumentSwop completed";
					return Autodesk.Revit.UI.Result.Failed;
			}
			finally
			{
					filePlaceholder = null;
					fileRevitActive = null;
					fileCompare = 0;
					uiapp = null;
					doc = null;
					docPlaceHolder = null;
			}
	}
}
   

 

 

Custom Addin for External Command Manifest...

 

<?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>

 

 

Custom Addin calling External Command...

 

private static string comIdCommandDocumentSwop = "21A8C920-ED49-434A-AACD-176784316B93";
Autodesk.Revit.UI.RevitCommandId addinId = null;

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

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

 

Seems like the custom external command is executed, but the desired result is not obtained - thus the document swop does not occur.

 

Anyone have some ideas?

 

Regards,

Zach

4 REPLIES 4
Message 2 of 5
Anonymous
in reply to: Anonymous

Have added additional debugging by writing to a log, found that the RevitId or AddInId of my custom external command is null, and thus the cause

of my external command not being executed.

 

 

Message 3 of 5
Anonymous
in reply to: Anonymous

I have looked at the example again on Jermery's post, and listed both the external commands; manifest

 

Jeremy's Example Manifest...

 

  <AddIn Type="Command">
    <Text>PostAddinCommand Dummy Command</Text>
    <Description>Test command for PostAddinCommand.</Description>
    <Assembly>PostAddinCommand.dll</Assembly>
    <FullClassName>PostAddinCommand.CmdDummy</FullClassName>
    <ClientId>64b3d907-37cf-4cab-8bbc-3de9b66a3efa</ClientId>
    <VendorId>TBC_</VendorId>
    <VendorDescription>The Building Coder, http://thebuildingcoder.typepad.com</VendorDescription>
  </AddIn>

 

My External Commands's Manifest...

 

<?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:\VelocityBIM\Revit Addin\Velocity.Revit.AddIns.DocumentSwop.dll</Assembly> 
    		<AddInId>21A8C920-ED49-434A-AACD-176784316B93</AddInId>
	    	<FullClassName>Velocity.Revit.AddIns.DocumentSwop</FullClassName>
		<VendorId>Velocity-IT</VendorId>    
		<VendorDescription>Velocity-IT: www.velocity-it.co.uk</VendorDescription>
  	</AddIn> 
</RevitAddIns>

My external command contains a node for <AddInId> holding the value of the AddInId, while Jeremy's example store this value in the <ClientId> node.

 

Using the UIApplication.PostCommand method to execute the external command from my addin. but the lookup method RevitCommandId.LookupCommandId([manifestId]) brings back a null for my RevitCommandId.

 

Message 4 of 5
Revitalizer
in reply to: Anonymous

Hi zach.bester,

 

there may be another approach for invoking commands, using Reflection.

 

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

namespace MyNamespace
{
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.ReadOnly)]
    [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
    public class Command_InvokeThirdPartyCommand : IExternalCommand
    {
        public Autodesk.Revit.UI.Result Execute(ExternalCommandData revit, ref String message, ElementSet elements)
        {
            try
            {
		// dll path, can be read from addin manifest file
                Assembly asm = Assembly.LoadFrom(@"D:\Tools\2016\RevitLookup.dll");
				
		// Namespace.ClassName, can be read from addin manifest file, too
                Type t = asm.GetType("RevitLookup.CmdSnoopModScope", true); 
				
		// creating an instance of the CmdSnoopModScope
                object obj = Activator.CreateInstance(t);

		// we just hand over the parameters of our own Execute method
                object[] args = new object[3] { revit, message, elements };

                // some modfications must be made because 'message' is a ref parameter
                // http://stackoverflow.com/questions/9881069/why-cant-i-retrieve-the-value-for-parameters-of-type-out-or-ref-using-type-invo
                ParameterModifier pMod = new ParameterModifier(3);
                pMod[1] = true;
                ParameterModifier[] mods = { pMod };
				
		// here we run the instance's Execute method and get the result...
                Result res = (Result)(t.InvokeMember("Execute", 
                    BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Public| BindingFlags.Instance | BindingFlags.Static, 
                    null, obj, args, mods, null, null));

		// ...for just returning it by our own Execute method
                return res;
            }
            catch (Exception ex)
            {
                // log Exception...
                return Autodesk.Revit.UI.Result.Failed;
            }
        }
    }
}

I tested the code with two readonly commands, RevitLookup's 'CmdSnoopModScope' and 'HelloWorld'.
Don't know if the TransactionMode needs to be changed to 'Manual' if the invoked command needs to modify the database.
I suppose that the target method's own TransactionMode attribute will be used.

 

 

Best regards, have a nice weekend,

 

Revitalizer

 

 

 




Rudolf Honke
Software Developer
Mensch und Maschine





Message 5 of 5
SUGKJ
in reply to: Anonymous

I had the same problem today.
Try lower-casing the Id.

SUGKJ

EESignature

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

Post to forums  

Autodesk Design & Make Report