Starting in December, we will archive content from the community that is 10 years and older. This FAQ provides more information.
Hi Everyone:
I am a newcomer to develop RevitAPI,now I have a question about suppressing warning messages.
when we use "Paste/ AlignedToSelectedLevels"command to paste elements, if some of these are overlap, Revit displays the following warning message:
Now I creat a addin, in which I use “uiapp.PostCommand(RevitCommandId.LookupPostableCommandId(PostableCommand.AlignedToSelectedLevels));” to paste some elements ,meanwhile I want to suppressing this warning messages and get these messages .
This is my code:-
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Autodesk.Revit.UI; using Autodesk.Revit.DB; using Autodesk.Revit.UI.Selection; using Autodesk.Revit.Attributes; using Autodesk.Revit.DB.Plumbing; using Autodesk.Revit.DB.Mechanical; using Autodesk.Revit.DB.Electrical; using Autodesk.Revit.DB.Architecture; using Autodesk.Revit.DB.Structure; using Autodesk.Revit.DB.Events; using System.Threading; namespace DeleteWarningElement { [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)] public class Class1 : IExternalCommand { public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Document doc = uidoc.Document; uiapp.PostCommand(RevitCommandId.LookupPostableCommandId(PostableCommand.AlignedToSelectedLevels)); Transaction transaction = new Transaction(doc, "BIM"); FailureHandlingOptions options = transaction.GetFailureHandlingOptions(); options.SetFailuresPreprocessor(new FailurePreproccessor()); transaction.SetFailureHandlingOptions(options); transaction.Start(); TaskDialog.Show("1", "12"); Thread.Sleep(5000); transaction.Commit(); return Result.Succeeded; } } public class FailurePreproccessor : IFailuresPreprocessor { public FailureProcessingResult PreprocessFailures(FailuresAccessor failuresAccessor) { IList<FailureMessageAccessor> failList = failuresAccessor.GetFailureMessages(); if (failList.Count == 0) { TaskDialog.Show("1", failList.Count().ToString()); return FailureProcessingResult.Continue; } foreach (FailureMessageAccessor failure in failList) { TaskDialog.Show("1", "123"); FailureDefinitionId failID = failure.GetFailureDefinitionId(); if (BuiltInFailures.CopyPasteFailures.CannotDuplicateWarn==failID) { failuresAccessor.DeleteWarning(failure); } } return FailureProcessingResult.ProceedWithCommit; } } }
When I executed the code, I found this warning was not suppressed. I also found that“ Transaction transaction = new Transaction(doc, "BIM"); ” is a null operation, so what is Transaction of PostCommand in Revit .
how to solve this problem?
Looking forward to your reply!
GoodLuck!
Solved! Go to Solution.
Solved by Mustafa.Salaheldin. Go to Solution.
Solved by Mustafa.Salaheldin. Go to Solution.
Try this and tell me if it works like a charm
#region Namespaces using System; using System.Text; using System.Linq; using System.Xml; using System.Reflection; using System.ComponentModel; using System.Collections; using System.Collections.Generic; using System.Windows; using System.Windows.Media.Imaging; using System.Windows.Forms; using System.IO; using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Events; using Autodesk.Revit.DB.Architecture; using Autodesk.Revit.DB.Structure; using Autodesk.Revit.DB.Mechanical; using Autodesk.Revit.DB.Electrical; using Autodesk.Revit.DB.Plumbing; using Autodesk.Revit.UI; using Autodesk.Revit.UI.Selection; using Autodesk.Revit.UI.Events; //using Autodesk.Revit.Collections; using Autodesk.Revit.Exceptions; using Autodesk.Revit.Utility; using RvtApplication = Autodesk.Revit.ApplicationServices.Application; using RvtDocument = Autodesk.Revit.DB.Document; #endregion namespace RevitAddinCS2 { [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] public class ExtCmd : IExternalCommand { #region Cached Variables 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; } } #endregion #region IExternalCommand Members public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elemSet) { _cachedCmdData = cmdData; try { UIApplication uiapp = cmdData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Document doc = uidoc.Document; uiapp.Application.FailuresProcessing += FaliureProcessor; uiapp.PostCommand(RevitCommandId.LookupPostableCommandId(PostableCommand.AlignedToSelectedLevels)); return Result.Succeeded; } catch (Exception ex) { msg = ex.ToString(); return Result.Failed; } } private void FaliureProcessor(object sender, FailuresProcessingEventArgs e) { FailuresAccessor fas = e.GetFailuresAccessor(); List<FailureMessageAccessor> fma = fas.GetFailureMessages().ToList(); foreach (FailureMessageAccessor fa in fma) { if (fa.GetFailureDefinitionId() == BuiltInFailures.OverlapFailures.DuplicateInstances) { fas.DeleteWarning(fa); } } } #endregion } }
If this satisfies your need please don't forget to mark this reply as an answer.
That's a couple of really great questions, and detecting when a PostableCommand has ended is a problem I've been looking at. Here's my first stab at it. Fair warning, I've only tested this with a very small subset of PostableCommands, and not with the AlignedToSelectedLevels at all. I'm very interested in how it works for you and any feedback the community may have.
Using Mustafa's excellent example in conjuction with the PostableCommandBase, here's what you're command class would look like.
using System; using System.Linq; using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Events; using Autodesk.Revit.UI; namespace DWH.Core.Revit.Commands { [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] public class PostableCommandEndedExample : PostableCommandBase { private static ExternalCommandData _cachedCmdData; protected override PostableCommand PostableCommand => PostableCommand.AlignedToSelectedLevels; protected override RevitCommandResult Initialize(ExternalCommandData commandData, ElementSet elements) { _cachedCmdData = commandData; commandData.Application.Application.FailuresProcessing += FaliureProcessor; return RevitCommandResult.Succeeded(); } protected override void OnCommandEnded(object sender, EventArgs eventArgs) { _cachedCmdData.Application.Application.FailuresProcessing -= FaliureProcessor; } private void FaliureProcessor(object sender, FailuresProcessingEventArgs e) { var failureAccessor = e.GetFailuresAccessor(); var duplicateInstancesMessages = failureAccessor.GetFailureMessages(). Where(messageAccessor => messageAccessor.GetFailureDefinitionId() == BuiltInFailures.OverlapFailures.DuplicateInstances); foreach (var message in duplicateInstancesMessages) { failureAccessor.DeleteWarning(message); } } } }
using System; using Autodesk.Revit.DB; using Autodesk.Revit.UI; namespace DWH.Core.Revit.Commands { public abstract class PostableCommandBase : IExternalCommand { protected abstract PostableCommand PostableCommand { get; } public Result Execute(ExternalCommandData commandData, ref string failureMessage, ElementSet elements) { var initResult = Initialize(commandData, elements); if (initResult.CommandResult != Result.Succeeded) { failureMessage = initResult.FailureMessage; return initResult.CommandResult; } PostCommand(commandData.Application); return Result.Succeeded; } private void PostCommand(UIApplication revitUiApplication) { var commandMonitor = new RevitCommandEndedMonitor(revitUiApplication); commandMonitor.CommandEnded += OnCommandEnded; revitUiApplication.PostCommand(RevitCommandId.LookupPostableCommandId(PostableCommand)); } protected abstract RevitCommandResult Initialize(ExternalCommandData commandData, ElementSet elements); protected virtual void OnCommandEnded(object sender, EventArgs eventArgs) {} } }
using System; using Autodesk.Revit.UI; using Autodesk.Revit.UI.Events; namespace DWH.Core.Revit.Commands { public class RevitCommandEndedMonitor { private readonly UIApplication _revitUiApplication; private bool _initializingCommandMonitor; public event EventHandler CommandEnded; public RevitCommandEndedMonitor(UIApplication revituiApplication) { _revitUiApplication = revituiApplication; _initializingCommandMonitor = true; _revitUiApplication.Idling += OnRevitUiApplicationIdling; } private void OnRevitUiApplicationIdling(object sender, IdlingEventArgs idlingEventArgs) { if (_initializingCommandMonitor) { _initializingCommandMonitor = false; return; } _revitUiApplication.Idling -= OnRevitUiApplicationIdling; OnCommandEnded(); } protected virtual void OnCommandEnded() { CommandEnded?.Invoke(this, EventArgs.Empty); } } }
using Autodesk.Revit.UI; namespace DWH.Core.Revit.Commands { public class RevitCommandResult { private RevitCommandResult(Result revitResult, string failureMessage ="") { FailureMessage = failureMessage; CommandResult = revitResult; } public string FailureMessage { get; private set; } public Result CommandResult { get; private set; } public static RevitCommandResult Failed(string failureMessage) { return new RevitCommandResult(Result.Failed, failureMessage); } public static RevitCommandResult Cancelled() { return new RevitCommandResult(Result.Cancelled); } public static RevitCommandResult Succeeded() { return new RevitCommandResult(Result.Succeeded); } } }
You can simply use
#region Namespaces
using System;
using System.Text;
using System.Linq;
using System.Xml;
using System.Reflection;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Forms;
using System.IO;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.UI.Events;
//using Autodesk.Revit.Collections;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.Utility;
using RvtApplication = Autodesk.Revit.ApplicationServices.Application;
using RvtDocument = Autodesk.Revit.DB.Document;
#endregion
namespace RevitAddinCS2
{
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
public class ExtCmd : IExternalCommand
{
#region Cached Variables
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;
}
}
#endregion
#region IExternalCommand Members
public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elemSet)
{
_cachedCmdData = cmdData;
try
{
CachedUiApp.Application.FailuresProcessing += FaliureProcessor;
CachedUiApp.PostCommand(RevitCommandId.LookupPostableCommandId(PostableCommand.AlignedToSelectedLevels));
return Result.Succeeded;
}
catch (Exception ex)
{
msg = ex.ToString();
return Result.Failed;
}
}
private void FaliureProcessor(object sender, FailuresProcessingEventArgs e)
{
FailuresAccessor fas = e.GetFailuresAccessor();
List<FailureMessageAccessor> fma = fas.GetFailureMessages().ToList();
foreach (FailureMessageAccessor fa in fma)
{
try
{
if (fa.GetFailureDefinitionId() == BuiltInFailures.OverlapFailures.DuplicateInstances)
{
//use the following lines to delete the warning elements
List<ElementId> elemntsToDelete = fa.GetFailingElementIds().ToList();
fas.DeleteElements(elemntsToDelete);
fas.DeleteWarning(fa);
//use the following line to disable the message supressor after the external command ends
CachedUiApp.Application.FailuresProcessing -= FaliureProcessor;
}
}
catch (Exception ex)
{
}
}
}
#endregion
}
}
This will remove the custom failure processor, but from the current location will only remove it in the event of a failure of type DuplicateInstances; it will be active for all commands until then.
//use the following line to disable the message supressor after the external command ends CachedUiApp.Application.FailuresProcessing -= FaliureProcessor;
Does this display the elements to delete in the failure dialog tree as a potential failure resolution? If so, that's much simpler than what I previously thought.
//use the following lines to delete the warning elements
List<ElementId> elemntsToDelete = fa.GetFailingElementIds().ToList();
fas.DeleteElements(elemntsToDelete);
fas.DeleteWarning(fa);
yes bobby this is needed to be done with the duplicate warning fired from the external command only. i.e. if you use the paste align command from the ribbon bar, it is so normal to see the warning again. That is required in our case.
For any other command we actually need to tweek the code to not suppres any related warnings by mistake as you refered.
For the second part of the code you can compare the ids of the elements returned with the ones appears in the warning dialog then clicking expand too see the full deltails.
Thanks Mustafa.Salaheldin.
I used the following code to delete the warning elements:
List<ElementId> elemntsToDelete = fa.GetFailingElementIds().ToList(); fas.DeleteElements(elemntsToDelete); fas.DeleteWarning(fa);
but warning elements were not deleted;
I changed this code as follow:
List<ElementId> elemntsToDelete = fa.GetFailingElementIds().ToList();
IList<ElementId> elemntsToDelete1 = new List<ElementId>();
elemntsToDelete1.Add(elemntsToDelete[0]);
fas.DeleteElements(elemntsToDelete1);
fas.DeleteWarning(fa);
This can detele some elements except pipes connected fitting(as shown in figure), when I paste pipes connected fitting,there will be error:
What reason is this?Do you think how to deal with it?
I have two programs: testA and testB.
In my addin, I want to copy all elements included in testA and then paste (use this command: revitUiApplication.PostCommand(RevitCommandId.LookupPostableCommandId(PostableCommand));) them on testB, if one warning message is pop-up ,I want to dismiss this warning message and delete elements in this warning message.
Could you please try it?
Here you are and don't forget to mark this as an answer if it satisfies your needs:
#region Namespaces using System; using System.Text; using System.Linq; using System.Xml; using System.Reflection; using System.ComponentModel; using System.Collections; using System.Collections.Generic; using System.Windows; using System.Windows.Media.Imaging; using System.Windows.Forms; using System.IO; using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Events; using Autodesk.Revit.DB.Architecture; using Autodesk.Revit.DB.Structure; using Autodesk.Revit.DB.Mechanical; using Autodesk.Revit.DB.Electrical; using Autodesk.Revit.DB.Plumbing; using Autodesk.Revit.UI; using Autodesk.Revit.UI.Selection; using Autodesk.Revit.UI.Events; //using Autodesk.Revit.Collections; using Autodesk.Revit.Exceptions; using Autodesk.Revit.Utility; using RvtApplication = Autodesk.Revit.ApplicationServices.Application; using RvtDocument = Autodesk.Revit.DB.Document; #endregion namespace RevitAddinCS2 { [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] public class ExtCmd : IExternalCommand { #region Cached Variables 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; } } #endregion #region IExternalCommand Members public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elemSet) { _cachedCmdData = cmdData; try { CachedUiApp.Application.FailuresProcessing += FaliureProcessor; CachedUiApp.PostCommand(RevitCommandId.LookupPostableCommandId(PostableCommand.AlignedToSelectedLevels)); return Result.Succeeded; } catch (Exception ex) { msg = ex.ToString(); return Result.Failed; } } private void FaliureProcessor(object sender, FailuresProcessingEventArgs e) { bool hasFailure = false; FailuresAccessor fas = e.GetFailuresAccessor(); List<FailureMessageAccessor> fma = fas.GetFailureMessages().ToList(); foreach (FailureMessageAccessor fa in fma) { try { if (fa.GetFailureDefinitionId() == BuiltInFailures.OverlapFailures.DuplicateInstances) { //use the following lines to delete the warning elements List<ElementId> elemntsToDelete = fa.GetFailingElementIds().ToList(); IList<ElementId> elemntToDelete = new List<ElementId>(); elemntToDelete.Add(elemntsToDelete[0]); fas.DeleteElements(elemntToDelete); fas.DeleteWarning(fa); hasFailure = true; //use the following line to disable the message supressor after the external command ends CachedUiApp.Application.FailuresProcessing -= FaliureProcessor; } } catch (Exception ex) { } } if(hasFailure) { e.SetProcessingResult(FailureProcessingResult.ProceedWithCommit); } e.SetProcessingResult(FailureProcessingResult.Continue); } #endregion } }
Thanks Mustafa.Salaheldin.
I used the above code,but there will be error:
private void FaliureProcessor(object sender, FailuresProcessingEventArgs e) { bool hasFailure = false; FailuresAccessor fas = e.GetFailuresAccessor(); List<FailureMessageAccessor> fma = fas.GetFailureMessages().ToList(); foreach (FailureMessageAccessor fa in fma) { try { if (fa.GetFailureDefinitionId() == BuiltInFailures.OverlapFailures.DuplicateInstances) { //use the following lines to delete the warning elements List<ElementId> elemntsToDelete = fa.GetFailingElementIds().ToList(); IList<ElementId> elemntToDelete = new List<ElementId>(); elemntToDelete.Add(elemntsToDelete[0]); fas.DeleteElements(elemntToDelete); fas.DeleteWarning(fa); hasFailure = true; //use the following line to disable the message supressor after the external command ends CachedUiApp.Application.FailuresProcessing -= FaliureProcessor; } } catch (Exception ex) { TaskDialog.Show("`1", ex.ToString()); } } if(hasFailure) { e.SetProcessingResult(FailureProcessingResult.ProceedWithCommit); } e.SetProcessingResult(FailureProcessingResult.Continue); }
What reason is this?
Here is the cure for all your pain. The error occured because you are trying to delete an element which is already deleted, so I filtered the elements to be deleted list from duplicated ids then celete the elements.
#region Namespaces using System; using System.Text; using System.Linq; using System.Xml; using System.Reflection; using System.ComponentModel; using System.Collections; using System.Collections.Generic; using System.Windows; using System.Windows.Media.Imaging; using System.Windows.Forms; using System.IO; using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Events; using Autodesk.Revit.DB.Architecture; using Autodesk.Revit.DB.Structure; using Autodesk.Revit.DB.Mechanical; using Autodesk.Revit.DB.Electrical; using Autodesk.Revit.DB.Plumbing; using Autodesk.Revit.UI; using Autodesk.Revit.UI.Selection; using Autodesk.Revit.UI.Events; //using Autodesk.Revit.Collections; using Autodesk.Revit.Exceptions; using Autodesk.Revit.Utility; using RvtApplication = Autodesk.Revit.ApplicationServices.Application; using RvtDocument = Autodesk.Revit.DB.Document; #endregion namespace RevitAddinCS2 { [Transaction(TransactionMode.Manual)] [Regeneration(RegenerationOption.Manual)] public class ExtCmd : IExternalCommand { #region Cached Variables 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; } } #endregion #region IExternalCommand Members public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elemSet) { _cachedCmdData = cmdData; try { CachedUiApp.Application.FailuresProcessing += FaliureProcessor; CachedUiApp.PostCommand(RevitCommandId.LookupPostableCommandId(PostableCommand.AlignedToSelectedLevels)); return Result.Succeeded; } catch (Exception ex) { msg = ex.ToString(); return Result.Failed; } } private void FaliureProcessor(object sender, FailuresProcessingEventArgs e) { bool hasFailure = false; FailuresAccessor fas = e.GetFailuresAccessor(); List<FailureMessageAccessor> fma = fas.GetFailureMessages().ToList(); List<ElementId> ElemntsToDelete = new List<ElementId>(); foreach (FailureMessageAccessor fa in fma) { try { if (fa.GetFailureDefinitionId() == BuiltInFailures.OverlapFailures.DuplicateInstances) { //use the following lines to delete the warning elements List<ElementId> FailingElementIds = fa.GetFailingElementIds().ToList(); ElementId FailingElementId = FailingElementIds[0]; if (!ElemntsToDelete.Contains(FailingElementId)) { ElemntsToDelete.Add(FailingElementId); } fas.DeleteWarning(fa); hasFailure = true; } } catch (Exception ex) { } } fas.DeleteElements(ElemntsToDelete); //use the following line to disable the message supressor after the external command ends CachedUiApp.Application.FailuresProcessing -= FaliureProcessor; if (hasFailure) { e.SetProcessingResult(FailureProcessingResult.ProceedWithCommit); } e.SetProcessingResult(FailureProcessingResult.Continue); } #endregion } }
If this satisfies your needs don't forget to mark this reply as an answer.
Can't find what you're looking for? Ask the community or share your knowledge.