Hello everyone, I’m trying to update a Dynamo script that worked fine in Revit 2021 to Revit 2023. I have a problem with the TaskDialog syntacs, with the Show() method. As seen in the image below. Python always gives me an error message with the show method, even though in the Revit api website that have no updates menitoned in this method. Any ideas what could be the problem here.
It has something to do with CPython and overloads.
So you need to fill out the default parameters for that call, I believe.
@Amr.Omara
If you have little experience with .Net Reflection, this can be useful to get around problems of Overloading
an example
import sys
import clr
import System
from System.Collections.Generic import List
clr.AddReference('RevitAPI')
import Autodesk.Revit.DB as DB
#clr.AddReference("System.Reflection")
from System.Reflection import BindingFlags
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import (TaskDialog, TaskDialogCommonButtons,
TaskDialogCommandLinkId, TaskDialogResult)
title = 'Task Dialog Title'
dialog = TaskDialog(title)
# Properties
dialog.MainInstruction = 'Text Header'
dialog.MainContent = 'Text Content'
dialog.FooterText = 'Footer Text'
dialog.VerificationText = 'Verification Text'
# dialog.ExpandedContent = expanded_content
# Add Button
dialog.CommonButtons = TaskDialogCommonButtons.Ok | TaskDialogCommonButtons.Yes
# Set Default Button
dialog.DefaultButton = getattr(TaskDialogResult, "None")
# Add Command Link
dialog.AddCommandLink(TaskDialogCommandLinkId.CommandLink1,
'Command Button Text',
'Command Button Sub Text')
dialog.AddCommandLink(TaskDialogCommandLinkId.CommandLink2,
'Command Button Text 2',
'Command Button Sub Text 2')
#result = dialog.Show()
# Example 1 with InvokeMember
arguments = []
invokeObj_1 = clr.GetClrType(dialog.GetType()).InvokeMember("Show", BindingFlags.InvokeMethod , None, dialog, arguments)
# OR
# Example 1 with Invoke
filter = System.Predicate[System.Object](lambda m : m.Name == "Show" and len(m.GetParameters()) == 0 )
invokeMethod = List[System.Reflection.MethodInfo](clr.GetClrType(dialog.GetType()).GetMethods()).Find(filter)
invokeObj_2 = invokeMethod.Invoke(dialog, None)
#
OUT = invokeObj_1, invokeObj_2
InvokeMember worked for a TaskDialog in Revit 2024, Invoke did not?
I am trying to create a Revit transaction that can be rolled back. Works fine with IronPython2
thoughts?
import clr
import difflib
import os
import traceback
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
#clr.AddReference('System')
#from System.Collections.Generic import List
from System import Enum
names = Enum.GetNames(FamilyPlacementType)
values = Enum.GetValues(FamilyPlacementType)
placement_dict = dict(zip(values, names))
#clr.AddReference("System.Reflection")
from System.Reflection import BindingFlags
doc = DocumentManager.Instance.CurrentDBDocument
app = doc.Application
options = OpenOptions()
elemDimFilter = ElementClassFilter(Dimension)
elemGeometryFilter = ElementClassFilter(GenericForm)
sm0 = difflib.SequenceMatcher(isjunk=None, a='', b='', autojunk=True)
sm1 = difflib.SequenceMatcher(isjunk=None, a='', b='', autojunk=True)
testfactor = 1.01 #multiply a parameter value and then test if any shape's BoundingBox has changed
difflib_checkratio = 0.8 #if file summaries are more similar then this value, report as suspect
globalErrorReport = []
class CreateFailureAdvancedHandler(IFailuresPreprocessor):
#https://forum.dynamobim.com/t/cant-sucessfully-implement-the-ifailurespreprocessor-interface/50708/2
#https://thebuildingcoder.typepad.com/blog/2012/04/failure-rollback.html
#cant get this to work without a global variable
def PreprocessFailures(self, failuresAccessor):
failMessages = failuresAccessor.GetFailureMessages()
if failMessages.Count == 0:
return FailureProcessingResult.Continue
for currentMessage in failMessages:
failureText = currentMessage.GetDescriptionText()
globalErrorReport.append(failureText) #write to global
failuresAccessor.DeleteWarning(currentMessage) #is this an overlap with .ClearAfterRollback?
return FailureProcessingResult.ProceedWithRollBack
fp = IN[0]
globalErrorReport = []
# Dynamo's transaction handling is pretty poor for multiple documents, so we'll need to force close every single transaction we open
try:
modelPath = ModelPathUtils.ConvertUserVisiblePathToModelPath(fp)
docOnDisk = app.OpenDocumentFile(modelPath, options)
except Exception:
info = str(traceback.format_exc())
else:
TransactionManager.Instance.ForceCloseTransaction()
TransactionManager.Instance.ForceCloseTransaction()
with Transaction(docOnDisk) as tr0:
tr0.Start("SetFamilyType")
#do stuff
tr0.Commit()
TransactionManager.Instance.ForceCloseTransaction()
with Transaction(docOnDisk) as tr2:
tr2.Start("ParameterTest")
failureOptions = tr2.GetFailureHandlingOptions()
failureOptions.SetFailuresPreprocessor(CreateFailureAdvancedHandler())
failureOptions.SetClearAfterRollback(True)
tr2.SetFailureHandlingOptions(failureOptions)
#do stuff
#tr2.Commit() #tr2 failureOptions suppresses any error that occurs
#arguments = []
#x = clr.GetClrType(tr2.GetType())
#invokeObj_1 = x.InvokeMember("Commit", BindingFlags.InvokeMethod , None, tr2, arguments)
filter = System.Predicate[System.Object](lambda m : m.Name == "Commit" and len(m.GetParameters()) == 0 )
invokeMethod = List[System.Reflection.MethodInfo](clr.GetClrType(tr2.GetType()).GetMethods()).Find(filter)
invokeObj_2 = invokeMethod.Invoke(tr2, None)
TransactionManager.Instance.ForceCloseTransaction()
docOnDisk.Close(False)
OUT = info
Hi @e.j.nap
Unfortunately, to date, the CPython3/PythonNet2 engine in Revit 2024 has some additional bugs, due to incomplete compatibility between the Target Framework of PythonRuntime (Python Net 2.5 library) and the Net Framework 4.8 (clr runtime).
there is a fix, but it seems to me that it hasn’t been pushed with Revit 2024.3 (the latest version of Revit 2024 to date)
But fixed in Revit 2025
Example here