Announcements
Due to scheduled maintenance, the Autodesk Community will be inaccessible from 10:00PM PDT on Oct 16th for approximately 1 hour. We appreciate your patience during this time.
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: 

Run external command on Revit startup

11 REPLIES 11
Reply
Message 1 of 12
Paulio
6153 Views, 11 Replies

Run external command on Revit startup

Guys,

 

I have an external command that I can run when I click a button in Revit (it opens a family file, adds some parameters, closes and saves it).

I've also found in the SDK samples an example of running some code when Revit starts up.

 

The problem I have is how do I run my command when the application starts? The startup one implements IExternalAplication and the button one implements IExternalCommand. I can't just put the code for my button into the OnStartup function of the external application as it needs access to the CommandData that you get in the Execute function of the external command.

 

I've come from programming AutoCAD and I'm a bit of a Revit noob so apologies if the answer is obvious but I've had a search around and can't seem to find anything.

 

Thanks in advance.

11 REPLIES 11
Message 2 of 12
Paulio
in reply to: Paulio

I've done some more investigation and found a blog post by Jeremy on his Building Coder blog which seems to suggest that it might be possible using SendKeys and the WinAPI. It is a VERY old post and I don't really want to go that route. I found another post which suggests that what I'm trying to do is either not possible or if I do get it to work somehow it would be risky and unstable (that post is from 2010).

 

I was just wondering as I'm using Revit 2012 whether anything had been implemented which would allow me to do what I'm trying to do. If it's not possible, that's fine, it would just be nice to know for certain one way or the other.

 

I don't want to waste time trying to figure out how to do something that can't be done.

Message 3 of 12
jeremytammik
in reply to: Paulio

Dear Paulio,

Thank you for your query.

Just as you discovered on The Building Coder blog, the Revit API can only be used within a valid call-back context.

These contexts are provided by the various events defined by the API, including the external command Execute and the external application OnStartup and OnShutdown that you mention. The Revit API defines many other events that you can optionally subscribe to from within these.

You are perfectly correct in stating that there is no absolutely obvious way to achieve what you want right out of the box using one single step, but it can very well be achieved by combining a few different steps.

Also, you are definitely on the right track when you say that you need some functionality from the AutoParameter sample and another bit from the APIAppStartup one.

As said, the external application is given access to the API through the OnStartup event. Unfortunately, at that point in time, the document that you wish to modify may not be fully opened and accessible yet, so that is too early. What you can do, however, is subscribe to the DocumentOpened event from within OnStartup.

The Revit API documentation in RevitAPI.chm has the following to say about this event:

"Subscribe to the DocumentOpened event to be notified immediately after Revit has finished opening a document.

This event is raised immediately after Revit has finished opening a document. It is raised even when document opening failed or was cancelled (during DocumentOpening event).

Handlers of this event are permitted to make modifications to any document (including the active document), except for documents that are currently in read-only mode.

Check the 'Status' field in the event argument to see whether the action itself was successful or not.

This event is not cancellable, for the process of opening document has already been finished.

If the action was not successful, the document may not be modified and new transactions may not be started.

The following API functions are not available for the current document during this event: Close and similar overloads."

That sounds as if you could very well run the code to add your parameters within this event handler.

All you have to do is extract the code from the AutoParameter sample that you are using and convert it from an external command Execute method implementation taking a CommandData input argument to take a Document argument instead.

I hope this helps.

Please let us know if there is anything further we can help with, how you get on, and what solution you end up implementing, since I think this issue might be of interest to others as well.

Best regards,

Jeremy
--
Jeremy Tammik
Autodesk Developer Network -- http://www.autodesk.com/joinadn
The Building Coder -- http://thebuildingcoder.typepad.com



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

Message 4 of 12
Paulio
in reply to: Paulio

Hi Jeremy,

 

Excellent, that sounds like a plan.

 

I guess I'll need to open a dummy document so that the document opened event gets fired but that shouldn't cause a problem.

 

Will the application object from the document in the DocumentOpenedEventArgs give me access to opening and closing the family files?

 

I guess I'll find out when I try it!

 

I'll let you know how it goes.

 

Thanks

Message 5 of 12
Paulio
in reply to: Paulio

OK so I got it working thanks to Jeremy's suggestion.

 

I can't post the full code here but this is the basics in case anyone's interested:

 

In my Revit addin I'm subscribing to the DocumentOpened event.

I've got my windows app writing settings to an XML file that I want revit to read.

My app sets a flag in the settings file that my DocumentOpened event handler reads

My windows app just does a system.process.start on a blank rfa file to boot up revit and open that dummy file

