在Revit程序中注册文件操作事件,保存新建或打开文件的信息。当保存时,如果当前文件内容和之前的一致时,则弹出对话框提示并取消保存。对话框中有一个功能链接,点击可打开插件所在目录。
#region Namespaces using System; using System.Collections.Generic; using System.IO; using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Events; using Autodesk.Revit.UI; using Autodesk.RevitAddIns; #endregion namespace CancelSave { [Autodesk.Revit.Attributes.Transaction(TransactionMode.Manual)] [Autodesk.Revit.Attributes.Regeneration(RegenerationOption.Manual)] [Autodesk.Revit.Attributes.Journaling(JournalingMode.NoCommandData)] class App : IExternalApplication { const string thisAddinFileName = "CancelSave.addin"; Dictionary<int, string> documentOriginalStatusDic = new Dictionary<int, string>(); int hashcodeofCurrentClosingDoc; public Result OnStartup(UIControlledApplication a) { a.ControlledApplication.DocumentOpened += new EventHandler<DocumentOpenedEventArgs>(ReserveProjectOriginalStatus); a.ControlledApplication.DocumentCreated += new EventHandler<DocumentCreatedEventArgs>(ReserveProjectOriginalStatus); a.ControlledApplication.DocumentSaving += new EventHandler<DocumentSavingEventArgs>(CheckProjectStatusUpdate); a.ControlledApplication.DocumentSavingAs += new EventHandler<DocumentSavingAsEventArgs>(CheckProjectStatusUpdate); a.ControlledApplication.DocumentClosing += new EventHandler<DocumentClosingEventArgs>(MemClosingDocumentHashCode); a.ControlledApplication.DocumentClosed += new EventHandler<DocumentClosedEventArgs>(RemoveStatusofClosedDocument); return Result.Succeeded; } public Result OnShutdown(UIControlledApplication a) { a.ControlledApplication.DocumentOpened -= new EventHandler<DocumentOpenedEventArgs>(ReserveProjectOriginalStatus); a.ControlledApplication.DocumentCreated -= new EventHandler<DocumentCreatedEventArgs>(ReserveProjectOriginalStatus); a.ControlledApplication.DocumentSaving -= new EventHandler<DocumentSavingEventArgs>(CheckProjectStatusUpdate); a.ControlledApplication.DocumentSavingAs -= new EventHandler<DocumentSavingAsEventArgs>(CheckProjectStatusUpdate); LogManager.LogFinalize(); return Result.Succeeded; } private void ReserveProjectOriginalStatus(Object sender, RevitAPIPostDocEventArgs args) { Document doc = args.Document; if (doc.IsFamilyDocument) { return; } LogManager.WriteLog(args, doc); int docHashCode = doc.GetHashCode(); string currentProjectStatus = RetrieveProjectCurrentStatus(doc); documentOriginalStatusDic.Add(docHashCode, currentProjectStatus); LogManager.WriteLog(" Current Project Status: " + currentProjectStatus); } private void CheckProjectStatusUpdate(Object sender, RevitAPIPreDocEventArgs args) { Document doc = args.Document; if (doc.IsFamilyDocument) { return; } LogManager.WriteLog(args, doc); string currentProjectStatus = RetrieveProjectCurrentStatus(args.Document); string originalProjectStatus = documentOriginalStatusDic[doc.GetHashCode()]; LogManager.WriteLog(" Current Project Status: " + currentProjectStatus + "; Orignial Project Status: " + originalProjectStatus); if ((string.IsNullOrEmpty(currentProjectStatus) && string.IsNullOrEmpty(originalProjectStatus)) || (0 == string.Compare(currentProjectStatus, originalProjectStatus, true))) { DealNotUpdate(args); return; } documentOriginalStatusDic.Remove(doc.GetHashCode()); documentOriginalStatusDic.Add(doc.GetHashCode(), currentProjectStatus); } private void MemClosingDocumentHashCode(Object sender, DocumentClosingEventArgs args) { hashcodeofCurrentClosingDoc = args.Document.GetHashCode(); } private void RemoveStatusofClosedDocument(Object sender, DocumentClosedEventArgs args) { if (args.Status.Equals(RevitAPIEventStatus.Succeeded) && (documentOriginalStatusDic.ContainsKey(hashcodeofCurrentClosingDoc))) { documentOriginalStatusDic.Remove(hashcodeofCurrentClosingDoc); } } private static void DealNotUpdate(RevitAPIPreDocEventArgs args) { string mainMessage; string additionalText; TaskDialog taskDialog = new TaskDialog("CancelSave Sample"); if (args.Cancellable) { args.Cancel(); mainMessage = "CancelSave sample detected that the Project Status parameter on Project Info has not been updated. The file will not be saved."; // prompt to user. } else { // will not cancel this event since it isn't cancellable. mainMessage = "The file is about to save. But CancelSave sample detected that the Project Status parameter on Project Info has not been updated."; // prompt to user. } if (!LogManager.RegressionTestNow) { additionalText = "You can disable this permanently by uninstaling the CancelSave sample from Revit. Remove or rename CancelSave.addin from the addins directory."; taskDialog.MainInstruction = mainMessage; taskDialog.MainContent = additionalText; taskDialog.AddCommandLink(TaskDialogCommandLinkId.CommandLink1, "Open the addins directory"); taskDialog.CommonButtons = TaskDialogCommonButtons.Close; taskDialog.DefaultButton = TaskDialogResult.Close; TaskDialogResult tResult = taskDialog.Show(); if (TaskDialogResult.CommandLink1 == tResult) { System.Diagnostics.Process.Start("explorer.exe", DetectAddinFileLocation(args.Document.Application)); } } LogManager.WriteLog(" Project Status is not updated, taskDialog informs user: " + mainMessage); } private static string RetrieveProjectCurrentStatus(Document doc) { if (doc.IsFamilyDocument) { return null; } return doc.ProjectInformation.Status; } private static string DetectAddinFileLocation(Autodesk.Revit.ApplicationServices.Application application) { string addinFileFolderLocation = null; IList<RevitProduct> installedRevitList = RevitProductUtility.GetAllInstalledRevitProducts(); foreach (RevitProduct revit in installedRevitList) { if (revit.Version.ToString().Contains(application.VersionNumber)) { string allUsersAddInFolder = revit.AllUsersAddInFolder; string currentUserAddInFolder = revit.CurrentUserAddInFolder; if (File.Exists(Path.Combine(allUsersAddInFolder, thisAddinFileName))) { addinFileFolderLocation = allUsersAddInFolder; } else if (File.Exists(Path.Combine(currentUserAddInFolder, thisAddinFileName))) { addinFileFolderLocation = currentUserAddInFolder; } break; } } return addinFileFolderLocation; } } }
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using Autodesk.Revit.DB; namespace CancelSave { class LogManager { private static TextWriterTraceListener TxtListener; private static string AssemblyLocation = Path.GetDirectoryName( System.Reflection.Assembly.GetExecutingAssembly().Location); public static bool RegressionTestNow { get { string expectedLogFile = Path.Combine(AssemblyLocation, "ExpectedOutput.log"); if (File.Exists(expectedLogFile)) { return true; } return false; } } static LogManager() { string actullyLogFile = Path.Combine(AssemblyLocation, "CancelSave.log"); if (File.Exists(actullyLogFile)) { File.Delete(actullyLogFile); } TxtListener = new TextWriterTraceListener(actullyLogFile); Trace.Listeners.Add(TxtListener); Trace.AutoFlush = true; } public static void LogFinalize() { Trace.Flush(); TxtListener.Close(); Trace.Close(); Trace.Listeners.Remove(TxtListener); } public static void WriteLog(EventArgs args, Document doc) { Trace.WriteLine(""); Trace.WriteLine("[Event] " + GetEventName(args.GetType()) + ": " + TitleNoExt(doc.Title)); } public static void WriteLog(string message) { Trace.WriteLine(message); } private static string GetEventName(Type type) { string argName = type.ToString(); string tail = "EventArgs"; string head = "Autodesk.Revit.DB.Events."; int firstIndex = head.Length; int length = argName.Length - head.Length - tail.Length; string eventName = argName.Substring(firstIndex, length); return eventName; } private static string TitleNoExt(string orgTitle) { if (string.IsNullOrEmpty(orgTitle)) { return ""; } int pos = orgTitle.LastIndexOf('.'); if (-1 != pos) { return orgTitle.Remove(pos); } else { return orgTitle; } } } }