How to programmatically open, make changes, save and then close an RFT file. The "Closing" part is the issue

How to programmatically open, make changes, save and then close an RFT file. The "Closing" part is the issue

MiguelVJC82W
Enthusiast Enthusiast
1,966 Views
3 Replies
Message 1 of 4

How to programmatically open, make changes, save and then close an RFT file. The "Closing" part is the issue

MiguelVJC82W
Enthusiast
Enthusiast

I am creating a medium sized add-in (Using C#). The add-in will launch the WindowWizard Add-in from a project file Ribbon by openning the RFT file, and then launching the WindowWiazard form programmatically.
The windowWizard typically will save the family, then finishes with a completed window family. This all works well. I would like the RFT file to close once this save is complete but I can't seem to get the
doc.Close(); method to work. Can anyone please point me in the correct direction?

Please refer to the following code:

 

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


using RvtApplication = Autodesk.Revit.ApplicationServices.Application;
using RvtDocument = Autodesk.Revit.DB.Document;

 

namespace DuraRibbon
{
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]


class CmdLogo3 : IExternalCommand
      {
       private static ExternalCommandData _cachedCmdData;

       public static UIApplication CachedUiApp
           {
              get
                {
                  return _cachedCmdData.Application;
                }
          }

 

     public static RvtApplication CachedApp
      {
           get
              {
                 return CachedUiApp.Application;
              }
        }

 

     public static RvtDocument CachedDoc
      {
          get
            {
                return CachedUiApp.ActiveUIDocument.Document;
            }
        }


private const string Path = @"C:\ProgramData\Autodesk\RVT 2021\Family Templates\English-Imperial\Window.RFT";

 

public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elemSet)
      {
            _cachedCmdData = cmdData;
            Document doc = CachedApp.OpenDocumentFile(Path);
            cmdData.Application.OpenAndActivateDocument(Path);

         

             using (TransactionGroup transGroup = new TransactionGroup(doc))
                 {
                     using (Transaction trans = new Transaction(doc))
                   {
                      try
                          {
                             transGroup.Start("Action");

                              trans.Start("First Transaction");
                              // do some stuff
                            // do your modifications


                             UIApplication uiapp = cmdData.Application;
                               RevitCommandId id_built_in =                        RevitCommandId.LookupPostableCommandId(PostableCommand.SheetIssuesOrRevisions);
                              string name = "a3777760-d59c-426e-bcdc-01c805aa37b9";
                             RevitCommandId id_addin = RevitCommandId.LookupCommandId(name);
                              uiapp.PostCommand(id_addin);

 

                            if (trans.Commit() != TransactionStatus.Committed)
                             {
                                  return Result.Failed;
                             }

 

                            trans.Start("Second Transaction");

                            // do some more stuff
                            doc.Close();
                            trans.Commit();

 

                           if (trans.Commit() != TransactionStatus.Committed)
                             {
                                 return Result.Failed;
                              }

                       transGroup.Assimilate();

                   }
                      catch (Exception ex)
                       {
                             msg = ex.ToString();
                             return Result.Failed;
                       }
                  }

0 Likes
Accepted solutions (1)
1,967 Views
3 Replies
Replies (3)
Message 2 of 4

RPTHOMAS108
Mentor
Mentor

You can't close if you have an open transaction that should throw an exception and skip to the catch statement.

 

You need to complete the transaction then close, if you don't want to save then use close(false) but what would be the point of that?

 

I'm unclear if you want to start a new project file from a template or update the template itself?

 

No call to Application.NewProjectDocument(TemplatePath).

Message 3 of 4

MiguelVJC82W
Enthusiast
Enthusiast

Oh So the Doc.Close(); should not be inside a transaction is what you are saying? No, I still want to save it, but I will be saving the file now as a completed Window/Door Family file (.RFA) to a specified Folder designated by the user. A user should already have a Revit Project open When they launch the Add-in, so closing this window after saving essentially just return them back to the last window they had open.

 

But so what you are suggesting is I place a try catch after the final transGroup.Assimilate(); that contains the   Doc.Close(); method?

 

I've also tried dropping the close into a finally block at the end of my try/catch. The end code looked like this, but was also unsuccessful. 

 

using System;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using RvtApplication = Autodesk.Revit.ApplicationServices.Application;
using RvtDocument = Autodesk.Revit.DB.Document;

 

namespace DuraRibbon
     {
      [Transaction(TransactionMode.Manual)]
      [Regeneration(RegenerationOption.Manual)]


      class CmdLogo : IExternalCommand
               {
                 private static ExternalCommandData _cachedCmdData;

 

                 public static UIApplication CachedUiApp
                   {
                       get
                            {
                                return _cachedCmdData.Application;
                            }
                    }

 

                    public static RvtApplication CachedApp
                    {
                      get
                          {
                            return CachedUiApp.Application;
                           }
                     }

 

                    public static RvtDocument CachedDoc
                  {
                    get
                       {
                         return CachedUiApp.ActiveUIDocument.Document;
                       }
                    }

 

                    private const string Path = @"C:\ProgramData\Autodesk\RVT 2021\Family Templates\English\Metric Window.RFT";
                   private const string PathB = @"C:\ProgramData\Autodesk\RVT 2021\Family Templates\English-Imperial\Window.RFT";

 

                    public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elemSet)
                    {
                        _cachedCmdData = cmdData;
                       Document doc = CachedApp.OpenDocumentFile(PathB);

 

                        try
                             {

                                // do your modifications

                               cmdData.Application.OpenAndActivateDocument(PathB);
                               UIApplication uiapp = cmdData.Application;
                                RevitCommandId id_built_in = RevitCommandId.LookupPostableCommandId                (PostableCommand.SheetIssuesOrRevisions);
                                string name = "a3777760-d59c-426e-bcdc-01c805aa37b9";
                                RevitCommandId id_addin = RevitCommandId.LookupCommandId(name);
                                 uiapp.PostCommand(id_addin);

                               //doc.Close();

 

                              return Result.Succeeded;
                              }

                             catch (Exception ex)
                             {
                              msg = ex.ToString();
                             return Result.Failed;
                             }


                            finally
                             {
                               doc.Close();
                             }

                      }
               }
}

 

I do not want this to close before the code in the Try block has finished successfully.

 

0 Likes
Message 4 of 4

RPTHOMAS108
Mentor
Mentor
Accepted solution

My comment regarding try/catch was just the explanation of what would be happening in your code above (nothing after doc.Close executed apart from the catch statement). I would not suggest using try/catch for the avoidance of documented exceptions.

 

The command you post I believe will always be activated at the end i.e. after you exit the API context. That is just the way posting a command works (for good reason). It is always the last thing you do and is not synchronous with the other API calls you make in the same context.

 

If you can detect the end of the posted command i.e. a return to idling etc. then you could close the document that way (in a separate context) but that is about it as far as I know.

0 Likes