The DocumentOpened event reads the flag from the settings file and runs my code if the flag is true

It sets the flag to false so that the code doesn't run any more (as my code is opening rfa files)

 

The important thing is the flag that my addin reads to determine if it should do anything when a document opens. While it's set to False, nothing happens which means there's no problem having the addin loaded if the user is not using my app.

 

The problem I have now is speed: I've added the RegenerationOption.Manual attribute to my class but it's taking over 20 seconds to set a parameter value in a family that has 12 types. The Regeneration option doesn't seem to have any affect. Perhaps it's because my class doesn't implement IExternalCommand or IExternalApplication.

 

I think I'll post that as another question.

 

Thanks again to Jeremy for the idea. Hope this helps someone else.

 

Message 6 of 12
jeremytammik
in reply to: Paulio

Congratulations!

 

And thank you for the appreciation!

 

By the way, here is an old sample that does something related:

 

http://thebuildingcoder.typepad.com/blog/2009/07/journal-file-replay.html

 

Good luck optimising!

 

I will happily publish your final solution once it is done.

 

Cheers, Jeremy.



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

Message 7 of 12
Anonymous
in reply to: jeremytammik

Jeremy, any thoughts on the optimisation?

 

I'm not really sure what I can do to make it quicker.

 

As I've said in this post the regeneration option doesn't seem to make any difference and the SuspendUpdating is no longer available.

 

I'd appreciate any pointers you might have.

 

Thanks

Message 8 of 12
Dale.Bartlett
in reply to: Paulio

I am trying the following code and addin to build a start-up module to run some simple process. I don't think it is close to being correct, but I can't find examples. Can anyone shed some light?   

<code>

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Autodesk.Revit.DB;

using Autodesk.Revit.UI;

using Autodesk.Revit.Attributes;

namespace

ATK_RevitStartup

{

[Autodesk.Revit.Attributes.

Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]

[Autodesk.Revit.Attributes.

Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]

[Autodesk.Revit.Attributes.

Journaling(Autodesk.Revit.Attributes.JournalingMode.NoCommandData)]

 

publicclassStartupTest//: IExternalCommand

{

privatevoid Module_Startup(object sender, EventArgse)

{

System.Windows.Forms.

MessageBox.Show("Module_Startup");

}

void Application_DocumentOpened(object sender, Autodesk.Revit.DB.Events.DocumentOpenedEventArgse)

{

System.Windows.Forms.

MessageBox.Show("DocumentOpened");

}

privatevoid Module_Shutdown(object sender, EventArgse)

{

System.Windows.Forms.

MessageBox.Show(" Module_Shutdown");

}

}

}

</code>

<?xml version="1.0" encoding="utf-8"?>
<RevitAddIns>
  <AddIn Type="Application">
    <Name>ATK Revit Startup Test</Name>
    <Assembly>C:\ProgramData\Autodesk\Revit\Addins\2013\ATK_RevitStartup.dll</Assembly>
    <AddInId>5daea0de-0a4a-43cc-b1ed-2fb6e232bb27</AddInId>
    <FullClassName>ATK_RevitStartup.StartupTest</FullClassName>
    <VendorId>ATK</VendorId>
    <VendorDescription>Atkins</VendorDescription>
  </AddIn>
</RevitAddIns>




______________
Yes, I'm Satoshi.
Message 9 of 12

Hi Dale,

 

Please look at yesterday's post on The Building Coder:

 

http://thebuildingcoder.typepad.com/blog/2013/06/auto-pdf-print-from-revit-2014.html

 

Also, hang on and look at today's post, not yet published, but coming real sooooon now...

 

Best regards,

 

Jeremy



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

Message 10 of 12
jeremytammik
in reply to: jeremytammik
Message 11 of 12
arnostlobel
in reply to: Dale.Bartlett

There is no need for complex examples. However, what you need to realize first is that commands do not run on Revit startup. Only application-wide macros and external applications get invoked on startup. Please look through the SDK samples and find any example of an external application (search for IExternalApplication). You will find that it has methods OnStartup and OnShutdown. The former is, quite obviously, run when Revit starts.

 

Thank you

 

Arnošt Löbel

Autodesk Revit R&D

Arnošt Löbel
Message 12 of 12
Dale.Bartlett
in reply to: arnostlobel

Many thanks for the responses. I used 2014 SDK Samples\APIAppStartup as a starting point. The Splash Screen wasn't displaying (or so I thought) so added <code>System.Windows.Forms.MessageBox.Show("OnStartup"); </code>

Just what I needed. Dale




______________
Yes, I'm Satoshi.

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

Post to forums  

Rail Community


Autodesk Design & Make Report