mirror of
https://github.com/freedbygrace/PSOPNSenseAPI.git
synced 2026-08-31 04:47:55 +00:00
Fixed additional threading issues in PowerShell cmdlets to ensure WriteObject and WriteError are only called from the main thread
This commit is contained in:
@@ -34,30 +34,35 @@ namespace PSOPNSenseAPI.Cmdlets
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Processes the cmdlet
|
/// Processes the cmdlet
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void ProcessRecord()
|
protected override void ProcessRecordInternal()
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var cronService = new CronService(ApiClient, Logger);
|
var cronService = new CronService(ApiClient, Logger);
|
||||||
|
|
||||||
var task = Task.Run(async () => await cronService.ToggleJobAsync(Uuid, false));
|
// Use our safe execution method
|
||||||
var result = task.GetAwaiter().GetResult();
|
var result = ExecuteAsyncTask(() => cronService.ToggleJobAsync(Uuid, false));
|
||||||
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null || result == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
WriteVerbose($"Cron job {Uuid} disabled: {result.Result}");
|
WriteVerbose($"Cron job {Uuid} disabled: {result.Result}");
|
||||||
|
|
||||||
// Apply the changes if requested
|
// Apply the changes if requested
|
||||||
if (Apply.IsPresent)
|
if (Apply.IsPresent)
|
||||||
{
|
{
|
||||||
var applyTask = Task.Run(async () => await cronService.ApplyChangesAsync());
|
// Use our safe execution method
|
||||||
var applyResult = applyTask.GetAwaiter().GetResult();
|
var applyResult = ExecuteAsyncTask(() => cronService.ApplyChangesAsync());
|
||||||
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null || applyResult == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
WriteVerbose($"Cron changes applied: {applyResult.Status}");
|
WriteVerbose($"Cron changes applied: {applyResult.Status}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
HandleException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,15 +105,18 @@ namespace PSOPNSenseAPI.Cmdlets
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Processes the cmdlet
|
/// Processes the cmdlet
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void ProcessRecord()
|
protected override void ProcessRecordInternal()
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var tailscaleService = new TailscaleService(ApiClient, Logger);
|
var tailscaleService = new TailscaleService(ApiClient, Logger);
|
||||||
|
|
||||||
// Check if the plugin is installed
|
// Check if the plugin is installed
|
||||||
var isInstalledTask = Task.Run(async () => await tailscaleService.IsPluginInstalledAsync());
|
var isInstalled = ExecuteAsyncTask(() => tailscaleService.IsPluginInstalledAsync());
|
||||||
var isInstalled = isInstalledTask.GetAwaiter().GetResult();
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!isInstalled)
|
if (!isInstalled)
|
||||||
{
|
{
|
||||||
@@ -124,16 +127,17 @@ namespace PSOPNSenseAPI.Cmdlets
|
|||||||
}
|
}
|
||||||
|
|
||||||
WriteVerbose("Tailscale plugin is not installed. Installing...");
|
WriteVerbose("Tailscale plugin is not installed. Installing...");
|
||||||
var installTask = Task.Run(async () => await tailscaleService.InstallPluginAsync());
|
var installResult = ExecuteAsyncTask(() => tailscaleService.InstallPluginAsync());
|
||||||
var installResult = installTask.GetAwaiter().GetResult();
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!installResult)
|
if (!installResult)
|
||||||
{
|
{
|
||||||
WriteError(new ErrorRecord(
|
ProcessingException = new Exception("Failed to install Tailscale plugin.");
|
||||||
new Exception("Failed to install Tailscale plugin."),
|
|
||||||
"TailscalePluginInstallFailed",
|
|
||||||
ErrorCategory.InvalidOperation,
|
|
||||||
null));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,8 +145,15 @@ namespace PSOPNSenseAPI.Cmdlets
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get current settings
|
// Get current settings
|
||||||
var settingsTask = Task.Run(async () => await tailscaleService.GetSettingsAsync());
|
var settingsResult = ExecuteAsyncTask(() => tailscaleService.GetSettingsAsync());
|
||||||
var currentSettings = settingsTask.GetAwaiter().GetResult().General;
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null || settingsResult == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentSettings = settingsResult.General;
|
||||||
|
|
||||||
// Process subnet routes if provided
|
// Process subnet routes if provided
|
||||||
string routesToAdvertise = currentSettings.RoutesToAdvertise;
|
string routesToAdvertise = currentSettings.RoutesToAdvertise;
|
||||||
@@ -181,14 +192,24 @@ namespace PSOPNSenseAPI.Cmdlets
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update settings
|
// Update settings
|
||||||
var updateTask = Task.Run(async () => await tailscaleService.UpdateSettingsAsync(settings));
|
var updateResult = ExecuteAsyncTask(() => tailscaleService.UpdateSettingsAsync(settings));
|
||||||
var updateResult = updateTask.GetAwaiter().GetResult();
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null || updateResult == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
WriteVerbose($"Tailscale settings updated: {updateResult.Result}");
|
WriteVerbose($"Tailscale settings updated: {updateResult.Result}");
|
||||||
|
|
||||||
// Get current status
|
// Get current status
|
||||||
var statusTask = Task.Run(async () => await tailscaleService.GetStatusAsync());
|
var status = ExecuteAsyncTask(() => tailscaleService.GetStatusAsync());
|
||||||
var status = statusTask.GetAwaiter().GetResult();
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null || status == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Start or restart the service if requested
|
// Start or restart the service if requested
|
||||||
if (Restart.IsPresent || (Start.IsPresent && !status.Running))
|
if (Restart.IsPresent || (Start.IsPresent && !status.Running))
|
||||||
@@ -198,23 +219,40 @@ namespace PSOPNSenseAPI.Cmdlets
|
|||||||
if (Restart.IsPresent)
|
if (Restart.IsPresent)
|
||||||
{
|
{
|
||||||
WriteVerbose("Restarting Tailscale service...");
|
WriteVerbose("Restarting Tailscale service...");
|
||||||
var restartTask = Task.Run(async () => await tailscaleService.RestartServiceAsync());
|
var restartResult = ExecuteAsyncTask(() => tailscaleService.RestartServiceAsync());
|
||||||
var restartResult = restartTask.GetAwaiter().GetResult();
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null || restartResult == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
WriteVerbose($"Tailscale service restarted: {restartResult.Status}");
|
WriteVerbose($"Tailscale service restarted: {restartResult.Status}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Start.IsPresent)
|
else if (Start.IsPresent)
|
||||||
{
|
{
|
||||||
WriteVerbose("Starting Tailscale service...");
|
WriteVerbose("Starting Tailscale service...");
|
||||||
var startTask = Task.Run(async () => await tailscaleService.StartServiceAsync());
|
var startResult = ExecuteAsyncTask(() => tailscaleService.StartServiceAsync());
|
||||||
var startResult = startTask.GetAwaiter().GetResult();
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null || startResult == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
WriteVerbose($"Tailscale service started: {startResult.Status}");
|
WriteVerbose($"Tailscale service started: {startResult.Status}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get updated status
|
// Get updated status
|
||||||
statusTask = Task.Run(async () => await tailscaleService.GetStatusAsync());
|
status = ExecuteAsyncTask(() => tailscaleService.GetStatusAsync());
|
||||||
status = statusTask.GetAwaiter().GetResult();
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null || status == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Create result object
|
// Create result object
|
||||||
var result = new PSObject();
|
var result = new PSObject();
|
||||||
@@ -226,10 +264,5 @@ namespace PSOPNSenseAPI.Cmdlets
|
|||||||
|
|
||||||
WriteObject(result);
|
WriteObject(result);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
HandleException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,15 +33,18 @@ namespace PSOPNSenseAPI.Cmdlets
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Processes the cmdlet
|
/// Processes the cmdlet
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void ProcessRecord()
|
protected override void ProcessRecordInternal()
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var tailscaleService = new TailscaleService(ApiClient, Logger);
|
var tailscaleService = new TailscaleService(ApiClient, Logger);
|
||||||
|
|
||||||
// Check if the plugin is installed
|
// Check if the plugin is installed
|
||||||
var isInstalledTask = Task.Run(async () => await tailscaleService.IsPluginInstalledAsync());
|
var isInstalled = ExecuteAsyncTask(() => tailscaleService.IsPluginInstalledAsync());
|
||||||
var isInstalled = isInstalledTask.GetAwaiter().GetResult();
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!isInstalled)
|
if (!isInstalled)
|
||||||
{
|
{
|
||||||
@@ -58,8 +61,13 @@ namespace PSOPNSenseAPI.Cmdlets
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the status
|
// Get the status
|
||||||
var statusTask = Task.Run(async () => await tailscaleService.GetStatusAsync());
|
var status = ExecuteAsyncTask(() => tailscaleService.GetStatusAsync());
|
||||||
var status = statusTask.GetAwaiter().GetResult();
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null || status == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var result = new PSObject();
|
var result = new PSObject();
|
||||||
result.Properties.Add(new PSNoteProperty("PluginInstalled", true));
|
result.Properties.Add(new PSNoteProperty("PluginInstalled", true));
|
||||||
@@ -70,8 +78,13 @@ namespace PSOPNSenseAPI.Cmdlets
|
|||||||
// Get interfaces if requested
|
// Get interfaces if requested
|
||||||
if (IncludeInterfaces.IsPresent)
|
if (IncludeInterfaces.IsPresent)
|
||||||
{
|
{
|
||||||
var interfacesTask = Task.Run(async () => await tailscaleService.GetInterfacesAsync());
|
var interfaces = ExecuteAsyncTask(() => tailscaleService.GetInterfacesAsync());
|
||||||
var interfaces = interfacesTask.GetAwaiter().GetResult();
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null || interfaces == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
result.Properties.Add(new PSNoteProperty("Interfaces", interfaces.Interfaces));
|
result.Properties.Add(new PSNoteProperty("Interfaces", interfaces.Interfaces));
|
||||||
}
|
}
|
||||||
@@ -79,18 +92,18 @@ namespace PSOPNSenseAPI.Cmdlets
|
|||||||
// Get settings if requested
|
// Get settings if requested
|
||||||
if (IncludeSettings.IsPresent)
|
if (IncludeSettings.IsPresent)
|
||||||
{
|
{
|
||||||
var settingsTask = Task.Run(async () => await tailscaleService.GetSettingsAsync());
|
var settings = ExecuteAsyncTask(() => tailscaleService.GetSettingsAsync());
|
||||||
var settings = settingsTask.GetAwaiter().GetResult();
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null || settings == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
result.Properties.Add(new PSNoteProperty("Settings", settings.General));
|
result.Properties.Add(new PSNoteProperty("Settings", settings.General));
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteObject(result);
|
WriteObject(result);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
HandleException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,9 +53,7 @@ namespace PSOPNSenseAPI.Cmdlets
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Processes the cmdlet
|
/// Processes the cmdlet
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void ProcessRecord()
|
protected override void ProcessRecordInternal()
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var dnsService = new DNSService(ApiClient, Logger);
|
var dnsService = new DNSService(ApiClient, Logger);
|
||||||
|
|
||||||
@@ -67,26 +65,33 @@ namespace PSOPNSenseAPI.Cmdlets
|
|||||||
Enabled = Enabled.IsPresent ? "1" : "0"
|
Enabled = Enabled.IsPresent ? "1" : "0"
|
||||||
};
|
};
|
||||||
|
|
||||||
var createTask = Task.Run(async () => await dnsService.CreateDNSForwardingHostAsync(host));
|
// Use our safe execution method
|
||||||
var createResult = createTask.GetAwaiter().GetResult();
|
var createResult = ExecuteAsyncTask(() => dnsService.CreateDNSForwardingHostAsync(host));
|
||||||
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null || createResult == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
WriteVerbose($"Created DNS forwarding host with UUID {createResult.Uuid}");
|
WriteVerbose($"Created DNS forwarding host with UUID {createResult.Uuid}");
|
||||||
|
|
||||||
// Apply changes if requested
|
// Apply changes if requested
|
||||||
if (Apply.IsPresent)
|
if (Apply.IsPresent)
|
||||||
{
|
{
|
||||||
var applyTask = Task.Run(async () => await dnsService.ApplyDNSChangesAsync());
|
// Use our safe execution method
|
||||||
var applyResult = applyTask.GetAwaiter().GetResult();
|
var applyResult = ExecuteAsyncTask(() => dnsService.ApplyDNSChangesAsync());
|
||||||
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null || applyResult == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
WriteVerbose($"DNS changes applied: {applyResult.Status}");
|
WriteVerbose($"DNS changes applied: {applyResult.Status}");
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteObject(createResult.Uuid);
|
WriteObject(createResult.Uuid);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
HandleException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,15 +93,20 @@ namespace PSOPNSenseAPI.Cmdlets
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Processes the cmdlet
|
/// Processes the cmdlet
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void ProcessRecord()
|
protected override void ProcessRecordInternal()
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var cronService = new CronService(ApiClient, Logger);
|
var cronService = new CronService(ApiClient, Logger);
|
||||||
|
|
||||||
// First, get the current job
|
// First, get the current job
|
||||||
var getTask = Task.Run(async () => await cronService.GetJobAsync(Uuid));
|
var getResult = ExecuteAsyncTask(() => cronService.GetJobAsync(Uuid));
|
||||||
var currentJob = getTask.GetAwaiter().GetResult().Job;
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null || getResult == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentJob = getResult.Job;
|
||||||
|
|
||||||
// Create the updated job
|
// Create the updated job
|
||||||
var job = new CronJobConfig
|
var job = new CronJobConfig
|
||||||
@@ -135,24 +140,29 @@ namespace PSOPNSenseAPI.Cmdlets
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update the job
|
// Update the job
|
||||||
var updateTask = Task.Run(async () => await cronService.UpdateJobAsync(Uuid, job));
|
var updateResult = ExecuteAsyncTask(() => cronService.UpdateJobAsync(Uuid, job));
|
||||||
var updateResult = updateTask.GetAwaiter().GetResult();
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null || updateResult == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
WriteVerbose($"Cron job {Uuid} updated: {updateResult.Result}");
|
WriteVerbose($"Cron job {Uuid} updated: {updateResult.Result}");
|
||||||
|
|
||||||
// Apply the changes if requested
|
// Apply the changes if requested
|
||||||
if (Apply.IsPresent)
|
if (Apply.IsPresent)
|
||||||
{
|
{
|
||||||
var applyTask = Task.Run(async () => await cronService.ApplyChangesAsync());
|
var applyResult = ExecuteAsyncTask(() => cronService.ApplyChangesAsync());
|
||||||
var applyResult = applyTask.GetAwaiter().GetResult();
|
|
||||||
|
// Only continue if no exception occurred
|
||||||
|
if (ProcessingException != null || applyResult == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
WriteVerbose($"Cron changes applied: {applyResult.Status}");
|
WriteVerbose($"Cron changes applied: {applyResult.Status}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
HandleException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
RootModule = 'lib\PSOPNSenseAPI.dll'
|
RootModule = 'lib\PSOPNSenseAPI.dll'
|
||||||
|
|
||||||
# Version number of this module.
|
# Version number of this module.
|
||||||
ModuleVersion = '2025.04.15.1234'
|
ModuleVersion = '2025.04.15.1245'
|
||||||
|
|
||||||
# Supported PSEditions
|
# Supported PSEditions
|
||||||
CompatiblePSEditions = @('Desktop', 'Core')
|
CompatiblePSEditions = @('Desktop', 'Core')
|
||||||
|
|||||||
Reference in New Issue
Block a user