diff --git a/SampleLibrary/SampleLibrary.csproj b/SampleLibrary/SampleLibrary.csproj
index d82da80..f103af6 100644
--- a/SampleLibrary/SampleLibrary.csproj
+++ b/SampleLibrary/SampleLibrary.csproj
@@ -22,7 +22,7 @@
full
false
bin\Debug\
- DEBUG;TRACE
+ TRACE;DEBUG
prompt
4
@@ -34,6 +34,27 @@
prompt
4
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE,post2021
+ prompt
+ 4
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE,pre2021
+ prompt
+ 4
+
+
..\packages\ModPlus.Revit.API.2021.1.0.0\lib\AdWindows.dll
diff --git a/SampleLibrary/SampleTest.cs b/SampleLibrary/SampleTest.cs
index 48e0b0d..379c68d 100644
--- a/SampleLibrary/SampleTest.cs
+++ b/SampleLibrary/SampleTest.cs
@@ -34,8 +34,12 @@ namespace SampleLibrary
[Fact]
public void SampleFail()
{
- var feet = UnitUtils.ConvertToInternalUnits(3000, DisplayUnitType.DUT_MILLIMETERS);
- Assert.Equal(5, feet);
+#if pre2021
+ var feet = UnitUtils.ConvertToInternalUnits(3000, DisplayUnitType.DUT_MILLIMETERS);
+#else
+ var feet = UnitUtils.ConvertToInternalUnits(3000, UnitTypeId.Feet);
+#endif
+ Assert.Equal(5, feet);
}
[Fact]
@@ -60,12 +64,8 @@ namespace SampleLibrary
var wallFaceEdges = face.GetEdgesAsCurveLoops();
grossArea = ExporterIFCUtils.ComputeAreaOfCurveLoops(wallFaceEdges);
transaction.RollBack();
-
}
}, doc).Wait();
-
-
-
Assert.True(grossArea > 0);
}
diff --git a/SampleLibrary/TestWithFixture.cs b/SampleLibrary/TestWithFixture.cs
index 551a6f7..e469a77 100644
--- a/SampleLibrary/TestWithFixture.cs
+++ b/SampleLibrary/TestWithFixture.cs
@@ -47,9 +47,14 @@ namespace SampleLibrary
{
var wall = fixture.Doc.GetElement(new ElementId(346573));
var param = wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET);
- var baseOffset = UnitUtils.ConvertFromInternalUnits(param.AsDouble(), param.DisplayUnitType);
- Assert.Equal(2000, baseOffset);
+#if pre2021
+ var baseOffset = UnitUtils.ConvertFromInternalUnits(param.AsDouble(), param.DisplayUnitType);
+#else
+ var baseOffset = UnitUtils.ConvertFromInternalUnits(param.AsDouble(), param.GetUnitTypeId());
+#endif
+
+ Assert.Equal(2000, baseOffset);
}
[Fact]
@@ -62,8 +67,13 @@ namespace SampleLibrary
foreach(var wall in walls)
{
var param = wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET);
- var baseOffset = UnitUtils.ConvertToInternalUnits(2000, param.DisplayUnitType);
- param.Set(baseOffset);
+
+#if pre2021
+ var baseOffset = UnitUtils.ConvertToInternalUnits(2000, param.DisplayUnitType);
+#else
+ var baseOffset = UnitUtils.ConvertToInternalUnits(2000, param.GetUnitTypeId());
+#endif
+ param.Set(baseOffset);
}
}, fixture.Doc)
.Wait(); // Important! Wait for action to finish
@@ -71,8 +81,12 @@ namespace SampleLibrary
foreach (var wall in walls)
{
var param = wall.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET);
- var baseOffset = UnitUtils.ConvertFromInternalUnits(param.AsDouble(), param.DisplayUnitType);
- Assert.Equal(2000, baseOffset);
+#if pre2021
+ var baseOffset = UnitUtils.ConvertFromInternalUnits(param.AsDouble(), param.DisplayUnitType);
+#else
+ var baseOffset = UnitUtils.ConvertFromInternalUnits(param.AsDouble(), param.GetUnitTypeId());
+#endif
+ Assert.Equal(2000, baseOffset);
}
}
}
diff --git a/xUnitRevit.sln b/xUnitRevit.sln
index 9061394..3112c70 100644
--- a/xUnitRevit.sln
+++ b/xUnitRevit.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30011.22
+# Visual Studio Version 17
+VisualStudioVersion = 17.2.32630.192
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "xUnitRevit", "xUnitRevit\xUnitRevit.csproj", "{27A79ACA-7EA8-4406-8BB8-216578CC3AB7}"
EndProject
@@ -13,12 +13,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "xUnitRevitUtils2019", "xUni
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleLibrary", "SampleLibrary\SampleLibrary.csproj", "{C3A8684E-15BB-4B8B-B46C-35ACE3729C35}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "xUnitRevitUtils2023", "xUnitRevitUtils2023\xUnitRevitUtils2023.csproj", "{E0BF38C2-13BC-4ACC-B0F2-4DFE82965DB4}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "xUnitRevitUtils2022", "xUnitRevitUtils2022\xUnitRevitUtils2022.csproj", "{78770414-4F6B-4429-BD8F-F0F64A349551}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug2019|Any CPU = Debug2019|Any CPU
Debug2020|Any CPU = Debug2020|Any CPU
Debug2021|Any CPU = Debug2021|Any CPU
+ Debug2022|Any CPU = Debug2022|Any CPU
+ Debug2023|Any CPU = Debug2023|Any CPU
Release|Any CPU = Release|Any CPU
Release2019|Any CPU = Release2019|Any CPU
Release2020|Any CPU = Release2020|Any CPU
@@ -33,6 +39,10 @@ Global
{27A79ACA-7EA8-4406-8BB8-216578CC3AB7}.Debug2020|Any CPU.Build.0 = Debug2020|Any CPU
{27A79ACA-7EA8-4406-8BB8-216578CC3AB7}.Debug2021|Any CPU.ActiveCfg = Debug2021|Any CPU
{27A79ACA-7EA8-4406-8BB8-216578CC3AB7}.Debug2021|Any CPU.Build.0 = Debug2021|Any CPU
+ {27A79ACA-7EA8-4406-8BB8-216578CC3AB7}.Debug2022|Any CPU.ActiveCfg = Debug2022|Any CPU
+ {27A79ACA-7EA8-4406-8BB8-216578CC3AB7}.Debug2022|Any CPU.Build.0 = Debug2022|Any CPU
+ {27A79ACA-7EA8-4406-8BB8-216578CC3AB7}.Debug2023|Any CPU.ActiveCfg = Debug2023|Any CPU
+ {27A79ACA-7EA8-4406-8BB8-216578CC3AB7}.Debug2023|Any CPU.Build.0 = Debug2023|Any CPU
{27A79ACA-7EA8-4406-8BB8-216578CC3AB7}.Release|Any CPU.ActiveCfg = Release2021|Any CPU
{27A79ACA-7EA8-4406-8BB8-216578CC3AB7}.Release2019|Any CPU.ActiveCfg = Release2019|Any CPU
{27A79ACA-7EA8-4406-8BB8-216578CC3AB7}.Release2019|Any CPU.Build.0 = Release2019|Any CPU
@@ -46,6 +56,8 @@ Global
{977E0B63-5706-4C2B-9C01-3C02D9EBE377}.Debug2020|Any CPU.ActiveCfg = Debug|Any CPU
{977E0B63-5706-4C2B-9C01-3C02D9EBE377}.Debug2021|Any CPU.ActiveCfg = Debug|Any CPU
{977E0B63-5706-4C2B-9C01-3C02D9EBE377}.Debug2021|Any CPU.Build.0 = Debug|Any CPU
+ {977E0B63-5706-4C2B-9C01-3C02D9EBE377}.Debug2022|Any CPU.ActiveCfg = Debug|Any CPU
+ {977E0B63-5706-4C2B-9C01-3C02D9EBE377}.Debug2023|Any CPU.ActiveCfg = Debug|Any CPU
{977E0B63-5706-4C2B-9C01-3C02D9EBE377}.Release|Any CPU.ActiveCfg = Release|Any CPU
{977E0B63-5706-4C2B-9C01-3C02D9EBE377}.Release|Any CPU.Build.0 = Release|Any CPU
{977E0B63-5706-4C2B-9C01-3C02D9EBE377}.Release2019|Any CPU.ActiveCfg = Release|Any CPU
@@ -58,6 +70,8 @@ Global
{0DEF0F23-8AE2-461B-B014-8A0DA7494088}.Debug2020|Any CPU.ActiveCfg = Debug|Any CPU
{0DEF0F23-8AE2-461B-B014-8A0DA7494088}.Debug2020|Any CPU.Build.0 = Debug|Any CPU
{0DEF0F23-8AE2-461B-B014-8A0DA7494088}.Debug2021|Any CPU.ActiveCfg = Debug|Any CPU
+ {0DEF0F23-8AE2-461B-B014-8A0DA7494088}.Debug2022|Any CPU.ActiveCfg = Debug|Any CPU
+ {0DEF0F23-8AE2-461B-B014-8A0DA7494088}.Debug2023|Any CPU.ActiveCfg = Debug|Any CPU
{0DEF0F23-8AE2-461B-B014-8A0DA7494088}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0DEF0F23-8AE2-461B-B014-8A0DA7494088}.Release|Any CPU.Build.0 = Release|Any CPU
{0DEF0F23-8AE2-461B-B014-8A0DA7494088}.Release2019|Any CPU.ActiveCfg = Release|Any CPU
@@ -70,6 +84,10 @@ Global
{02399359-9CA0-4B47-B467-541E290E700F}.Debug2019|Any CPU.Build.0 = Debug|Any CPU
{02399359-9CA0-4B47-B467-541E290E700F}.Debug2020|Any CPU.ActiveCfg = Debug|Any CPU
{02399359-9CA0-4B47-B467-541E290E700F}.Debug2021|Any CPU.ActiveCfg = Debug|Any CPU
+ {02399359-9CA0-4B47-B467-541E290E700F}.Debug2022|Any CPU.ActiveCfg = Debug|Any CPU
+ {02399359-9CA0-4B47-B467-541E290E700F}.Debug2022|Any CPU.Build.0 = Debug|Any CPU
+ {02399359-9CA0-4B47-B467-541E290E700F}.Debug2023|Any CPU.ActiveCfg = Debug|Any CPU
+ {02399359-9CA0-4B47-B467-541E290E700F}.Debug2023|Any CPU.Build.0 = Debug|Any CPU
{02399359-9CA0-4B47-B467-541E290E700F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{02399359-9CA0-4B47-B467-541E290E700F}.Release|Any CPU.Build.0 = Release|Any CPU
{02399359-9CA0-4B47-B467-541E290E700F}.Release2019|Any CPU.ActiveCfg = Release|Any CPU
@@ -84,6 +102,10 @@ Global
{C3A8684E-15BB-4B8B-B46C-35ACE3729C35}.Debug2020|Any CPU.Build.0 = Debug|Any CPU
{C3A8684E-15BB-4B8B-B46C-35ACE3729C35}.Debug2021|Any CPU.ActiveCfg = Debug|Any CPU
{C3A8684E-15BB-4B8B-B46C-35ACE3729C35}.Debug2021|Any CPU.Build.0 = Debug|Any CPU
+ {C3A8684E-15BB-4B8B-B46C-35ACE3729C35}.Debug2022|Any CPU.ActiveCfg = Debug|Any CPU
+ {C3A8684E-15BB-4B8B-B46C-35ACE3729C35}.Debug2022|Any CPU.Build.0 = Debug|Any CPU
+ {C3A8684E-15BB-4B8B-B46C-35ACE3729C35}.Debug2023|Any CPU.ActiveCfg = Debug|Any CPU
+ {C3A8684E-15BB-4B8B-B46C-35ACE3729C35}.Debug2023|Any CPU.Build.0 = Debug|Any CPU
{C3A8684E-15BB-4B8B-B46C-35ACE3729C35}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3A8684E-15BB-4B8B-B46C-35ACE3729C35}.Release|Any CPU.Build.0 = Release|Any CPU
{C3A8684E-15BB-4B8B-B46C-35ACE3729C35}.Release2019|Any CPU.ActiveCfg = Release|Any CPU
@@ -92,6 +114,32 @@ Global
{C3A8684E-15BB-4B8B-B46C-35ACE3729C35}.Release2020|Any CPU.Build.0 = Release|Any CPU
{C3A8684E-15BB-4B8B-B46C-35ACE3729C35}.Release2021|Any CPU.ActiveCfg = Release|Any CPU
{C3A8684E-15BB-4B8B-B46C-35ACE3729C35}.Release2021|Any CPU.Build.0 = Release|Any CPU
+ {E0BF38C2-13BC-4ACC-B0F2-4DFE82965DB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E0BF38C2-13BC-4ACC-B0F2-4DFE82965DB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E0BF38C2-13BC-4ACC-B0F2-4DFE82965DB4}.Debug2019|Any CPU.ActiveCfg = Debug|Any CPU
+ {E0BF38C2-13BC-4ACC-B0F2-4DFE82965DB4}.Debug2020|Any CPU.ActiveCfg = Debug|Any CPU
+ {E0BF38C2-13BC-4ACC-B0F2-4DFE82965DB4}.Debug2021|Any CPU.ActiveCfg = Debug|Any CPU
+ {E0BF38C2-13BC-4ACC-B0F2-4DFE82965DB4}.Debug2022|Any CPU.ActiveCfg = Debug|Any CPU
+ {E0BF38C2-13BC-4ACC-B0F2-4DFE82965DB4}.Debug2023|Any CPU.ActiveCfg = Debug|Any CPU
+ {E0BF38C2-13BC-4ACC-B0F2-4DFE82965DB4}.Debug2023|Any CPU.Build.0 = Debug|Any CPU
+ {E0BF38C2-13BC-4ACC-B0F2-4DFE82965DB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E0BF38C2-13BC-4ACC-B0F2-4DFE82965DB4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E0BF38C2-13BC-4ACC-B0F2-4DFE82965DB4}.Release2019|Any CPU.ActiveCfg = Release|Any CPU
+ {E0BF38C2-13BC-4ACC-B0F2-4DFE82965DB4}.Release2020|Any CPU.ActiveCfg = Release|Any CPU
+ {E0BF38C2-13BC-4ACC-B0F2-4DFE82965DB4}.Release2021|Any CPU.ActiveCfg = Release|Any CPU
+ {78770414-4F6B-4429-BD8F-F0F64A349551}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {78770414-4F6B-4429-BD8F-F0F64A349551}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {78770414-4F6B-4429-BD8F-F0F64A349551}.Debug2019|Any CPU.ActiveCfg = Debug|Any CPU
+ {78770414-4F6B-4429-BD8F-F0F64A349551}.Debug2020|Any CPU.ActiveCfg = Debug|Any CPU
+ {78770414-4F6B-4429-BD8F-F0F64A349551}.Debug2021|Any CPU.ActiveCfg = Debug|Any CPU
+ {78770414-4F6B-4429-BD8F-F0F64A349551}.Debug2022|Any CPU.ActiveCfg = Debug|Any CPU
+ {78770414-4F6B-4429-BD8F-F0F64A349551}.Debug2022|Any CPU.Build.0 = Debug|Any CPU
+ {78770414-4F6B-4429-BD8F-F0F64A349551}.Debug2023|Any CPU.ActiveCfg = Debug|Any CPU
+ {78770414-4F6B-4429-BD8F-F0F64A349551}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {78770414-4F6B-4429-BD8F-F0F64A349551}.Release|Any CPU.Build.0 = Release|Any CPU
+ {78770414-4F6B-4429-BD8F-F0F64A349551}.Release2019|Any CPU.ActiveCfg = Release|Any CPU
+ {78770414-4F6B-4429-BD8F-F0F64A349551}.Release2020|Any CPU.ActiveCfg = Release|Any CPU
+ {78770414-4F6B-4429-BD8F-F0F64A349551}.Release2021|Any CPU.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/xUnitRevit/xUnitRevit.csproj b/xUnitRevit/xUnitRevit.csproj
index da47d28..67f8d1d 100644
--- a/xUnitRevit/xUnitRevit.csproj
+++ b/xUnitRevit/xUnitRevit.csproj
@@ -36,7 +36,7 @@
pdbonly
- true
+ false
bin\Release\
TRACE
prompt
@@ -60,7 +60,7 @@
pdbonly
- true
+ false
bin\Release\
TRACE
prompt
@@ -84,7 +84,7 @@
pdbonly
- true
+ false
bin\Release\
TRACE
prompt
@@ -93,6 +93,30 @@
$(ProgramW6432)\Autodesk\Revit 2019\Revit.exe
2019
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ Program
+ $(ProgramW6432)\Autodesk\Revit 2022\Revit.exe
+ 2022
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ Program
+ $(ProgramW6432)\Autodesk\Revit 2023\Revit.exe
+ 2023
+
@@ -113,12 +137,17 @@
-
- Always
-
Always
+
+ Always
+
+
@@ -165,6 +194,34 @@
+
+
+
+ 1.0.0
+ runtime
+
+
+
+
+ {78770414-4F6B-4429-BD8F-F0F64A349551}
+ xUnitRevitUtils2022
+
+
+
+
+
+
+ 1.0.0
+ runtime
+
+
+
+
+ {E0BF38C2-13BC-4ACC-B0F2-4DFE82965DB4}
+ xUnitRevitUtils2023
+
+
+
diff --git a/xUnitRevitUtils2022/xUnitRevitUtils2022.csproj b/xUnitRevitUtils2022/xUnitRevitUtils2022.csproj
new file mode 100644
index 0000000..63de3a5
--- /dev/null
+++ b/xUnitRevitUtils2022/xUnitRevitUtils2022.csproj
@@ -0,0 +1,27 @@
+
+
+
+ netstandard2.0
+ https://github.com/Speckle-Next/xunit-Revit
+ https://github.com/Speckle-Next/xunit-Revit
+ xunit revit runner
+ Speckle
+ Speckle
+ xUnit runner utilities for Revit 2021
+ https://avatars2.githubusercontent.com/u/2092016
+ xunit.png
+ MIT
+ true
+ xUnitRevitUtils
+ xUnitRevitUtils
+ xUnitRevitUtils.2021
+ 1.0.4
+ 1.0.4.0
+
+
+
+
+
+
+
+
diff --git a/xUnitRevitUtils2022/xUnitRevitUtils2022.nuspec b/xUnitRevitUtils2022/xUnitRevitUtils2022.nuspec
new file mode 100644
index 0000000..d628e16
--- /dev/null
+++ b/xUnitRevitUtils2022/xUnitRevitUtils2022.nuspec
@@ -0,0 +1,22 @@
+
+
+
+ xUnitRevitUtils.2023
+ $version$
+ $title$
+ $author$
+ $author$
+ false
+ MIT
+ https://github.com/Speckle-Next/xunit-Revit
+ https://avatars2.githubusercontent.com/u/2092016
+ $description$
+
+ Copyright 2022
+ xunit revit
+
+
+
+
+
+
diff --git a/xUnitRevitUtils2022/xru.cs b/xUnitRevitUtils2022/xru.cs
new file mode 100644
index 0000000..e24fb25
--- /dev/null
+++ b/xUnitRevitUtils2022/xru.cs
@@ -0,0 +1,191 @@
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Revit.UI.Selection;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace xUnitRevitUtils
+{
+ ///
+ /// Utility class with methods and properties used by the xUnit Revit plugin
+ ///
+ public static class xru
+ {
+ public static UIApplication Uiapp { get; set; }
+ private static List Queue { get; set; }
+ private static ExternalEvent EventHandler { get; set; }
+ public static SynchronizationContext UiContext { get; set; }
+ public static void Initialize(UIApplication uiapp, SynchronizationContext uiContext, ExternalEvent eventHandler, List queue)
+ {
+ Uiapp = uiapp;
+ UiContext = uiContext;
+ EventHandler = eventHandler;
+ Queue = queue;
+ }
+
+ #region utility methods
+
+
+ ///
+ /// Returns the selected elements in the active document
+ ///
+ ///
+ public static List GetActiveSelection()
+ {
+ Assert.NotNull(Uiapp);
+
+ if (Uiapp.ActiveUIDocument != null)
+ return Uiapp.ActiveUIDocument.Selection.GetElementIds().Select(x => Uiapp.ActiveUIDocument.Document.GetElement(x)).ToList();
+ return new List();
+ }
+ ///
+ /// Opens and activates a document if not open already
+ ///
+ /// Path to the file to open
+ public static Document OpenDoc(string filePath)
+ {
+ Assert.NotNull(Uiapp);
+ Document doc = null;
+ //OpenAndActivateDocument only works if run from the current context
+ UiContext.Send(x => { doc = Uiapp.OpenAndActivateDocument(filePath).Document; }, null);
+ Assert.NotNull(doc);
+ return doc;
+ }
+
+
+ ///
+ /// Creates a new empty document
+ ///
+ /// Path to the project template
+ /// Path where to save the new doc
+ /// If true overwrites existing files with same name
+ ///
+ public static Document CreateNewDoc(string templatePath, string filePath, bool overwrite = true)
+ {
+ Assert.NotNull(Uiapp);
+ Document doc = null;
+
+ try
+ {
+ if (overwrite && File.Exists(filePath))
+ File.Delete(filePath);
+ }
+ catch { }
+
+ //OpenAndActivateDocument only works if run from the current context
+ UiContext.Send(x =>
+ {
+ //if already open, just use it
+ if (!File.Exists(filePath))
+ {
+ doc = Uiapp.Application.NewProjectDocument(templatePath);
+ doc.SaveAs(filePath);
+ doc.Close();
+ }
+
+ doc = Uiapp.OpenAndActivateDocument(filePath).Document;
+ }
+ , null);
+ Assert.NotNull(doc);
+ return doc;
+ }
+
+
+ ///
+ /// Runs an Action in a Revit transaction, uses TaskCompletionSource to communicate when done
+ ///
+ /// Action to run
+ /// Revit Document
+ /// Transaction Name
+ /// Enable to swallow all warnings generated by the transaction and prevent them from being raised within Revit
+ ///
+ public static Task RunInTransaction(Action action, Document doc, string transactionName = "transaction", bool ignoreWarnings = false)
+ {
+ var tcs = new TaskCompletionSource();
+ Queue.Add(new Action(() =>
+ {
+ try
+ {
+ using (Transaction transaction = new Transaction(doc, transactionName))
+ {
+ transaction.Start();
+
+ if (ignoreWarnings)
+ {
+ var options = transaction.GetFailureHandlingOptions();
+ options.SetFailuresPreprocessor(new IgnoreAllWarnings());
+ transaction.SetFailureHandlingOptions(options);
+ }
+
+ action.Invoke();
+ transaction.Commit();
+ }
+ }
+ catch (Exception e)
+ {
+ tcs.TrySetException(e);
+ }
+ tcs.TrySetResult("");
+ }));
+
+ EventHandler.Raise();
+
+ return tcs.Task;
+
+ }
+
+ ///
+ /// Runs an Action, uses TaskCompletionSource to communicate when done
+ ///
+ /// Action to run
+ /// Revit Document
+ ///
+ public static Task Run(Action action, Document doc)
+ {
+ var tcs = new TaskCompletionSource();
+ Queue.Add(new Action(() =>
+ {
+ try
+ {
+ action.Invoke();
+ }
+ catch (Exception e)
+ {
+ tcs.TrySetException(e);
+ }
+ tcs.TrySetResult("");
+ }));
+
+ EventHandler.Raise();
+
+ return tcs.Task;
+
+ }
+
+ ///
+ /// A failures preprocesser that clears any failures that occur within a transaction
+ ///
+ internal class IgnoreAllWarnings : IFailuresPreprocessor
+ {
+ public FailureProcessingResult PreprocessFailures(FailuresAccessor failuresAccessor)
+ {
+ var failList = failuresAccessor.GetFailureMessages();
+
+ foreach (FailureMessageAccessor failure in failList)
+ {
+ failuresAccessor.DeleteWarning(failure);
+ }
+
+ return FailureProcessingResult.Continue;
+ }
+ }
+
+
+ #endregion
+ }
+}
diff --git a/xUnitRevitUtils2023/xUnitRevitUtils2023.csproj b/xUnitRevitUtils2023/xUnitRevitUtils2023.csproj
new file mode 100644
index 0000000..1123025
--- /dev/null
+++ b/xUnitRevitUtils2023/xUnitRevitUtils2023.csproj
@@ -0,0 +1,27 @@
+
+
+
+ netstandard2.0
+ https://github.com/Speckle-Next/xunit-Revit
+ https://github.com/Speckle-Next/xunit-Revit
+ xunit revit runner
+ Speckle
+ Speckle
+ xUnit runner utilities for Revit 2023
+ https://avatars2.githubusercontent.com/u/2092016
+ xunit.png
+ MIT
+ true
+ xUnitRevitUtils
+ xUnitRevitUtils
+ xUnitRevitUtils.2023
+ 1.0.4
+ 1.0.4.0
+
+
+
+
+
+
+
+
diff --git a/xUnitRevitUtils2023/xUnitRevitUtils2023.nuspec b/xUnitRevitUtils2023/xUnitRevitUtils2023.nuspec
new file mode 100644
index 0000000..d628e16
--- /dev/null
+++ b/xUnitRevitUtils2023/xUnitRevitUtils2023.nuspec
@@ -0,0 +1,22 @@
+
+
+
+ xUnitRevitUtils.2023
+ $version$
+ $title$
+ $author$
+ $author$
+ false
+ MIT
+ https://github.com/Speckle-Next/xunit-Revit
+ https://avatars2.githubusercontent.com/u/2092016
+ $description$
+
+ Copyright 2022
+ xunit revit
+
+
+
+
+
+
diff --git a/xUnitRevitUtils2023/xru.cs b/xUnitRevitUtils2023/xru.cs
new file mode 100644
index 0000000..e24fb25
--- /dev/null
+++ b/xUnitRevitUtils2023/xru.cs
@@ -0,0 +1,191 @@
+using Autodesk.Revit.DB;
+using Autodesk.Revit.UI;
+using Autodesk.Revit.UI.Selection;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace xUnitRevitUtils
+{
+ ///
+ /// Utility class with methods and properties used by the xUnit Revit plugin
+ ///
+ public static class xru
+ {
+ public static UIApplication Uiapp { get; set; }
+ private static List Queue { get; set; }
+ private static ExternalEvent EventHandler { get; set; }
+ public static SynchronizationContext UiContext { get; set; }
+ public static void Initialize(UIApplication uiapp, SynchronizationContext uiContext, ExternalEvent eventHandler, List queue)
+ {
+ Uiapp = uiapp;
+ UiContext = uiContext;
+ EventHandler = eventHandler;
+ Queue = queue;
+ }
+
+ #region utility methods
+
+
+ ///
+ /// Returns the selected elements in the active document
+ ///
+ ///
+ public static List GetActiveSelection()
+ {
+ Assert.NotNull(Uiapp);
+
+ if (Uiapp.ActiveUIDocument != null)
+ return Uiapp.ActiveUIDocument.Selection.GetElementIds().Select(x => Uiapp.ActiveUIDocument.Document.GetElement(x)).ToList();
+ return new List();
+ }
+ ///
+ /// Opens and activates a document if not open already
+ ///
+ /// Path to the file to open
+ public static Document OpenDoc(string filePath)
+ {
+ Assert.NotNull(Uiapp);
+ Document doc = null;
+ //OpenAndActivateDocument only works if run from the current context
+ UiContext.Send(x => { doc = Uiapp.OpenAndActivateDocument(filePath).Document; }, null);
+ Assert.NotNull(doc);
+ return doc;
+ }
+
+
+ ///
+ /// Creates a new empty document
+ ///
+ /// Path to the project template
+ /// Path where to save the new doc
+ /// If true overwrites existing files with same name
+ ///
+ public static Document CreateNewDoc(string templatePath, string filePath, bool overwrite = true)
+ {
+ Assert.NotNull(Uiapp);
+ Document doc = null;
+
+ try
+ {
+ if (overwrite && File.Exists(filePath))
+ File.Delete(filePath);
+ }
+ catch { }
+
+ //OpenAndActivateDocument only works if run from the current context
+ UiContext.Send(x =>
+ {
+ //if already open, just use it
+ if (!File.Exists(filePath))
+ {
+ doc = Uiapp.Application.NewProjectDocument(templatePath);
+ doc.SaveAs(filePath);
+ doc.Close();
+ }
+
+ doc = Uiapp.OpenAndActivateDocument(filePath).Document;
+ }
+ , null);
+ Assert.NotNull(doc);
+ return doc;
+ }
+
+
+ ///
+ /// Runs an Action in a Revit transaction, uses TaskCompletionSource to communicate when done
+ ///
+ /// Action to run
+ /// Revit Document
+ /// Transaction Name
+ /// Enable to swallow all warnings generated by the transaction and prevent them from being raised within Revit
+ ///
+ public static Task RunInTransaction(Action action, Document doc, string transactionName = "transaction", bool ignoreWarnings = false)
+ {
+ var tcs = new TaskCompletionSource();
+ Queue.Add(new Action(() =>
+ {
+ try
+ {
+ using (Transaction transaction = new Transaction(doc, transactionName))
+ {
+ transaction.Start();
+
+ if (ignoreWarnings)
+ {
+ var options = transaction.GetFailureHandlingOptions();
+ options.SetFailuresPreprocessor(new IgnoreAllWarnings());
+ transaction.SetFailureHandlingOptions(options);
+ }
+
+ action.Invoke();
+ transaction.Commit();
+ }
+ }
+ catch (Exception e)
+ {
+ tcs.TrySetException(e);
+ }
+ tcs.TrySetResult("");
+ }));
+
+ EventHandler.Raise();
+
+ return tcs.Task;
+
+ }
+
+ ///
+ /// Runs an Action, uses TaskCompletionSource to communicate when done
+ ///
+ /// Action to run
+ /// Revit Document
+ ///
+ public static Task Run(Action action, Document doc)
+ {
+ var tcs = new TaskCompletionSource();
+ Queue.Add(new Action(() =>
+ {
+ try
+ {
+ action.Invoke();
+ }
+ catch (Exception e)
+ {
+ tcs.TrySetException(e);
+ }
+ tcs.TrySetResult("");
+ }));
+
+ EventHandler.Raise();
+
+ return tcs.Task;
+
+ }
+
+ ///
+ /// A failures preprocesser that clears any failures that occur within a transaction
+ ///
+ internal class IgnoreAllWarnings : IFailuresPreprocessor
+ {
+ public FailureProcessingResult PreprocessFailures(FailuresAccessor failuresAccessor)
+ {
+ var failList = failuresAccessor.GetFailureMessages();
+
+ foreach (FailureMessageAccessor failure in failList)
+ {
+ failuresAccessor.DeleteWarning(failure);
+ }
+
+ return FailureProcessingResult.Continue;
+ }
+ }
+
+
+ #endregion
+ }
+}