diff --git a/src/PSOPNSenseAPI/Cmdlets/ConnectOPNSenseTailscaleCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/ConnectOPNSenseTailscaleCmdlet.cs
index 0e5fd4b..60b5d7c 100644
--- a/src/PSOPNSenseAPI/Cmdlets/ConnectOPNSenseTailscaleCmdlet.cs
+++ b/src/PSOPNSenseAPI/Cmdlets/ConnectOPNSenseTailscaleCmdlet.cs
@@ -76,178 +76,213 @@ namespace PSOPNSenseAPI.Cmdlets
///
/// Processes the cmdlet
///
- protected override void ProcessRecord()
+ protected override void ProcessRecordInternal()
{
- try
+ var tailscaleService = new TailscaleService(ApiClient, Logger);
+
+ // Check if the plugin is installed
+ var isInstalled = ExecuteAsyncTask(() => tailscaleService.IsPluginInstalledAsync());
+
+ // Only continue if no exception occurred
+ if (ProcessingException != null)
{
- var tailscaleService = new TailscaleService(ApiClient, Logger);
+ return;
+ }
- // Check if the plugin is installed
- var isInstalledTask = Task.Run(async () => await tailscaleService.IsPluginInstalledAsync());
- var isInstalled = isInstalledTask.GetAwaiter().GetResult();
-
- if (!isInstalled)
+ if (!isInstalled)
+ {
+ if (!InstallIfMissing.IsPresent)
{
- if (!InstallIfMissing.IsPresent)
- {
- WriteError(new ErrorRecord(
- new Exception("Tailscale plugin is not installed. Use -InstallIfMissing to install it."),
- "TailscalePluginNotInstalled",
- ErrorCategory.InvalidOperation,
- null));
- return;
- }
-
- if (!Force.IsPresent && !ShouldProcess("OPNSense firewall", "Install Tailscale plugin"))
- {
- return;
- }
-
- WriteVerbose("Tailscale plugin is not installed. Installing...");
- var installTask = Task.Run(async () => await tailscaleService.InstallPluginAsync());
- var installResult = installTask.GetAwaiter().GetResult();
-
- if (!installResult)
- {
- WriteError(new ErrorRecord(
- new Exception("Failed to install Tailscale plugin."),
- "TailscalePluginInstallFailed",
- ErrorCategory.InvalidOperation,
- null));
- return;
- }
-
- WriteVerbose("Tailscale plugin installed successfully.");
- }
-
- // Get current status
- var statusTask = Task.Run(async () => await tailscaleService.GetStatusAsync());
- var status = statusTask.GetAwaiter().GetResult();
-
- // Enable Tailscale if needed
- if (!status.Enabled && EnableIfDisabled.IsPresent)
- {
- WriteVerbose("Tailscale is disabled. Enabling...");
-
- // Get current settings
- var settingsTask = Task.Run(async () => await tailscaleService.GetSettingsAsync());
- var currentSettings = settingsTask.GetAwaiter().GetResult().General;
-
- // Process subnet routes if provided
- string routesToAdvertise = currentSettings.RoutesToAdvertise;
- bool advertiseRoutes = AdvertiseRoutes.IsPresent || currentSettings.AdvertiseRoutes == "1";
- bool advertiseExitNode = AdvertiseExitNode.IsPresent || currentSettings.AdvertiseExitNode == "1";
-
- if (SubnetRoutes != null && SubnetRoutes.Length > 0)
- {
- routesToAdvertise = string.Join(",", SubnetRoutes);
- WriteVerbose($"Advertising subnet routes: {routesToAdvertise}");
-
- // If routes are specified but AdvertiseRoutes is not set, enable it automatically
- if (!advertiseRoutes)
- {
- WriteVerbose("Automatically enabling route advertisement because subnet routes were specified.");
- advertiseRoutes = true;
- }
- }
-
- // Create new settings with enabled flag
- var settings = new TailscaleSettings
- {
- Enabled = "1",
- AcceptDns = currentSettings.AcceptDns,
- AcceptRoutes = currentSettings.AcceptRoutes,
- AdvertiseExitNode = advertiseExitNode ? "1" : "0",
- AdvertiseRoutes = advertiseRoutes ? "1" : "0",
- RoutesToAdvertise = routesToAdvertise,
- Hostname = currentSettings.Hostname,
- LoginServer = currentSettings.LoginServer,
- Ssh = currentSettings.Ssh,
- Ephemeral = currentSettings.Ephemeral,
- ResetOnStart = currentSettings.ResetOnStart
- };
-
- // Update settings
- var updateTask = Task.Run(async () => await tailscaleService.UpdateSettingsAsync(settings));
- var updateResult = updateTask.GetAwaiter().GetResult();
-
- WriteVerbose($"Tailscale settings updated: {updateResult.Result}");
-
- // Get updated status
- statusTask = Task.Run(async () => await tailscaleService.GetStatusAsync());
- status = statusTask.GetAwaiter().GetResult();
- }
-
- // Start the service if needed
- if (!status.Running && StartIfStopped.IsPresent)
- {
- WriteVerbose("Tailscale service is not running. Starting...");
- var startTask = Task.Run(async () => await tailscaleService.StartServiceAsync());
- var startResult = startTask.GetAwaiter().GetResult();
- WriteVerbose($"Tailscale service started: {startResult.Status}");
-
- // Get updated status
- statusTask = Task.Run(async () => await tailscaleService.GetStatusAsync());
- status = statusTask.GetAwaiter().GetResult();
- }
-
- // Check if Tailscale is enabled and running
- if (!status.Enabled)
- {
- WriteError(new ErrorRecord(
- new Exception("Tailscale is not enabled. Use -EnableIfDisabled to enable it."),
- "TailscaleNotEnabled",
- ErrorCategory.InvalidOperation,
- null));
+ ProcessingException = new Exception("Tailscale plugin is not installed. Use -InstallIfMissing to install it.");
return;
}
- if (!status.Running)
- {
- WriteError(new ErrorRecord(
- new Exception("Tailscale service is not running. Use -StartIfStopped to start it."),
- "TailscaleNotRunning",
- ErrorCategory.InvalidOperation,
- null));
- return;
- }
-
- if (!Force.IsPresent && !ShouldProcess("OPNSense firewall", "Connect to Tailscale network"))
+ if (!Force.IsPresent && !ShouldProcess("OPNSense firewall", "Install Tailscale plugin"))
{
return;
}
- // Connect to Tailscale
- WriteVerbose("Connecting to Tailscale network...");
- var connectTask = Task.Run(async () => await tailscaleService.ConnectAsync(AuthKey));
- var connectResult = connectTask.GetAwaiter().GetResult();
+ WriteVerbose("Tailscale plugin is not installed. Installing...");
+ var installResult = ExecuteAsyncTask(() => tailscaleService.InstallPluginAsync());
- WriteVerbose($"Tailscale connection status: {connectResult.Status}");
- WriteVerbose($"Tailscale connection message: {connectResult.Message}");
+ // Only continue if no exception occurred
+ if (ProcessingException != null)
+ {
+ return;
+ }
+
+ if (!installResult)
+ {
+ ProcessingException = new Exception("Failed to install Tailscale plugin.");
+ return;
+ }
+
+ WriteVerbose("Tailscale plugin installed successfully.");
+ }
+
+ // Get current status
+ var status = ExecuteAsyncTask(() => tailscaleService.GetStatusAsync());
+
+ // Only continue if no exception occurred
+ if (ProcessingException != null || status == null)
+ {
+ return;
+ }
+
+ // Enable Tailscale if needed
+ if (!status.Enabled && EnableIfDisabled.IsPresent)
+ {
+ WriteVerbose("Tailscale is disabled. Enabling...");
+
+ // Get current settings
+ var settingsResult = ExecuteAsyncTask(() => tailscaleService.GetSettingsAsync());
+
+ // Only continue if no exception occurred
+ if (ProcessingException != null || settingsResult == null)
+ {
+ return;
+ }
+
+ var currentSettings = settingsResult.General;
+
+ // Process subnet routes if provided
+ string routesToAdvertise = currentSettings.RoutesToAdvertise;
+ bool advertiseRoutes = AdvertiseRoutes.IsPresent || currentSettings.AdvertiseRoutes == "1";
+ bool advertiseExitNode = AdvertiseExitNode.IsPresent || currentSettings.AdvertiseExitNode == "1";
+
+ if (SubnetRoutes != null && SubnetRoutes.Length > 0)
+ {
+ routesToAdvertise = string.Join(",", SubnetRoutes);
+ WriteVerbose($"Advertising subnet routes: {routesToAdvertise}");
+
+ // If routes are specified but AdvertiseRoutes is not set, enable it automatically
+ if (!advertiseRoutes)
+ {
+ WriteVerbose("Automatically enabling route advertisement because subnet routes were specified.");
+ advertiseRoutes = true;
+ }
+ }
+
+ // Create new settings with enabled flag
+ var settings = new TailscaleSettings
+ {
+ Enabled = "1",
+ AcceptDns = currentSettings.AcceptDns,
+ AcceptRoutes = currentSettings.AcceptRoutes,
+ AdvertiseExitNode = advertiseExitNode ? "1" : "0",
+ AdvertiseRoutes = advertiseRoutes ? "1" : "0",
+ RoutesToAdvertise = routesToAdvertise,
+ Hostname = currentSettings.Hostname,
+ LoginServer = currentSettings.LoginServer,
+ Ssh = currentSettings.Ssh,
+ Ephemeral = currentSettings.Ephemeral,
+ ResetOnStart = currentSettings.ResetOnStart
+ };
+
+ // Update settings
+ var updateResult = ExecuteAsyncTask(() => tailscaleService.UpdateSettingsAsync(settings));
+
+ // Only continue if no exception occurred
+ if (ProcessingException != null || updateResult == null)
+ {
+ return;
+ }
+
+ WriteVerbose($"Tailscale settings updated: {updateResult.Result}");
// Get updated status
- statusTask = Task.Run(async () => await tailscaleService.GetStatusAsync());
- status = statusTask.GetAwaiter().GetResult();
+ status = ExecuteAsyncTask(() => tailscaleService.GetStatusAsync());
- // Get interfaces
- var interfacesTask = Task.Run(async () => await tailscaleService.GetInterfacesAsync());
- var interfaces = interfacesTask.GetAwaiter().GetResult();
-
- // Create result object
- var result = new PSObject();
- result.Properties.Add(new PSNoteProperty("Status", status.Status));
- result.Properties.Add(new PSNoteProperty("Running", status.Running));
- result.Properties.Add(new PSNoteProperty("Enabled", status.Enabled));
- result.Properties.Add(new PSNoteProperty("ConnectionStatus", connectResult.Status));
- result.Properties.Add(new PSNoteProperty("ConnectionMessage", connectResult.Message));
- result.Properties.Add(new PSNoteProperty("Interfaces", interfaces.Interfaces));
-
- WriteObject(result);
+ // Only continue if no exception occurred
+ if (ProcessingException != null || status == null)
+ {
+ return;
+ }
}
- catch (Exception ex)
+
+ // Start the service if needed
+ if (!status.Running && StartIfStopped.IsPresent)
{
- HandleException(ex);
+ WriteVerbose("Tailscale service is not running. Starting...");
+ var startResult = ExecuteAsyncTask(() => tailscaleService.StartServiceAsync());
+
+ // Only continue if no exception occurred
+ if (ProcessingException != null || startResult == null)
+ {
+ return;
+ }
+
+ WriteVerbose($"Tailscale service started: {startResult.Status}");
+
+ // Get updated status
+ status = ExecuteAsyncTask(() => tailscaleService.GetStatusAsync());
+
+ // Only continue if no exception occurred
+ if (ProcessingException != null || status == null)
+ {
+ return;
+ }
}
+
+ // Check if Tailscale is enabled and running
+ if (!status.Enabled)
+ {
+ ProcessingException = new Exception("Tailscale is not enabled. Use -EnableIfDisabled to enable it.");
+ return;
+ }
+
+ if (!status.Running)
+ {
+ ProcessingException = new Exception("Tailscale service is not running. Use -StartIfStopped to start it.");
+ return;
+ }
+
+ if (!Force.IsPresent && !ShouldProcess("OPNSense firewall", "Connect to Tailscale network"))
+ {
+ return;
+ }
+
+ // Connect to Tailscale
+ WriteVerbose("Connecting to Tailscale network...");
+ var connectResult = ExecuteAsyncTask(() => tailscaleService.ConnectAsync(AuthKey));
+
+ // Only continue if no exception occurred
+ if (ProcessingException != null || connectResult == null)
+ {
+ return;
+ }
+
+ WriteVerbose($"Tailscale connection status: {connectResult.Status}");
+ WriteVerbose($"Tailscale connection message: {connectResult.Message}");
+
+ // Get updated status
+ status = ExecuteAsyncTask(() => tailscaleService.GetStatusAsync());
+
+ // Only continue if no exception occurred
+ if (ProcessingException != null || status == null)
+ {
+ return;
+ }
+
+ // Get interfaces
+ var interfaces = ExecuteAsyncTask(() => tailscaleService.GetInterfacesAsync());
+
+ // Only continue if no exception occurred
+ if (ProcessingException != null || interfaces == null)
+ {
+ return;
+ }
+
+ // Create result object
+ var result = new PSObject();
+ result.Properties.Add(new PSNoteProperty("Status", status.Status));
+ result.Properties.Add(new PSNoteProperty("Running", status.Running));
+ result.Properties.Add(new PSNoteProperty("Enabled", status.Enabled));
+ result.Properties.Add(new PSNoteProperty("ConnectionStatus", connectResult.Status));
+ result.Properties.Add(new PSNoteProperty("ConnectionMessage", connectResult.Message));
+ result.Properties.Add(new PSNoteProperty("Interfaces", interfaces.Interfaces));
+
+ WriteObject(result);
}
}
}
diff --git a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseConnectionCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseConnectionCmdlet.cs
index e69259d..b4f5bb3 100644
--- a/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseConnectionCmdlet.cs
+++ b/src/PSOPNSenseAPI/Cmdlets/GetOPNSenseConnectionCmdlet.cs
@@ -1,5 +1,6 @@
using System;
using System.Management.Automation;
+using PSOPNSenseAPI.Logging;
using PSOPNSenseAPI.Models;
namespace PSOPNSenseAPI.Cmdlets
@@ -15,35 +16,32 @@ namespace PSOPNSenseAPI.Cmdlets
///
[Cmdlet(VerbsCommon.Get, "OPNSenseConnection")]
[OutputType(typeof(PSObject))]
- public class GetOPNSenseConnectionCmdlet : PSCmdlet
+ public class GetOPNSenseConnectionCmdlet : OPNSenseBaseCmdlet
{
///
/// Processes the cmdlet
///
- protected override void ProcessRecord()
+ protected override void BeginProcessing()
{
- try
- {
- if (!OPNSenseSession.IsConnected)
- {
- WriteWarning("Not connected to any OPNSense firewall.");
- return;
- }
+ // Override the base implementation to avoid checking for connection
+ // since this cmdlet is used to check the connection status
+ base.BeginProcessing();
+ Logger = new PowerShellLogger(this);
+ }
- var connectionInfo = new PSObject();
- connectionInfo.Properties.Add(new PSNoteProperty("Server", OPNSenseSession.BaseUrl));
- connectionInfo.Properties.Add(new PSNoteProperty("Connected", OPNSenseSession.IsConnected));
-
- WriteObject(connectionInfo);
- }
- catch (Exception ex)
+ protected override void ProcessRecordInternal()
+ {
+ if (!OPNSenseSession.IsConnected)
{
- WriteError(new ErrorRecord(
- ex,
- "GetConnectionFailed",
- ErrorCategory.ConnectionError,
- null));
+ WriteWarning("Not connected to any OPNSense firewall.");
+ return;
}
+
+ var connectionInfo = new PSObject();
+ connectionInfo.Properties.Add(new PSNoteProperty("Server", OPNSenseSession.BaseUrl));
+ connectionInfo.Properties.Add(new PSNoteProperty("Connected", OPNSenseSession.IsConnected));
+
+ WriteObject(connectionInfo);
}
}
}
diff --git a/src/PSOPNSenseAPI/Cmdlets/InvokeOPNSenseNetworkCalculationCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/InvokeOPNSenseNetworkCalculationCmdlet.cs
index 2f67113..8cb1d69 100644
--- a/src/PSOPNSenseAPI/Cmdlets/InvokeOPNSenseNetworkCalculationCmdlet.cs
+++ b/src/PSOPNSenseAPI/Cmdlets/InvokeOPNSenseNetworkCalculationCmdlet.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Management.Automation;
using System.Net;
+using PSOPNSenseAPI.Logging;
using PSOPNSenseAPI.Utilities;
namespace PSOPNSenseAPI.Cmdlets
@@ -27,7 +28,7 @@ namespace PSOPNSenseAPI.Cmdlets
///
[Cmdlet(VerbsLifecycle.Invoke, "OPNSenseNetworkCalculation")]
[OutputType(typeof(PSObject), typeof(bool), typeof(IPNetwork2[]))]
- public class InvokeOPNSenseNetworkCalculationCmdlet : PSCmdlet
+ public class InvokeOPNSenseNetworkCalculationCmdlet : OPNSenseBaseCmdlet
{
///
/// The network in CIDR notation to perform calculations on.
@@ -72,111 +73,93 @@ namespace PSOPNSenseAPI.Cmdlets
///
/// Processes the cmdlet
///
- protected override void ProcessRecord()
+ protected override void BeginProcessing()
{
+ // Override the base implementation to avoid checking for connection
+ // since this cmdlet doesn't require a connection
+ base.BeginProcessing();
+ Logger = new PowerShellLogger(this);
+ }
+
+ protected override void ProcessRecordInternal()
+ {
+ // Parse the network
+ IPNetwork2 network;
try
{
- // Parse the network
- IPNetwork2 network = NetworkUtility.ParseCIDR(Network);
-
- switch (Operation)
- {
- case "Info":
- WriteNetworkInfo(network);
- break;
-
- case "Subnet":
- if (!PrefixLength.HasValue)
- {
- WriteError(new ErrorRecord(
- new ArgumentException("PrefixLength is required for Subnet operations."),
- "MissingPrefixLength",
- ErrorCategory.InvalidArgument,
- null));
- return;
- }
-
- WriteSubnets(network, PrefixLength.Value);
- break;
-
- case "SubnetByCount":
- if (!SubnetCount.HasValue)
- {
- WriteError(new ErrorRecord(
- new ArgumentException("SubnetCount is required for SubnetByCount operations."),
- "MissingSubnetCount",
- ErrorCategory.InvalidArgument,
- null));
- return;
- }
-
- WriteSubnetsByCount(network, SubnetCount.Value);
- break;
-
- case "Contains":
- if (string.IsNullOrEmpty(IPAddress))
- {
- WriteError(new ErrorRecord(
- new ArgumentException("IPAddress is required for Contains operations."),
- "MissingIPAddress",
- ErrorCategory.InvalidArgument,
- null));
- return;
- }
-
- WriteContains(network, IPAddress);
- break;
-
- case "Overlaps":
- if (AdditionalNetworks == null || AdditionalNetworks.Length == 0)
- {
- WriteError(new ErrorRecord(
- new ArgumentException("AdditionalNetworks is required for Overlaps operations."),
- "MissingAdditionalNetworks",
- ErrorCategory.InvalidArgument,
- null));
- return;
- }
-
- WriteOverlaps(network, AdditionalNetworks);
- break;
-
- case "Supernet":
- if (AdditionalNetworks == null || AdditionalNetworks.Length == 0)
- {
- WriteError(new ErrorRecord(
- new ArgumentException("AdditionalNetworks is required for Supernet operations."),
- "MissingAdditionalNetworks",
- ErrorCategory.InvalidArgument,
- null));
- return;
- }
-
- WriteSupernet(network, AdditionalNetworks);
- break;
-
- case "SupernetSummarize":
- if (AdditionalNetworks == null || AdditionalNetworks.Length == 0)
- {
- WriteError(new ErrorRecord(
- new ArgumentException("AdditionalNetworks is required for SupernetSummarize operations."),
- "MissingAdditionalNetworks",
- ErrorCategory.InvalidArgument,
- null));
- return;
- }
-
- WriteSupernetSummarize(network, AdditionalNetworks);
- break;
- }
+ network = NetworkUtility.ParseCIDR(Network);
}
catch (Exception ex)
{
- WriteError(new ErrorRecord(
- ex,
- "NetworkCalculationError",
- ErrorCategory.InvalidOperation,
- null));
+ ProcessingException = new ArgumentException($"Invalid network format: {Network}", ex);
+ return;
+ }
+
+ switch (Operation)
+ {
+ case "Info":
+ WriteNetworkInfo(network);
+ break;
+
+ case "Subnet":
+ if (!PrefixLength.HasValue)
+ {
+ ProcessingException = new ArgumentException("PrefixLength is required for Subnet operations.");
+ return;
+ }
+
+ WriteSubnets(network, PrefixLength.Value);
+ break;
+
+ case "SubnetByCount":
+ if (!SubnetCount.HasValue)
+ {
+ ProcessingException = new ArgumentException("SubnetCount is required for SubnetByCount operations.");
+ return;
+ }
+
+ WriteSubnetsByCount(network, SubnetCount.Value);
+ break;
+
+ case "Contains":
+ if (string.IsNullOrEmpty(IPAddress))
+ {
+ ProcessingException = new ArgumentException("IPAddress is required for Contains operations.");
+ return;
+ }
+
+ WriteContains(network, IPAddress);
+ break;
+
+ case "Overlaps":
+ if (AdditionalNetworks == null || AdditionalNetworks.Length == 0)
+ {
+ ProcessingException = new ArgumentException("AdditionalNetworks is required for Overlaps operations.");
+ return;
+ }
+
+ WriteOverlaps(network, AdditionalNetworks);
+ break;
+
+ case "Supernet":
+ if (AdditionalNetworks == null || AdditionalNetworks.Length == 0)
+ {
+ ProcessingException = new ArgumentException("AdditionalNetworks is required for Supernet operations.");
+ return;
+ }
+
+ WriteSupernet(network, AdditionalNetworks);
+ break;
+
+ case "SupernetSummarize":
+ if (AdditionalNetworks == null || AdditionalNetworks.Length == 0)
+ {
+ ProcessingException = new ArgumentException("AdditionalNetworks is required for SupernetSummarize operations.");
+ return;
+ }
+
+ WriteSupernetSummarize(network, AdditionalNetworks);
+ break;
}
}
diff --git a/src/PSOPNSenseAPI/Cmdlets/NewOPNSenseCronJobCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/NewOPNSenseCronJobCmdlet.cs
index 59f0834..b36efc3 100644
--- a/src/PSOPNSenseAPI/Cmdlets/NewOPNSenseCronJobCmdlet.cs
+++ b/src/PSOPNSenseAPI/Cmdlets/NewOPNSenseCronJobCmdlet.cs
@@ -82,44 +82,49 @@ namespace PSOPNSenseAPI.Cmdlets
///
/// Processes the cmdlet
///
- protected override void ProcessRecord()
+ protected override void ProcessRecordInternal()
{
- try
+ var cronService = new CronService(ApiClient, Logger);
+
+ var job = new CronJobConfig
{
- var cronService = new CronService(ApiClient, Logger);
+ Description = Description,
+ Command = Command,
+ Minutes = Minutes,
+ Hours = Hours,
+ Days = Days,
+ Months = Months,
+ Weekdays = Weekdays,
+ Enabled = Enabled.IsPresent ? "1" : "0"
+ };
- var job = new CronJobConfig
+ // Use our safe execution method
+ var createResult = ExecuteAsyncTask(() => cronService.CreateJobAsync(job));
+
+ // Only continue if no exception occurred
+ if (ProcessingException != null || createResult == null)
+ {
+ return;
+ }
+
+ WriteVerbose($"Created cron job with UUID {createResult.Uuid}");
+
+ // Apply the changes if requested
+ if (Apply.IsPresent)
+ {
+ // Use our safe execution method
+ var applyResult = ExecuteAsyncTask(() => cronService.ApplyChangesAsync());
+
+ // Only continue if no exception occurred
+ if (ProcessingException != null || applyResult == null)
{
- Description = Description,
- Command = Command,
- Minutes = Minutes,
- Hours = Hours,
- Days = Days,
- Months = Months,
- Weekdays = Weekdays,
- Enabled = Enabled.IsPresent ? "1" : "0"
- };
-
- var createTask = Task.Run(async () => await cronService.CreateJobAsync(job));
- var createResult = createTask.GetAwaiter().GetResult();
-
- WriteVerbose($"Created cron job with UUID {createResult.Uuid}");
-
- // Apply the changes if requested
- if (Apply.IsPresent)
- {
- var applyTask = Task.Run(async () => await cronService.ApplyChangesAsync());
- var applyResult = applyTask.GetAwaiter().GetResult();
-
- WriteVerbose($"Cron changes applied: {applyResult.Status}");
+ return;
}
- WriteObject(createResult.Uuid);
- }
- catch (Exception ex)
- {
- HandleException(ex);
+ WriteVerbose($"Cron changes applied: {applyResult.Status}");
}
+
+ WriteObject(createResult.Uuid);
}
}
}
diff --git a/src/PSOPNSenseAPI/Cmdlets/OPNSenseBaseCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/OPNSenseBaseCmdlet.cs
index f154bfb..dfa1519 100644
--- a/src/PSOPNSenseAPI/Cmdlets/OPNSenseBaseCmdlet.cs
+++ b/src/PSOPNSenseAPI/Cmdlets/OPNSenseBaseCmdlet.cs
@@ -73,14 +73,14 @@ namespace PSOPNSenseAPI.Cmdlets
///
/// Gets the logger
///
- protected ILogger Logger { get; private set; }
+ protected ILogger Logger { get; set; }
///
/// Exception to be processed in ProcessRecord
///
- protected Exception ProcessingException { get; private set; }
+ protected Exception ProcessingException { get; set; }
///
/// Handles exceptions by storing them for later processing
diff --git a/src/PSOPNSenseAPI/Cmdlets/UninstallOPNSensePluginCmdlet.cs b/src/PSOPNSenseAPI/Cmdlets/UninstallOPNSensePluginCmdlet.cs
index 751de84..65548eb 100644
--- a/src/PSOPNSenseAPI/Cmdlets/UninstallOPNSensePluginCmdlet.cs
+++ b/src/PSOPNSenseAPI/Cmdlets/UninstallOPNSensePluginCmdlet.cs
@@ -60,67 +60,69 @@ namespace PSOPNSenseAPI.Cmdlets
///
/// Processes the cmdlet
///
- protected override void ProcessRecord()
+ protected override void ProcessRecordInternal()
{
- try
+ if (!Force.IsPresent && !ShouldProcess(Name, "Uninstall plugin"))
{
- if (!Force.IsPresent && !ShouldProcess(Name, "Uninstall plugin"))
- {
- return;
- }
-
- var pluginService = new PluginService(ApiClient, Logger);
-
- var task = Task.Run(async () => await pluginService.UninstallPluginAsync(Name));
- var result = task.GetAwaiter().GetResult();
-
- WriteVerbose($"Plugin uninstallation initiated: {result.Status}");
- WriteObject($"Plugin uninstallation initiated: {result.Status}");
-
- if (Wait.IsPresent)
- {
- WriteVerbose($"Waiting for plugin uninstallation to complete (timeout: {Timeout} seconds, interval: {Interval} seconds)");
- WriteObject("Waiting for plugin uninstallation to complete...");
-
- DateTime startTime = DateTime.Now;
- bool completed = false;
-
- while (DateTime.Now - startTime < TimeSpan.FromSeconds(Timeout))
- {
- var statusTask = Task.Run(async () => await pluginService.GetPluginStatusAsync());
- var statusResult = statusTask.GetAwaiter().GetResult();
-
- if (statusResult.Status == "done")
- {
- WriteVerbose("Plugin uninstallation completed successfully");
- WriteObject("Plugin uninstallation completed successfully");
- completed = true;
- break;
- }
- else if (statusResult.Status == "error")
- {
- WriteError(new ErrorRecord(
- new Exception($"Plugin uninstallation failed: {statusResult.Log}"),
- "PluginUninstallationFailed",
- ErrorCategory.InvalidOperation,
- Name));
- completed = true;
- break;
- }
-
- WriteVerbose($"Plugin uninstallation status: {statusResult.Status}");
- Thread.Sleep(Interval * 1000);
- }
-
- if (!completed)
- {
- WriteWarning($"Timed out waiting for plugin uninstallation to complete after {Timeout} seconds");
- }
- }
+ return;
}
- catch (Exception ex)
+
+ var pluginService = new PluginService(ApiClient, Logger);
+
+ // Use our safe execution method
+ var result = ExecuteAsyncTask(() => pluginService.UninstallPluginAsync(Name));
+
+ // Only continue if no exception occurred
+ if (ProcessingException != null || result == null)
{
- HandleException(ex);
+ return;
+ }
+
+ WriteVerbose($"Plugin uninstallation initiated: {result.Status}");
+ WriteObject($"Plugin uninstallation initiated: {result.Status}");
+
+ if (Wait.IsPresent)
+ {
+ WriteVerbose($"Waiting for plugin uninstallation to complete (timeout: {Timeout} seconds, interval: {Interval} seconds)");
+ WriteObject("Waiting for plugin uninstallation to complete...");
+
+ DateTime startTime = DateTime.Now;
+ bool completed = false;
+
+ while (DateTime.Now - startTime < TimeSpan.FromSeconds(Timeout))
+ {
+ // Use our safe execution method
+ var statusResult = ExecuteAsyncTask(() => pluginService.GetPluginStatusAsync());
+
+ // Break if an exception occurred
+ if (ProcessingException != null || statusResult == null)
+ {
+ break;
+ }
+
+ if (statusResult.Status == "done")
+ {
+ WriteVerbose("Plugin uninstallation completed successfully");
+ WriteObject("Plugin uninstallation completed successfully");
+ completed = true;
+ break;
+ }
+ else if (statusResult.Status == "error")
+ {
+ // Store the exception to be processed in ProcessRecord
+ ProcessingException = new Exception($"Plugin uninstallation failed: {statusResult.Log}");
+ completed = true;
+ break;
+ }
+
+ WriteVerbose($"Plugin uninstallation status: {statusResult.Status}");
+ Thread.Sleep(Interval * 1000);
+ }
+
+ if (!completed && ProcessingException == null)
+ {
+ WriteWarning($"Timed out waiting for plugin uninstallation to complete after {Timeout} seconds");
+ }
}
}
}
diff --git a/src/PSOPNSenseAPI/PSOPNSenseAPI.psd1 b/src/PSOPNSenseAPI/PSOPNSenseAPI.psd1
index e99512f..875175e 100644
--- a/src/PSOPNSenseAPI/PSOPNSenseAPI.psd1
+++ b/src/PSOPNSenseAPI/PSOPNSenseAPI.psd1
@@ -3,7 +3,7 @@
RootModule = 'lib\PSOPNSenseAPI.dll'
# Version number of this module.
- ModuleVersion = '2025.04.15.1216'
+ ModuleVersion = '2025.04.15.1228'
# Supported PSEditions
CompatiblePSEditions = @('Desktop', 'Core')