Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat : R25 Support Unload Assembly #54

Merged
merged 8 commits into from
May 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions AddInManager.sln
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RevitElementBipChecker", "RevitElementBipChecker\RevitElementBipChecker.csproj", "{21460D85-C4AD-49D5-963F-CF13C4AE99EB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test2", "Test2\Test2.csproj", "{DA609427-F086-4C79-A5FA-202DBB5DE48D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug R22|Any CPU = Debug R22|Any CPU
Debug R23|Any CPU = Debug R23|Any CPU
Debug R24|Any CPU = Debug R24|Any CPU
Debug R25|Any CPU = Debug R25|Any CPU
Installer|Any CPU = Installer|Any CPU
Release R19|Any CPU = Release R19|Any CPU
Release R20|Any CPU = Release R20|Any CPU
Expand Down Expand Up @@ -55,6 +58,8 @@ Global
{C872CDA2-93F5-4681-BD2F-207EACF83D2E}.Release R24|Any CPU.Build.0 = Release R24|Any CPU
{C872CDA2-93F5-4681-BD2F-207EACF83D2E}.Release R25|Any CPU.ActiveCfg = Release R25|Any CPU
{C872CDA2-93F5-4681-BD2F-207EACF83D2E}.Release R25|Any CPU.Build.0 = Release R25|Any CPU
{C872CDA2-93F5-4681-BD2F-207EACF83D2E}.Debug R25|Any CPU.ActiveCfg = Debug R25|Any CPU
{C872CDA2-93F5-4681-BD2F-207EACF83D2E}.Debug R25|Any CPU.Build.0 = Debug R25|Any CPU
{E3C87D34-638C-47A0-A73A-D967B119458D}.Debug R22|Any CPU.ActiveCfg = Debug|Any CPU
{E3C87D34-638C-47A0-A73A-D967B119458D}.Debug R23|Any CPU.ActiveCfg = Debug|Any CPU
{E3C87D34-638C-47A0-A73A-D967B119458D}.Debug R24|Any CPU.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -90,6 +95,9 @@ Global
{1661572C-EF3A-4DD6-83BD-CB4239CE8CDD}.Release R23|Any CPU.ActiveCfg = Release R23|Any CPU
{1661572C-EF3A-4DD6-83BD-CB4239CE8CDD}.Release R24|Any CPU.ActiveCfg = Release R24|Any CPU
{1661572C-EF3A-4DD6-83BD-CB4239CE8CDD}.Release R25|Any CPU.ActiveCfg = Release R25|Any CPU
{1661572C-EF3A-4DD6-83BD-CB4239CE8CDD}.Release R25|Any CPU.Build.0 = Release R25|Any CPU
{1661572C-EF3A-4DD6-83BD-CB4239CE8CDD}.Debug R25|Any CPU.ActiveCfg = Release R25|Any CPU
{1661572C-EF3A-4DD6-83BD-CB4239CE8CDD}.Debug R25|Any CPU.Build.0 = Release R25|Any CPU
{21460D85-C4AD-49D5-963F-CF13C4AE99EB}.Debug R22|Any CPU.ActiveCfg = Debug R22|Any CPU
{21460D85-C4AD-49D5-963F-CF13C4AE99EB}.Debug R22|Any CPU.Build.0 = Debug R22|Any CPU
{21460D85-C4AD-49D5-963F-CF13C4AE99EB}.Installer|Any CPU.ActiveCfg = Debug R22|Any CPU
Expand All @@ -112,6 +120,8 @@ Global
{21460D85-C4AD-49D5-963F-CF13C4AE99EB}.Release R24|Any CPU.Build.0 = Release R24|Any CPU
{21460D85-C4AD-49D5-963F-CF13C4AE99EB}.Release R25|Any CPU.ActiveCfg = Release R25|Any CPU
{21460D85-C4AD-49D5-963F-CF13C4AE99EB}.Release R25|Any CPU.Build.0 = Release R25|Any CPU
{21460D85-C4AD-49D5-963F-CF13C4AE99EB}.Debug R25|Any CPU.ActiveCfg = Release R25|Any CPU
{21460D85-C4AD-49D5-963F-CF13C4AE99EB}.Debug R25|Any CPU.Build.0 = Release R25|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
59 changes: 58 additions & 1 deletion AddInManager/Command/AddinManagerBase.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
using System.IO;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using RevitAddinManager.Model;
using RevitAddinManager.ViewModel;
using System.Windows;
using static RevitAddinManager.App;

#if R25
using AssemblyLoadContext = RevitAddinManager.Model.AssemblyLoadContext;
using System.Runtime.Loader;
#endif

namespace RevitAddinManager.Command;

public sealed class AddinManagerBase
Expand All @@ -16,7 +23,12 @@ public Result ExecuteCommand(ExternalCommandData data, ref string message, Eleme
var vm = new AddInManagerViewModel(data, ref message, elements);
if (_activeCmd != null && faceless)
{
#if R19 || R20 || R21 || R22 || R23 || R24
return RunActiveCommand(vm, data, ref message, elements);
#else
return RunActiveCommand(data, ref message, elements);
#endif

}
FrmAddInManager = new View.FrmAddInManager(vm);
FrmAddInManager.SetRevitAsWindowOwner();
Expand Down Expand Up @@ -75,6 +87,51 @@ public Result RunActiveCommand(AddInManagerViewModel vm, ExternalCommandData dat
return result;
}

#if R25
public Result RunActiveCommand(ExternalCommandData data, ref string message, ElementSet elements)
{
var filePath = _activeCmd.FilePath;
if (!File.Exists(filePath))
{
MessageBox.Show("File not found: " + filePath,DefaultSetting.AppName, MessageBoxButton.OK, MessageBoxImage.Error);
return 0;
}
Result result = Result.Failed;
var alc = new AssemblyLoadContext(filePath);
try
{
var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
Assembly assembly = alc.LoadFromStream(stream);
object instance = assembly.CreateInstance(_activeCmdItem.FullClassName);
WeakReference alcWeakRef = new WeakReference(alc, trackResurrection: true);
if (instance is IExternalCommand externalCommand)
{
_activeEc = externalCommand;
result = _activeEc.Execute(data, ref message, elements);
alc.Unload();
}
int counter = 0;
for (counter = 0; alcWeakRef.IsAlive && (counter < 10); counter++)
{
alc = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
stream.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
result = Result.Failed;
}
finally
{
alc = null;
}
return result;
}
#endif

public static AddinManagerBase Instance
{
get
Expand Down
48 changes: 48 additions & 0 deletions AddInManager/Model/AssemblyLoadContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#if R25
using System.IO;
using System.Reflection;
using System.Runtime.Loader;

namespace RevitAddinManager.Model;

class AssemblyLoadContext : System.Runtime.Loader.AssemblyLoadContext
{
public AssemblyLoadContext() : base(isCollectible: true)
{
}
private AssemblyDependencyResolver _resolver;

public AssemblyLoadContext(string pluginPath): base(isCollectible: true)
{
_resolver = new AssemblyDependencyResolver(pluginPath);
}

protected override Assembly Load(AssemblyName assemblyName)
{
string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
if (assemblyPath != null)
{
if(assemblyPath.Contains("RevitAPI"))
{
return null;
}
var stream = new FileStream(assemblyPath, FileMode.Open, FileAccess.Read);
return LoadFromStream(stream);
}

return null;
}

protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
{
string libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
if (libraryPath != null)
{
return LoadUnmanagedDllFromPath(libraryPath);
}

return IntPtr.Zero;
}

}
#endif
4 changes: 4 additions & 0 deletions AddInManager/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
"commandName": "Executable",
"executablePath": "C:\\Program Files\\Autodesk\\Revit 2024\\Revit.exe"
} ,
"Revit2025": {
"commandName": "Executable",
"executablePath": "C:\\Program Files\\Autodesk\\Revit 2025\\Revit.exe"
} ,
"RevitPreview": {
"commandName": "Executable",
"executablePath": "C:\\Program Files\\Autodesk\\Revit Preview Release\\Revit.exe"
Expand Down
9 changes: 7 additions & 2 deletions AddInManager/RevitAddinManager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<PlatformTarget>x64</PlatformTarget>
<ImplicitUsings>true</ImplicitUsings>
<UseWindowsForms>false</UseWindowsForms>
<Configurations>Debug R22;Debug R23;Debug R24</Configurations>
<Configurations>Debug R22;Debug R23;Debug R24;Debug R25</Configurations>
<Configurations>$(Configurations);Release R25;Release R19;Release R20;Release R21;Release R22;Release R23;Release R24</Configurations>
</PropertyGroup>
<PropertyGroup Condition="$(Configuration.Contains('Debug'))">
Expand Down Expand Up @@ -52,6 +52,7 @@
<RevitVersion>2025</RevitVersion>
<DefineConstants>$(DefineConstants);R25</DefineConstants>
<TargetFramework>net8.0-windows</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
</PropertyGroup>
<PropertyGroup>
<Version>$(RevitVersion)</Version>
Expand Down Expand Up @@ -129,7 +130,11 @@
<ItemGroup>
<ProjectReference Include="..\RevitElementBipChecker\RevitElementBipChecker.csproj" />
</ItemGroup>

<PropertyGroup>
<StartAction>Program</StartAction>
<StartProgram>C:\Program Files\Autodesk\Revit $(RevitVersion)\Revit.exe</StartProgram>
<StartArguments>/language ENG</StartArguments>
</PropertyGroup>
<Target Name="CopyFiles" AfterTargets="CoreBuild">
<ItemGroup>
<RootItem Include="$(ProjectDir)*.addin" />
Expand Down
4 changes: 4 additions & 0 deletions AddInManager/ViewModel/AddInManagerViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,11 @@ public void ExecuteAddinCommandClick()
private void Execute()
{
string message = Message;
#if R19 || R20 || R21 || R22 || R23 || R24
MAddinManagerBase.RunActiveCommand(this, ExternalCommandData, ref message, Elements);
#else
MAddinManagerBase.RunActiveCommand(ExternalCommandData, ref message, Elements);
#endif
}

private void OpenLcAssemblyCommandClick()
Expand Down
8 changes: 7 additions & 1 deletion Test/Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
<LangVersion>latest</LangVersion>
<IsPackable>false</IsPackable>
<PlatformTarget>x64</PlatformTarget>
<Configurations>Debug R21;Debug R22;Debug R23;Debug R24;</Configurations>
<UseWpf>true</UseWpf>
<Configurations>Debug R21;Debug R22;Debug R23;Debug R24;Debug R25;</Configurations>
<Configurations>$(Configurations)Release R25;Release R19;Release R20;Release R21;Release R22;Release R23;Release R24</Configurations>
</PropertyGroup>
<PropertyGroup Condition="$(Configuration.Contains('R19'))">
Expand Down Expand Up @@ -35,6 +36,8 @@
</PropertyGroup>
<PropertyGroup Condition="$(Configuration.Contains('R25'))">
<RevitVersion>2025</RevitVersion>
<TargetFramework>net8.0-windows</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<DefineConstants>$(DefineConstants);R25</DefineConstants>
</PropertyGroup>
<PropertyGroup>
Expand All @@ -54,5 +57,8 @@
<ItemGroup>
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Test2\Test2.csproj" />
</ItemGroup>

</Project>
6 changes: 1 addition & 5 deletions Test/TestCommand.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Interop;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
Expand Down Expand Up @@ -166,7 +162,7 @@ public Result Execute(ExternalCommandData commandData, ref string message, Eleme
Debug.WriteLine($"Add: This is a add");
Debug.WriteLine($"Modify: This is a modify");
Debug.WriteLine($"Delete: This is a delete");
TraceListenerCollection traceListenerCollection = Debug.Listeners;
TraceListenerCollection traceListenerCollection = Trace.Listeners;
return Result.Succeeded;
}
}
Expand Down
11 changes: 7 additions & 4 deletions Test/TestEvaCommand.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Windows;
using System;
using System.Windows;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Test2;

namespace Test;

Expand All @@ -10,9 +12,10 @@ public class TestEvaCommand : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{

UIApplication uiApplication = commandData.Application;
MessageBox.Show(uiApplication.Application.Username);
MessageBox.Show("TestEvaCommand");
// string? value = DependLib.ShowDialogFolder();
// Console.WriteLine(value);
// MessageBox.Show(value.ToString());
return Result.Succeeded;
}
}
24 changes: 24 additions & 0 deletions Test2/DependLib.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace Test2
{
public static class DependLib
{
public static double Plus()
{
return 2 + 10;
}

public static string? ShowDialogFolder()
{
//ookii-dialogs-wpf
var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog();
dialog.Description = "Select a folder";
dialog.UseDescriptionForTitle = true;
dialog.ShowNewFolderButton = true;
if (dialog.ShowDialog() == true)
{
return dialog.SelectedPath;
}
return null;
}
}
}
39 changes: 39 additions & 0 deletions Test2/Test2.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<PlatformTarget>x64</PlatformTarget>
<UseWpf>true</UseWpf>
</PropertyGroup>
<PropertyGroup Condition="$(Configuration.Contains('Debug'))">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<DefineConstants>$(DefineConstants);DEBUG</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="$(Configuration.Contains('Release'))">
<Optimize>true</Optimize>
<DebugType>none</DebugType>
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
</PropertyGroup>
<PropertyGroup>
<Version>$(RevitVersion)</Version>
<EnableDynamicLoading>true</EnableDynamicLoading>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<Description>A Project Support for developer in revit </Description>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.7" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.7" />
<PackageReference Include="coverlet.collector" Version="3.1.0" />
<PackageReference Include="Chuongmep.Revit.Api.RevitAPI" Version="$(RevitVersion).*" />
<PackageReference Include="Chuongmep.Revit.Api.RevitAPIUI" Version="$(RevitVersion).*" />
<PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />
</ItemGroup>
<ItemGroup>
<Reference Include="PresentationFramework" />
</ItemGroup>

</Project>
5 changes: 4 additions & 1 deletion build/Build.csproj.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ANONYMOUSMETHOD_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=4a98fdf6_002D7d98_002D4f5a_002Dafeb_002Dea44ad98c70c/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="FIELD" /&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=f9fce829_002De6f4_002D4cb2_002D80f1_002D5497c44f51df/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
Expand All @@ -25,4 +27,5 @@
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
Loading