def WithExceptionLogging(action, output): result = None try: result = action() except Exception, e: exception_util.LogOutputErrorDetails(e, output) raise
def DialogShowingEventHandler(sender, eventArgs, output): try: dialogResult = IDOK msg = StringBuilder() msg.AppendLine() msg.AppendLine("Dialog box shown:") msg.AppendLine() if isinstance(eventArgs, TaskDialogShowingEventArgs): msg.AppendLine("\tMessage: " + str(eventArgs.Message)) if eventArgs.DialogId == "TaskDialog_Missing_Third_Party_Updater": dialogResult = 1001 # Continue working with the file. elif eventArgs.DialogId == "TaskDialog_Location_Position_Changed": dialogResult = 1002 # Do not save. elif isinstance(eventArgs, MessageBoxShowingEventArgs): msg.AppendLine("\tMessage: " + str(eventArgs.Message)) msg.AppendLine("\tDialogType: " + str(eventArgs.DialogType)) dialogId = Try( lambda: eventArgs.DialogId ) # Available on DialogBoxShowingEventArgs in Revit 2017+ if dialogId is not None: msg.AppendLine("\tDialogId: " + str(dialogId)) helpId = Try( lambda: eventArgs.HelpId) # No longer available in Revit 2018+ if helpId is not None: msg.AppendLine("\tHelpId: " + str(helpId)) output(msg.ToString()) eventArgs.OverrideResult(dialogResult) except Exception, e: errorMsg = StringBuilder() errorMsg.AppendLine() errorMsg.AppendLine("Caught exception in dialog event handler!") errorMsg.AppendLine("Exception message: " + e.message) output(errorMsg.ToString()) exception_util.LogOutputErrorDetails(e, output)
def ConsolidateSnapshotData(dataExportFolderPath, output): try: snapshotDataFilePath = GetSnapshotDataFilePath(dataExportFolderPath) temporarySnapshotDataFilePath = GetTemporarySnapshotDataFilePath( dataExportFolderPath) if File.Exists(snapshotDataFilePath): if File.Exists(temporarySnapshotDataFilePath): File.Delete(temporarySnapshotDataFilePath) elif File.Exists(temporarySnapshotDataFilePath): File.Move(temporarySnapshotDataFilePath, snapshotDataFilePath) else: output() output( "WARNING: could not find snapshot data file in snapshot data folder:" ) output() output("\t" + dataExportFolderPath) except Exception, e: output() output( "WARNING: failed to properly consolidate the snapshot data in folder:" ) output() output("\t" + dataExportFolderPath) exception_util.LogOutputErrorDetails(e, output)
def TerminateHostRevitProcess(hostRevitProcess, output): try: hostRevitProcess.Kill() except Exception, e: output() output( "ERROR: an error occurred while attempting to kill the Revit process!" ) exception_util.LogOutputErrorDetails(e, output)
def CopySnapshotRevitJournalFile(snapshotDataFolderPath, output): revitJournalFilePath = None try: snapshotDataFilePath = GetSnapshotDataFilePath(snapshotDataFolderPath) revitJournalFilePath = ReadSnapshotDataRevitJournalFilePath(snapshotDataFilePath) except Exception, e: output() output("WARNING: failed to read journal file path from snapshot data file.") exception_util.LogOutputErrorDetails(e, output) output() output("Attempting to read journal file path from temporary snapshot data file instead.") snapshotDataFilePath = GetTemporarySnapshotDataFilePath(snapshotDataFolderPath) revitJournalFilePath = ReadSnapshotDataRevitJournalFilePath(snapshotDataFilePath)
def ProcessFailures(failuresAccessor, output, rollBackOnWarning=False): try: result = FailureProcessingResult.Continue doc = failuresAccessor.GetDocument() app = doc.Application failureReg = app.GetFailureDefinitionRegistry() failures = failuresAccessor.GetFailureMessages() if failures.Any(): output() output("Processing Revit document warnings / failures (" + str(failures.Count) + "):") for failure in failures: failureDefinition = failureReg.FindFailureDefinition( failure.GetFailureDefinitionId()) ReportFailureWarning(failure, failureDefinition, output) failureSeverity = failure.GetSeverity() if failureSeverity == FailureSeverity.Warning and not rollBackOnWarning: failuresAccessor.DeleteWarning(failure) elif (failureSeverity == FailureSeverity.Error and failure.HasResolutions() and result != FailureProcessingResult.ProceedWithRollBack and not rollBackOnWarning): # If Unlock Constraints is a valid resolution type for the current failure, use it. if failure.HasResolutionOfType( FailureResolutionType.UnlockConstraints): failure.SetCurrentResolutionType( FailureResolutionType.UnlockConstraints) elif failureDefinition.IsResolutionApplicable( FailureResolutionType.UnlockConstraints): output() output( "\t" + "WARNING: UnlockConstraints is not a valid resolution for this failure despite the definition reporting that it is an applicable resolution!" ) output() output("\t" + "Attempting to resolve error using resolution: " + str(failure.GetCurrentResolutionType())) failuresAccessor.ResolveFailure(failure) result = FailureProcessingResult.ProceedWithCommit else: result = FailureProcessingResult.ProceedWithRollBack else: result = FailureProcessingResult.Continue except Exception, e: output() output("ERROR: the failure handler generated an error!") exception_util.LogOutputErrorDetails(e, output) result = FailureProcessingResult.Continue
def ExecutePostProcessingScript(batchRvtConfig, output): aborted = False try: InitializeScriptUtil(batchRvtConfig) output() output("Post-processing script operation started.") script_util.ExecuteScript(batchRvtConfig.PostProcessingScriptFilePath) output() output("Post-processing script operation completed.") except Exception, e: output() output( "ERROR: An error occurred while executing the post-processing script! Operation aborted." ) exception_util.LogOutputErrorDetails(e, output) aborted = True
def WithErrorHandling(action, errorMessage, output=None, showErrorMessageBox=False): result = None try: result = action() except Exception, e: if output is not None: output() output(errorMessage) exception_util.LogOutputErrorDetails(e, output) if showErrorMessageBox: fullErrorMessage = StringBuilder() fullErrorMessage.AppendLine(errorMessage) fullErrorMessage.AppendLine() fullErrorMessage.AppendLine(exception_util.GetExceptionDetails(e)) ShowScriptErrorMessageBox(fullErrorMessage.ToString()) SetDataInCurrentDomain(SCRIPT_HOST_ERROR_DATA_VARIABLE, e)
def SafeCloseWithoutSave(doc, isOpenedInUI, closedMessage, output): app = doc.Application try: if not isOpenedInUI: revit_file_util.CloseWithoutSave(doc) output() output(closedMessage) except InvalidOperationException, e: output() output("WARNING: Couldn't close the document!") output() output(str(e.Message)) except Exception, e: output() output("WARNING: Couldn't close the document!") exception_util.LogOutputErrorDetails(e, output, False) app.PurgeReleasedAPIObjects() return def WithOpenedDetachedDocument(uiapp, openInUI, centralFilePath, discardWorksets, worksetConfig, audit, documentAction, output): app = uiapp.Application result = None output() output("Opening detached instance of central file: " + centralFilePath) closeAllWorksets = worksetConfig is None if openInUI: if discardWorksets: uidoc = revit_file_util.OpenAndActivateDetachAndDiscardWorksets(
def monitoringAction(): pendingProcessOutputReadLineTask[0] = ShowRevitProcessOutput( hostRevitProcess.StandardOutput, output, pendingProcessOutputReadLineTask[0]) pendingProcessErrorReadLineTask[0] = ShowRevitProcessError( hostRevitProcess.StandardError, showRevitProcessErrorMessages, output, pendingProcessErrorReadLineTask[0]) pendingReadLineTask[0] = ShowRevitScriptOutput( scriptOutputStreamReader, output, pendingReadLineTask[0]) if time_util.GetSecondsElapsedSinceUtc( progressRecordCheckTimeUtc[0] ) > REVIT_PROGRESS_CHECK_INTERVAL_IN_SECONDS: progressRecordCheckTimeUtc[ 0] = time_util.GetDateTimeUtcNow() progressRecordNumber = ScriptDataUtil.GetProgressNumber( progressRecordFilePath) if progressRecordNumber is not None: if currentProgressRecordNumber[ 0] != progressRecordNumber: # Progress update detected. currentProgressRecordNumber[ 0] = progressRecordNumber progressRecordChangedTimeUtc[ 0] = time_util.GetDateTimeUtcNow() if processingTimeOutInMinutes > 0: if currentProgressRecordNumber[0] != 0: if time_util.GetSecondsElapsedSinceUtc( progressRecordChangedTimeUtc[0]) > ( processingTimeOutInMinutes * SECONDS_PER_MINUTE): output() output( "WARNING: Timed-out waiting for Revit task / file to be processed. Forcibly terminating the Revit process..." ) TerminateHostRevitProcess(hostRevitProcess, output) if currentProgressRecordNumber[0] == 0: if time_util.GetSecondsElapsedSinceUtc( progressRecordChangedTimeUtc[0] ) > REVIT_PROCESS_BEGIN_PROCESSING_TIMEOUT_IN_SECONDS: output() output( "WARNING: Timed-out waiting for Revit script host to begin task / file processing. Forcibly terminating the Revit process..." ) TerminateHostRevitProcess(hostRevitProcess, output) if snapshotDataFilesExistTimestamp[0] is not None: if time_util.GetSecondsElapsedSinceUtc( snapshotDataFilesExistTimestamp[0] ) > REVIT_PROCESS_EXIT_TIMEOUT_IN_SECONDS: output() output( "WARNING: Timed-out waiting for the Revit process to exit. Forcibly terminating the Revit process..." ) TerminateHostRevitProcess(hostRevitProcess, output) elif snapshotDataFilePaths.All( lambda snapshotDataFilePath: File.Exists( snapshotDataFilePath)): output() output( "Detected snapshot data files. Waiting for Revit process to exit..." ) snapshotDataFilesExistTimestamp[ 0] = time_util.GetDateTimeUtcNow() try: revit_dialog_detection.DismissCheekyRevitDialogBoxes( hostRevitProcessId, output) except Exception, e: output() output( "WARNING: an error occurred in the cheeky Revit dialog box dismisser!" ) exception_util.LogOutputErrorDetails(e, output)
def ProcessRevitFiles(batchRvtConfig, supportedRevitFileList): aborted = False totalFilesCount = len(supportedRevitFileList) progressNumber = 1 for revitVersion, supportedRevitFiles in GroupByRevitVersion( batchRvtConfig, supportedRevitFileList): sessionRevitFiles = [] queuedRevitFiles = list(supportedRevitFiles) while queuedRevitFiles.Any(): scriptDatas = [] snapshotDataExportFolderPaths = [] if batchRvtConfig.RevitSessionOption == BatchRvt.RevitSessionOption.UseSameSessionForFilesOfSameVersion: sessionRevitFiles = queuedRevitFiles queuedRevitFiles = [] else: sessionRevitFiles = [queuedRevitFiles[0]] queuedRevitFiles = queuedRevitFiles[1:] sessionFilesCount = len(sessionRevitFiles) if len(sessionRevitFiles) == 1: Output() Output("Processing Revit file (" + str(progressNumber) + " of " + str(totalFilesCount) + ")" + " in Revit " + RevitVersion.GetRevitVersionText(revitVersion) + " session.") else: Output() Output("Processing Revit files (" + str(progressNumber) + " to " + str(progressNumber + sessionFilesCount - 1) + " of " + str(totalFilesCount) + ")" + " in Revit " + RevitVersion.GetRevitVersionText(revitVersion) + " session.") for supportedRevitFileInfo in sessionRevitFiles: batch_rvt_monitor_util.ShowSupportedRevitFileInfo( supportedRevitFileInfo, Output) Output() Output("Starting Revit " + RevitVersion.GetRevitVersionText(revitVersion) + " session...") for index, supportedRevitFileInfo in enumerate(sessionRevitFiles): snapshotDataExportFolderPath = str.Empty revitFilePath = supportedRevitFileInfo.GetRevitFileInfo( ).GetFullPath() if batchRvtConfig.EnableDataExport: snapshotDataExportFolderPath = snapshot_data_util.GetSnapshotFolderPath( batchRvtConfig.DataExportFolderPath, revitFilePath, batchRvtConfig.SessionStartTime) path_util.CreateDirectory(snapshotDataExportFolderPath) snapshotDataExportFolderPaths.append( snapshotDataExportFolderPath) revitFilePath = supportedRevitFileInfo.GetRevitFileInfo( ).GetFullPath() scriptData = ScriptDataUtil.ScriptData() scriptData.SessionId.SetValue(batchRvtConfig.SessionId) scriptData.TaskScriptFilePath.SetValue( batchRvtConfig.ScriptFilePath) scriptData.RevitFilePath.SetValue(revitFilePath) scriptData.TaskData.SetValue(batchRvtConfig.TaskData) scriptData.OpenInUI.SetValue(batchRvtConfig.OpenInUI) scriptData.EnableDataExport.SetValue( batchRvtConfig.EnableDataExport) scriptData.SessionDataFolderPath.SetValue( batchRvtConfig.SessionDataFolderPath) scriptData.DataExportFolderPath.SetValue( snapshotDataExportFolderPath) scriptData.ShowMessageBoxOnTaskScriptError.SetValue( batchRvtConfig.ShowMessageBoxOnTaskError) scriptData.RevitProcessingOption.SetValue( batchRvtConfig.RevitProcessingOption) scriptData.CentralFileOpenOption.SetValue( batchRvtConfig.CentralFileOpenOption) scriptData.DeleteLocalAfter.SetValue( batchRvtConfig.DeleteLocalAfter) scriptData.DiscardWorksetsOnDetach.SetValue( batchRvtConfig.DiscardWorksetsOnDetach) scriptData.ProgressNumber.SetValue(progressNumber + index) scriptData.ProgressMax.SetValue(totalFilesCount) scriptDatas.append(scriptData) batchRvtScriptsFolderPath = BatchRvt.GetBatchRvtScriptsFolderPath() while scriptDatas.Any(): nextProgressNumber = batch_rvt_monitor_util.RunScriptedRevitSession( revitVersion, batchRvtScriptsFolderPath, batchRvtConfig.ScriptFilePath, scriptDatas, progressNumber, batchRvtConfig.ProcessingTimeOutInMinutes, batchRvtConfig.TestModeFolderPath, Output) if nextProgressNumber is None: Output() Output( "WARNING: The Revit session failed to initialize properly! No Revit files were processed in this session!" ) progressNumber += len(scriptDatas) break else: progressNumber = nextProgressNumber scriptDatas = (scriptDatas.Where( lambda scriptData: scriptData.ProgressNumber.GetValue( ) >= progressNumber).ToList()) if batchRvtConfig.EnableDataExport: Output() Output("Consolidating snapshots data.") for snapshotDataExportFolderPath in snapshotDataExportFolderPaths: snapshot_data_util.ConsolidateSnapshotData( snapshotDataExportFolderPath, Output) # NOTE: Have disabled copying of journal files for now because if many files were processed # in the same Revit session, too many copies of a potentially large journal file # will be made. Consider modifying the logic so that the journal file is copied only # once per Revit seesion. Perhaps copy it to the BatchRvt session folder. if False: try: snapshot_data_util.CopySnapshotRevitJournalFile( snapshotDataExportFolderPath, Output) except Exception, e: Output() Output( "WARNING: failed to copy the Revit session's journal file to snapshot data folder:" ) Output() Output("\t" + snapshotDataExportFolderPath) exception_util.LogOutputErrorDetails(e, Output)
if batchRvtConfig.RevitProcessingOption == BatchRvt.RevitProcessingOption.BatchRevitFileProcessing: aborted = RunBatchRevitTasks(batchRvtConfig) else: aborted = RunSingleRevitTask(batchRvtConfig) except Exception, e: sessionError = exception_util.GetExceptionDetails(e) raise finally: if batchRvtConfig.EnableDataExport: sessionEndTime = time_util.GetDateTimeNow() session_data_exporter.ExportSessionData( batchRvtConfig.SessionId, batchRvtConfig.SessionStartTime, sessionEndTime, batchRvtConfig.SessionDataFolderPath, sessionError) Output() if aborted: Output("Operation aborted.") else: Output("Operation completed.") Output() return try: Main() except Exception, e: exception_util.LogOutputErrorDetails(e, Output) raise