Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.

Revit API Forum

Reply
Highlighted
Post 1 of 10
Accepted Solution

Event to run a IExternalCommand

188 Views, 9 Replies
11-16-2016 06:31 PM

Hi All,

Wondering if you can assist with an issue i'm having that i just cant seem to solve.

Would be nice just to know if what i am trying to do is possible or not.

 

I have been playing around with the events within an ExternalApplication and i have got these to work fine (i.e. using the DocumentCreated event to flash up a "HelloWorld" task dialog when a document is created)

I have also written a few basic ExternalCommands with buttons on the addin ribbon that work fine.

 

My issue is..... how do i get an event to fire off an ExternalCommand instead of having to use a button?

 

I am basically trying to get the event to trigger off the command and make some changes to the document and so i need the current document which i dont believe i can access within the ExternalApplication.

 

I have read all of the event samples in the SDK but still cant work it out and im sure it should be really simple.

 

Thanks

Hi Mike,


maybe I read your message a bit fast. I missed the fact that you were in a IExternalApplication context, I automatically thought you were in IExternalCommand, then you could jus pass the ExternalCommandData object forward.
But to solve your problem you could just refactor your code a bit to get an overload for the Execute()-method that takes a UIApplication object. The Execute-method in the IExternalCommand interface seems abit obsolete anyway.

Also, another thing to bear in mind here is that you should subscribe to the ApplicationInitialized event if you are to do anything with documents.

Here is an example code snippet:

 

 

 

 public class Command : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
return Execute(commandData.Application);
}
public Result Execute(UIApplication uiapp)
{
//Do all sorts of shiny stuff with your command.
return Result.Succeeded;
}
}
public class RevitStartup : IExternalApplication
{
public Result OnShutdown(UIControlledApplication application)
{
return Result.Succeeded;
}
public Result OnStartup(UIControlledApplication application)
{
application.ControlledApplication.ApplicationInitialized += ControlledApplication_ApplicationInitialized;
return Result.Succeeded;
}
private void ControlledApplication_ApplicationInitialized(object sender, Autodesk.Revit.DB.Events.ApplicationInitializedEventArgs e)
{
var command = new Command();
//I never remember if the sender is Application or UIApplication
if (sender is UIApplication)
command.Execute(sender as UIApplication);
else
command.Execute(new UIApplication(sender as Application));
}
}

This will also work even if you dont register a button.

And to Finish off, like Mike said: tell us why you want to achieve and maybe we can find an even easier way of doing it =)

 

/Erik

 

Post 2 of 10

Re: Event to run a IExternalCommand

11-17-2016 01:21 AM in reply to: Mike.Turpin

Hi Mike,

I'm pretty sure that's what PostCommand is for: http://www.revitapidocs.com/2017/b0df464d-1733-ea9e-ac40-399fa9c9a037.htm

 

Give it a test and report back!

 

-Matt

Re: Event to run a IExternalCommand

11-17-2016 04:10 AM in reply to: matthew.taylor

matthew.taylors response is correct and valid for all buttons in Revit (almost), but if you created the externalcommand, you can just create an instance of the class and run the execute-method. Thats even more simple.

Erik Eriksson
White
Post 4 of 10

Re: Event to run a IExternalCommand

11-20-2016 04:14 AM in reply to: erikeriksson5686

Hi Erik,

I am trying to do what you suggest "you can just create an instance of the class and run the execute-method. Thats even more simple" but thats where i am getting stuck.

In my externalapp i am trying to execute the command using 

                Command cmd = new Command();
                cmd.Execute();

however that understandably gives me the error
Error CS7036 There is no argument given that corresponds to the required formal parameter 'commandData' of 'Command.Execute(ExternalCommandData, ref string, ElementSet)'

 

Could you please expand on how i would use the execute method from an IExternalApplication?

 

Thanks

Mike

Re: Event to run a IExternalCommand

11-20-2016 04:45 AM in reply to: Mike.Turpin

Mike, you need a handler for the event, and the IExternaCommand.Execute method does not have the same parameters.

You can fake the the parameters (commanddata, etc) using reflection and a adapter. but that seems awkward.

My suggestion is just to implement a method to handle the event you are after. After all, the sender is usually the application.

Post 6 of 10

Re: Event to run a IExternalCommand

11-21-2016 03:58 AM in reply to: Mike.Turpin

Hi Mike,

