diff --git a/FemDesign.Core/Properties/GlobalAssemblyInfo.cs b/FemDesign.Core/Properties/GlobalAssemblyInfo.cs
index a395682f7..1c658be6c 100644
--- a/FemDesign.Core/Properties/GlobalAssemblyInfo.cs
+++ b/FemDesign.Core/Properties/GlobalAssemblyInfo.cs
@@ -23,5 +23,5 @@
// Revision
//
-[assembly: AssemblyVersion("25.0.0")]
-[assembly: AssemblyFileVersion("25.0.0")]
+[assembly: AssemblyVersion("25.1.0")]
+[assembly: AssemblyFileVersion("25.1.0")]
diff --git a/FemDesign.Grasshopper/FemDesign.Grasshopper.csproj b/FemDesign.Grasshopper/FemDesign.Grasshopper.csproj
index 99fff21f6..10d2a486e 100644
--- a/FemDesign.Grasshopper/FemDesign.Grasshopper.csproj
+++ b/FemDesign.Grasshopper/FemDesign.Grasshopper.csproj
@@ -9,6 +9,7 @@
v4.8
512
+ true
@@ -61,6 +62,9 @@
+
+ ..\packages\System.Resources.Extensions.8.0.0\lib\net462\System.Resources.Extensions.dll
+
@@ -232,6 +236,7 @@
+
diff --git a/FemDesign.Grasshopper/Helpers/FemDesignConnectionHub.cs b/FemDesign.Grasshopper/Helpers/FemDesignConnectionHub.cs
index a2683bde4..69f10368b 100644
--- a/FemDesign.Grasshopper/Helpers/FemDesignConnectionHub.cs
+++ b/FemDesign.Grasshopper/Helpers/FemDesignConnectionHub.cs
@@ -1,6 +1,7 @@
// https://strusoft.com/
using System;
using System.Collections.Concurrent;
+using System.Runtime.ExceptionServices;
using System.Threading;
using System.Threading.Tasks;
@@ -28,9 +29,30 @@ public static Guid Create(string fdDir, bool minimized, string outputDir = null,
{
var id = Guid.NewGuid();
var inst = new Instance();
+ var initialized = new ManualResetEventSlim(false);
+ Exception startupException = null;
+
inst.WorkerThread = new Thread(() =>
{
- inst.Connection = new FemDesign.FemDesignConnection(fdDir, minimized, outputDir: outputDir, tempOutputDir: deleteOutput);
+ try
+ {
+ inst.Connection = new FemDesign.FemDesignConnection(fdDir, minimized, outputDir: outputDir, tempOutputDir: deleteOutput);
+ }
+ catch (Exception ex)
+ {
+ startupException = ex;
+ }
+ finally
+ {
+ initialized.Set();
+ }
+
+ if (inst.Connection == null)
+ {
+ inst.Queue.CompleteAdding();
+ return;
+ }
+
foreach (var action in inst.Queue.GetConsumingEnumerable())
{
try { action(); }
@@ -45,6 +67,15 @@ public static Guid Create(string fdDir, bool minimized, string outputDir = null,
throw new InvalidOperationException("Failed to create FemDesign connection instance.");
inst.WorkerThread.Start();
+ initialized.Wait();
+
+ if (startupException != null)
+ {
+ _instances.TryRemove(id, out _);
+ inst.Queue.Dispose();
+ ExceptionDispatchInfo.Capture(startupException).Throw();
+ }
+
return id;
}
diff --git a/FemDesign.Grasshopper/Pipe/FemDesignConnectionComponent.cs b/FemDesign.Grasshopper/Pipe/FemDesignConnectionComponent.cs
index 43ae9d596..f2b754aa3 100644
--- a/FemDesign.Grasshopper/Pipe/FemDesignConnectionComponent.cs
+++ b/FemDesign.Grasshopper/Pipe/FemDesignConnectionComponent.cs
@@ -74,11 +74,20 @@ protected override void SolveInstance(IGH_DataAccess DA)
System.IO.Directory.SetCurrentDirectory(currentDir);
}
- CloseConnection();
- _handle = FemDesignConnectionHub.Create(fdDir, minimized, outputDir, deleteOutput);
+ try
+ {
+ CloseConnection();
+ _handle = FemDesignConnectionHub.Create(fdDir, minimized, outputDir, deleteOutput);
- // Emit a handle object to wire downstream
- DA.SetData("Connection", new FemDesign.Grasshopper.FemDesignHubHandle(_handle));
+ // Emit a handle object to wire downstream
+ DA.SetData("Connection", new FemDesign.Grasshopper.FemDesignHubHandle(_handle));
+ }
+ catch (Exception ex)
+ {
+ _handle = Guid.Empty;
+ AddRuntimeMessage(GH_RuntimeMessageLevel.Error, ex.Message);
+ DA.SetData("Connection", null);
+ }
}
private void CloseConnection()
@@ -102,7 +111,7 @@ public override void RemovedFromDocument(GH_Document document)
}
protected override System.Drawing.Bitmap Icon => FemDesign.Properties.Resources.FEM_Connection;
- public override Guid ComponentGuid => new Guid("{CBDD03EE-9F56-42FC-AA8D-7C45C152EF1C}");
+ public override Guid ComponentGuid => new Guid("{A3F7B2D1-E4C8-4A6F-9D3E-1B5C7F8A2E09}");
public override GH_Exposure Exposure => GH_Exposure.primary;
}
}
diff --git a/FemDesign.Grasshopper/Pipe/OBSOLETE/FemDesignConnectionComponent_OBSOLETE2500.cs b/FemDesign.Grasshopper/Pipe/OBSOLETE/FemDesignConnectionComponent_OBSOLETE2500.cs
new file mode 100644
index 000000000..f909a56ff
--- /dev/null
+++ b/FemDesign.Grasshopper/Pipe/OBSOLETE/FemDesignConnectionComponent_OBSOLETE2500.cs
@@ -0,0 +1,109 @@
+// https://strusoft.com/
+using System;
+using System.Collections.Generic;
+using Grasshopper;
+using Grasshopper.Kernel;
+
+namespace FemDesign.Grasshopper
+{
+ ///
+ /// Configures the shared FemDesignConnectionHub and exposes a lightweight handle.
+ ///
+ public class FemDesignConnectionComponent_OBSOLETE2500: FEM_Design_API_Component
+ {
+ private Guid _handle = Guid.Empty;
+ public FemDesignConnectionComponent_OBSOLETE2500() : base("FEM-Design.Connection", "Connection", "Create or configure a shared FEM-Design connection. Use it to specify the 'Connection' for the LiveLink components.\n\n" +
+ "Note: Removing this component will automatically close the FEM-Design window. To keep FEM-Design open after closing the connection, use the 'Disconnect' component.", CategoryName.Name(), SubCategoryName.Cat8())
+ {
+ ObjectChanged += FemDesignConnectionComponent_ObjectChanged;
+ }
+
+ private void FemDesignConnectionComponent_ObjectChanged(object sender, GH_ObjectChangedEventArgs e)
+ {
+ if (e.Type is GH_ObjectEventType.Enabled)
+ {
+ CloseConnection();
+ }
+ }
+
+ protected override void RegisterInputParams(GH_InputParamManager pManager)
+ {
+ pManager.AddTextParameter("FEM-Design dir", "FEM-Design dir", "Path to the FEM-Design installation directory.", GH_ParamAccess.item, @"C:\\Program Files\\StruSoft\\FEM-Design 25\\");
+ pManager[pManager.ParamCount - 1].Optional = true;
+
+ pManager.AddBooleanParameter("Minimized", "Minimized", "If true, FEM-Design window will open in a minimised mode.", GH_ParamAccess.item, false);
+ pManager[pManager.ParamCount - 1].Optional = true;
+
+ pManager.AddTextParameter("OutputDir", "OutputDir", "The directory where the script, log and result files will be saved. By default, the files will be written to the same directory as your .gh script.", GH_ParamAccess.item);
+ pManager[pManager.ParamCount - 1].Optional = true;
+
+ pManager.AddBooleanParameter("DeleteOutputFolder", "DeleteOutputFolder", "Delete output directory on disconnect.", GH_ParamAccess.item, false);
+ pManager[pManager.ParamCount - 1].Optional = true;
+ }
+
+ protected override void RegisterOutputParams(GH_OutputParamManager pManager)
+ {
+ pManager.AddGenericParameter("Connection", "Connection", "Shared FEM-Design connection handle.", GH_ParamAccess.item);
+ }
+
+ protected override void SolveInstance(IGH_DataAccess DA)
+ {
+ string fdDir = @"C:\\Program Files\\StruSoft\\FEM-Design 25\\";
+ DA.GetData("FEM-Design dir", ref fdDir);
+
+ bool minimized = false;
+ DA.GetData("Minimized", ref minimized);
+
+ string outputDir = null;
+ DA.GetData("OutputDir", ref outputDir);
+
+ bool deleteOutput = false;
+ DA.GetData("DeleteOutputFolder", ref deleteOutput);
+
+ // Set working directory similarly to existing component behavior
+ bool fileExist = OnPingDocument().IsFilePathDefined;
+ if (!fileExist)
+ {
+ string tempPath = System.IO.Path.GetTempPath();
+ System.IO.Directory.SetCurrentDirectory(tempPath);
+ }
+ else
+ {
+ var filePath = OnPingDocument().FilePath;
+ var currentDir = System.IO.Path.GetDirectoryName(filePath);
+ System.IO.Directory.SetCurrentDirectory(currentDir);
+ }
+
+ CloseConnection();
+ _handle = FemDesignConnectionHub.Create(fdDir, minimized, outputDir, deleteOutput);
+
+ // Emit a handle object to wire downstream
+ DA.SetData("Connection", new FemDesign.Grasshopper.FemDesignHubHandle(_handle));
+ }
+
+ private void CloseConnection()
+ {
+ if (_handle != Guid.Empty)
+ {
+ FemDesignConnectionHub.DisposeAsync(_handle).GetAwaiter().GetResult();
+ _handle = Guid.Empty;
+ }
+ }
+
+ public override void RemovedFromDocument(GH_Document document)
+ {
+ try
+ {
+ CloseConnection();
+ }
+ catch { }
+
+ base.RemovedFromDocument(document);
+ }
+
+ protected override System.Drawing.Bitmap Icon => FemDesign.Properties.Resources.FEM_Connection;
+ public override Guid ComponentGuid => new Guid("{CBDD03EE-9F56-42FC-AA8D-7C45C152EF1C}");
+ public override GH_Exposure Exposure => GH_Exposure.hidden;
+ }
+}
+
diff --git a/FemDesign.Grasshopper/packages.config b/FemDesign.Grasshopper/packages.config
index 8f67b3d0e..78e746087 100644
--- a/FemDesign.Grasshopper/packages.config
+++ b/FemDesign.Grasshopper/packages.config
@@ -3,4 +3,5 @@
+
\ No newline at end of file
diff --git a/FemDesign.Tests/Results/Assets/General.str b/FemDesign.Tests/Results/Assets/General.str
index f5696b058..568b15aa0 100644
Binary files a/FemDesign.Tests/Results/Assets/General.str and b/FemDesign.Tests/Results/Assets/General.str differ
diff --git a/FemDesign.Tests/Results/Assets/General.strFEM b/FemDesign.Tests/Results/Assets/General.strFEM
index dae27badc..871e5bde9 100644
Binary files a/FemDesign.Tests/Results/Assets/General.strFEM and b/FemDesign.Tests/Results/Assets/General.strFEM differ
diff --git a/FemDesign.Tests/Sections/SectionDatabaseTests.cs b/FemDesign.Tests/Sections/SectionDatabaseTests.cs
index 66c666514..4bffb0cfb 100644
--- a/FemDesign.Tests/Sections/SectionDatabaseTests.cs
+++ b/FemDesign.Tests/Sections/SectionDatabaseTests.cs
@@ -34,9 +34,8 @@ public void GetDefaultTest()
}
- [TestMethod("SectionDatabase - Fuzzy search")]
[TestCategory("FEM-Design required")]
-
+ [TestMethod("Fuzzy Search")]
public void TestFuzzySearch()
{
var db = SectionDatabase.GetDefault();