Here is a question that comes up from time to time on how to open and display a project or family file in the Revit user interface. I mentioned a workaround in the answer to a comment by Nadim, and now I think it is time to promote this little information nugget to a proper post to make it easier to find.
Question: I need to open and display an existing project or family in the Revit user interface. I see that the NewFamilyDocument and NewProjectDocument methods create new documents but do not open them. I tried to use the OpenDocumentFile method taking a document path name argument to open an existing project, but it does not display it in the user interface either, it only returns an in-memory version of the document. I also implemented an event handler and verified that the OnDocumentOpen event is not triggered by it. Is it possible to open and display a document in the Revit user interface, and if so, how, please?
Answer: Yes, correct, NewFamilyDocument, NewProjectDocument and OpenDocumentFile only create new or open existing documents for API manipulation. They do not display them in the user interface, only open them in the background in-memory, without the Revit user interface even being aware of it, which is why the event is not triggered either. There is currently no API method at all to make a document current in the Revit user interface. There is a workaround, though, that several people have used successfully: you can use Process.Start as described in the comments on debugging an add-in. Here is a little console application demonstrating such a call:
class Program { static void Main( string[] args ) { System.Diagnostics.Process.Start( "C:/tmp/wall.rvt" ); } }
This uses the existing instance of Revit if it is already running. It also works fine to start up Revit if you replace the project file "C:/tmp/wall.rvt" by the Revit application executable, although in that case obviously no document is opened.
Hi Jeremy,
This post got me half way to where I need to be. Is there a way to start the revit.exe and then supply the file name? I need a way to deal with multiple versions installed on a machine and have the correct year / flavor open. I tried setting ...StartInfo.Arguments to the file name but Revit returns a "Failed to open document." error. Any ideas?
Posted by: Chris | April 15, 2010 at 21:15
Dear Chris,
Sorry for the very late answer, I seem to have missed the original notification when you posted your comment.
You should be able to use Process.Start to start up Revit.exe as well, specifying the full desired path name and the project file as an argument at the same time, cf. e.g.
http://dotnetperls.com/process-start-net
Cheers, Jeremy.
Posted by: Jeremy Tammik | May 10, 2010 at 10:36
Wow wow, GREAT web site!
I can’t tell you how much time is spend reading your Website getting ideas, testing, playing.
I don’t even have any real programming experience and I’m thinking of leaving my Architectural Job and starting my own Software Company.
A friend and I am trying to write an add-on that will loop through a list of families, open each family extract a list of type names and parameters values and close it without saving.
The code I have post below works for a small number of families (less that 100) but Revit crashes when we process a large number (more than 100) it displays a dialog saying it was “memory corruption”. It would happen during the opening of a file “OpenDocumentFile()”(see code below).
Is there a better way to loop through families opening and closing them?
Could we have an external application fire up Revit and run my plugin. The external application could keep track of which file was next.
Thank you very much any help would be much appreciated.
void LoadFamily(Autodesk.Revit.ApplicationServices.Application app,
ExternalCommandData commandData, string filename, StreamWriter writer)
{
try
{
if (string.IsNullOrEmpty(filename))
return;
if (!File.Exists(filename))
return;
Document activeDoc =
commandData.Application.ActiveUIDocument.Document;
if (activeDoc != null)
activeDoc.Close();
activeDoc = app.OpenDocumentFile(filename);
if (activeDoc == null)
return;
//process the document and add data to an external file
}
catch (Exception e)
{
MessageBox.Show(e.Message + "\n" + filename);
}
}
Posted by: Nicholas B | June 10, 2010 at 09:45
Dear Nicholas,
Thank you very much for your appreciation, and I am very glad that you find it useful!
Congratulations on getting into Revit programming with your friend!
I see several sub-questions in your comment:
1) How can I reduce the memory being used by Revit when I open and close a file?
2) How can I drive Revit from outside to open a specific file, execute some code in it, and close the file again, so that I can keep track from outside of which files have been processed so far?
Regarding the first question, I see you are closing the active document. I do not think that this will work. When you open a document through the Revit API, that does not affect the active foreground document, as far as I know. The API-opened document will always be a background document. I would do something like this instead, ignoring the active document, doing all the processing in the background:
Document doc = app.OpenDocumentFile( filename );
Process( doc );
doc.Close();
Try it out, that might solve your problem.
If not, you can continue with your second idea, which makes good sense to me. I have resorted to similar approaches in the past for batch processing a large number of files with applications which do not release all the data every time the files is closed, so they eventually run out of memory.
You could implement your functionality in an Application.DocumentOpened event handler, and then use a command line application to start up Revit with a journal file to simply open and close each document you wish to process. You could also simply implement your functionality in an external command instead of the DocumentOpened event, and add the launching of your command to the journal file steps. For more info on this approach, please refer to
http://thebuildingcoder.typepad.com/blog/2009/07/journal-file-replay.html
I hope this helps and wish you much success with your project!
Cheers, Jeremy.
Posted by: Jeremy Tammik | June 10, 2010 at 15:10
Is is possible to open a project and show the specify workset dialog before the file opens?
Thanks.
Posted by: Ian | July 16, 2010 at 23:51
Dear Ian,
If it is possible for you to include starting up Revit itself into the steps you describe, then yes, that should be possible using a journal file as described in
http://thebuildingcoder.typepad.com/blog/2010/07/ifc-import-and-conversion-journal-script.html
Otherwise, you might be able to use Autohotkey or the Windows API or some other mechanism to simulate the user input to display the desired dialogue.
Cheers, Jeremy.
Posted by: Jeremy Tammik | July 19, 2010 at 17:42
Hi Jeremy,
Is it possible to open/load a Revit project(.rvt) without Revit.exe instance running? Most of the Revit Sdk samples are running in add-in behavior where the Revit.exe must be startup first.
Let's said i want to open a Revit project and retrieve the elements inside the project and show it in a windows form.(without running in add-in manner)
Posted by: bsyap | March 01, 2011 at 04:41
Dear Bsyap,
Short and clear answer: no, sorry, no way.
Cheers, Jeremy.
Posted by: Jeremy Tammik | March 02, 2011 at 07:39
Hi Jeremy,
For Revit 2012, is it possible to insert Revit file as linked file using Revit API. I have read and search if there are any method or way to doing it but failed. I only managed to open revit file in a separate window using OpenAndActivateDocument.
Thank you
Abby
Posted by: abby | March 08, 2012 at 07:35
Dear Abby,
Sorry, that is currently not supported by the Revit API.
All we have right now is the Document.Link method, which only applies to DWG files.
Cheers, Jeremy.
Posted by: Jeremy Tammik | March 08, 2012 at 08:05
Is there any way to open revit file with 'Audit' option using Process.Start? Where could I find the full list of command line parameters (if there are any)?
Thank you!
Posted by: Victor | May 03, 2012 at 09:27
Dear Victor,
Nope, not that I know of.
Your best bet, if you really want to do it anyway, without official API support, might be to try using UI Automation:
http://thebuildingcoder.typepad.com/blog/automation
Cheers, Jeremy.
Posted by: Jeremy Tammik | May 07, 2012 at 04:35
Hello,
your solution works well thanks a lot
I have just create a small code OpenRevit.exe to open a file in REVIT with filename as Parameter (use "" if filename have any space in name , ex : OpenRevit.exe "C:\temp\My File REVIT.rvt")
Module Module1
Sub Main()
Dim CommandLine As String = My.Application.CommandLineArgs(0)
'Environment.GetCommandLineArgs()
System.Diagnostics.Process.Start(CommandLine)
End Sub
End Module
Posted by: Xavier KLEIN | December 18, 2014 at 13:10
Dear Xavier,
Cool! Thank you for your appreciation and for sharing your code!
Cheers, Jeremy.
Posted by: Jeremy Tammik | December 19, 2014 at 02:43