TaskDialog Problem in Revit 2023

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.

6 Likes

@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
7 Likes

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

3 Likes