I think @erikeriksson5686 was suggesting that if you wrote the external command, you could call the same function that you call in the external command.

 

PostCommand would be the best fit, if you can apply it. Why don't you tell us exactly what you're trying to do?

 

-Matt

Re: Event to run a IExternalCommand

11-21-2016 04:14 AM in reply to: Mike.Turpin

Hi Mike,


maybe I read your message a bit fast. I missed the fact that you were in a IExternalApplication context, I automatically thought you were in IExternalCommand, then you could jus pass the ExternalCommandData object forward.
But to solve your problem you could just refactor your code a bit to get an overload for the Execute()-method that takes a UIApplication object. The Execute-method in the IExternalCommand interface seems abit obsolete anyway.

Also, another thing to bear in mind here is that you should subscribe to the ApplicationInitialized event if you are to do anything with documents.

Here is an example code snippet:

 

 

 

  public class Command : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {

           return Execute(commandData.Application);


        }
        public Result Execute(UIApplication uiapp)
        {
            //Do all sorts of shiny stuff with your command. 

            return Result.Succeeded;

        }
    }
    public class RevitStartup : IExternalApplication
    {
        public Result OnShutdown(UIControlledApplication application)
        {
            return Result.Succeeded;
        }

        public Result OnStartup(UIControlledApplication application)
        {
            application.ControlledApplication.ApplicationInitialized += ControlledApplication_ApplicationInitialized;

            return Result.Succeeded;
        }

        private void ControlledApplication_ApplicationInitialized(object sender, Autodesk.Revit.DB.Events.ApplicationInitializedEventArgs e)
        {
            var command = new Command();

            //I never remember if the sender is Application or UIApplication
            if (sender is UIApplication)
                command.Execute(sender as UIApplication);
            else
                command.Execute(new UIApplication(sender as Application));



        }
    }

This will also work even if you dont register a button.

And to Finish off, like Mike said: tell us why you want to achieve and maybe we can find an even easier way of doing it =)

 

/Erik

 

Erik Eriksson
White
Post 8 of 10

Re: Event to run a IExternalCommand

11-22-2016 02:35 AM in reply to: erikeriksson5686

Hi All,

 

Many many thanks for all your replies.

Although none of them answered the question they did help me realise that what I was trying to do was the wrong way to approach things and that I actually didn't need the ExternalCommand.

 

My reason for thinking I needed the external command was trying to get the "Document" but thanks to Eriks post I found I could get the UIApplication from the sender and that this then let me access the document. So now I am able to run all of my code in the external application!

 

Again many thanks for all your assistance.

 

To finalise my end result was to register a dialog event on startup and shutdown and then:

 

        public void application_new(object sender, DialogBoxShowingEventArgs args)
        {
            if (args.DialogId == "Dialog_Revit_NewProject")
            {
                UIApplication uiapp = sender as UIApplication;
                Application app = uiapp.Application;

//etc etc etc
Post 9 of 10

Re: Event to run a IExternalCommand

11-23-2016 11:06 AM in reply to: Mike.Turpin

Dear Mike, Matt, Erik and Gonçalo,

 

Thank you very much for raising this issue and helping to solve it.

 

I think this discussion is fruitful, illuminating, and well worth preserving, so I published an edited version on the blog:

 

http://thebuildingcoder.typepad.com/blog/2016/11/using-other-events-to-execute-add-in-code.html

 

I hope that you agree with this and like it.

 

Please let me know if you would like me to modify, add or correct anything whatsoever.

 

Thank you!

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Post 10 of 10

Re: Event to run a IExternalCommand

12-06-2016 12:41 PM in reply to: Mike.Turpin

Hey guys,

 

Please note another cool approach described by David Echols to load and execute assembly code on the fly in an Idling event handler by subscribing to that event in the application OnStartup method: "I have used the following code in the last four versions of Revit for overnight batch processing of PDF and DWG exports and sheet lists across multiple workstations. This is not the most elegant way to do this, but it does show how I load the assembly on the fly and execute the command that does the processing...":

 

http://thebuildingcoder.typepad.com/blog/2016/11/using-other-events-to-execute-add-in-code.html#2

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Post to the Community

Have questions about Autodesk products? Ask the community.

New Post

Revit Exchange Apps

Created by the community for the community, Autodesk Exchange Apps for Revit helps you achieve greater speed, accuracy, and automation from concept to manufacturing.