mirror of
https://github.com/freedbygrace/PSOPNSenseAPI.git
synced 2026-07-26 11:58:18 +00:00
Fixed more threading issues in PowerShell cmdlets to ensure WriteObject and WriteError are only called from the main thread
This commit is contained in:
@@ -95,54 +95,59 @@ namespace PSOPNSenseAPI.Cmdlets
|
||||
/// <summary>
|
||||
/// Processes the cmdlet
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
protected override void ProcessRecordInternal()
|
||||
{
|
||||
try
|
||||
var aliasService = new AliasService(ApiClient, Logger);
|
||||
|
||||
var alias = new AliasConfig
|
||||
{
|
||||
var aliasService = new AliasService(ApiClient, Logger);
|
||||
Name = Name,
|
||||
Type = Type.ToLower(),
|
||||
Content = Content,
|
||||
Description = Description,
|
||||
Enabled = Disabled.IsPresent ? "0" : "1",
|
||||
Counters = EnableCounters.IsPresent ? "1" : "0"
|
||||
};
|
||||
|
||||
var alias = new AliasConfig
|
||||
{
|
||||
Name = Name,
|
||||
Type = Type.ToLower(),
|
||||
Content = Content,
|
||||
Description = Description,
|
||||
Enabled = Disabled.IsPresent ? "0" : "1",
|
||||
Counters = EnableCounters.IsPresent ? "1" : "0"
|
||||
};
|
||||
|
||||
// Set protocol for port aliases
|
||||
if (Type.Equals("port", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(Protocol))
|
||||
{
|
||||
alias.Protocol = Protocol.ToUpper();
|
||||
}
|
||||
|
||||
// Set update frequency for URL aliases
|
||||
if ((Type.Equals("url", StringComparison.OrdinalIgnoreCase) || Type.Equals("urltable", StringComparison.OrdinalIgnoreCase)) && UpdateFrequency.HasValue)
|
||||
{
|
||||
alias.UpdateFrequency = UpdateFrequency.Value.ToString();
|
||||
}
|
||||
|
||||
var createTask = Task.Run(async () => await aliasService.CreateAliasAsync(alias));
|
||||
var createResult = createTask.GetAwaiter().GetResult();
|
||||
|
||||
WriteVerbose($"Created alias with UUID {createResult.Uuid}");
|
||||
|
||||
// Apply changes if requested
|
||||
if (Apply.IsPresent)
|
||||
{
|
||||
var applyTask = Task.Run(async () => await aliasService.ReconfigureAliasesAsync());
|
||||
var applyResult = applyTask.GetAwaiter().GetResult();
|
||||
|
||||
WriteVerbose($"Alias changes applied: {applyResult.Status}");
|
||||
}
|
||||
|
||||
WriteObject(createResult.Uuid);
|
||||
}
|
||||
catch (Exception ex)
|
||||
// Set protocol for port aliases
|
||||
if (Type.Equals("port", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(Protocol))
|
||||
{
|
||||
HandleException(ex);
|
||||
alias.Protocol = Protocol.ToUpper();
|
||||
}
|
||||
|
||||
// Set update frequency for URL aliases
|
||||
if ((Type.Equals("url", StringComparison.OrdinalIgnoreCase) || Type.Equals("urltable", StringComparison.OrdinalIgnoreCase)) && UpdateFrequency.HasValue)
|
||||
{
|
||||
alias.UpdateFrequency = UpdateFrequency.Value.ToString();
|
||||
}
|
||||
|
||||
// Use our safe execution method
|
||||
var createResult = ExecuteAsyncTask(() => aliasService.CreateAliasAsync(alias));
|
||||
|
||||
// Only continue if no exception occurred
|
||||
if (ProcessingException != null || createResult == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
WriteVerbose($"Created alias with UUID {createResult.Uuid}");
|
||||
|
||||
// Apply changes if requested
|
||||
if (Apply.IsPresent)
|
||||
{
|
||||
// Use our safe execution method
|
||||
var applyResult = ExecuteAsyncTask(() => aliasService.ReconfigureAliasesAsync());
|
||||
|
||||
// Only continue if no exception occurred
|
||||
if (ProcessingException != null || applyResult == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
WriteVerbose($"Alias changes applied: {applyResult.Status}");
|
||||
}
|
||||
|
||||
WriteObject(createResult.Uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,40 +61,45 @@ namespace PSOPNSenseAPI.Cmdlets
|
||||
/// <summary>
|
||||
/// Processes the cmdlet
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
protected override void ProcessRecordInternal()
|
||||
{
|
||||
try
|
||||
var dhcpService = new DHCPService(ApiClient, Logger);
|
||||
|
||||
var option = new DHCPOptionConfig
|
||||
{
|
||||
var dhcpService = new DHCPService(ApiClient, Logger);
|
||||
Number = Number,
|
||||
Value = Value,
|
||||
Type = Type,
|
||||
Description = Description
|
||||
};
|
||||
|
||||
var option = new DHCPOptionConfig
|
||||
// Use our safe execution method
|
||||
var createResult = ExecuteAsyncTask(() => dhcpService.CreateOptionAsync(Interface, option));
|
||||
|
||||
// Only continue if no exception occurred
|
||||
if (ProcessingException != null || createResult == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
WriteVerbose($"Created DHCP option with UUID {createResult.Uuid}");
|
||||
|
||||
// Apply changes if requested
|
||||
if (Apply.IsPresent)
|
||||
{
|
||||
// Use our safe execution method
|
||||
var applyResult = ExecuteAsyncTask(() => dhcpService.ApplyChangesAsync());
|
||||
|
||||
// Only continue if no exception occurred
|
||||
if (ProcessingException != null || applyResult == null)
|
||||
{
|
||||
Number = Number,
|
||||
Value = Value,
|
||||
Type = Type,
|
||||
Description = Description
|
||||
};
|
||||
|
||||
var createTask = Task.Run(async () => await dhcpService.CreateOptionAsync(Interface, option));
|
||||
var createResult = createTask.GetAwaiter().GetResult();
|
||||
|
||||
WriteVerbose($"Created DHCP option with UUID {createResult.Uuid}");
|
||||
|
||||
// Apply changes if requested
|
||||
if (Apply.IsPresent)
|
||||
{
|
||||
var applyTask = Task.Run(async () => await dhcpService.ApplyChangesAsync());
|
||||
var applyResult = applyTask.GetAwaiter().GetResult();
|
||||
|
||||
WriteVerbose($"DHCP changes applied: {applyResult.Status}");
|
||||
return;
|
||||
}
|
||||
|
||||
WriteObject(createResult.Uuid);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
HandleException(ex);
|
||||
WriteVerbose($"DHCP changes applied: {applyResult.Status}");
|
||||
}
|
||||
|
||||
WriteObject(createResult.Uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,41 +66,46 @@ namespace PSOPNSenseAPI.Cmdlets
|
||||
/// <summary>
|
||||
/// Processes the cmdlet
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
protected override void ProcessRecordInternal()
|
||||
{
|
||||
try
|
||||
var dhcpService = new DHCPService(ApiClient, Logger);
|
||||
|
||||
var mapping = new DHCPStaticMappingConfig
|
||||
{
|
||||
var dhcpService = new DHCPService(ApiClient, Logger);
|
||||
MacAddress = MacAddress,
|
||||
IpAddress = IpAddress,
|
||||
Hostname = Hostname,
|
||||
Description = Description,
|
||||
Enabled = Enabled.IsPresent ? "1" : "0"
|
||||
};
|
||||
|
||||
var mapping = new DHCPStaticMappingConfig
|
||||
// Use our safe execution method
|
||||
var createResult = ExecuteAsyncTask(() => dhcpService.CreateStaticMappingAsync(Interface, mapping));
|
||||
|
||||
// Only continue if no exception occurred
|
||||
if (ProcessingException != null || createResult == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
WriteVerbose($"Created static mapping with UUID {createResult.Uuid}");
|
||||
|
||||
// Apply the changes if requested
|
||||
if (Apply.IsPresent)
|
||||
{
|
||||
// Use our safe execution method
|
||||
var applyResult = ExecuteAsyncTask(() => dhcpService.ApplyChangesAsync());
|
||||
|
||||
// Only continue if no exception occurred
|
||||
if (ProcessingException != null || applyResult == null)
|
||||
{
|
||||
MacAddress = MacAddress,
|
||||
IpAddress = IpAddress,
|
||||
Hostname = Hostname,
|
||||
Description = Description,
|
||||
Enabled = Enabled.IsPresent ? "1" : "0"
|
||||
};
|
||||
|
||||
var createTask = Task.Run(async () => await dhcpService.CreateStaticMappingAsync(Interface, mapping));
|
||||
var createResult = createTask.GetAwaiter().GetResult();
|
||||
|
||||
WriteVerbose($"Created static mapping with UUID {createResult.Uuid}");
|
||||
|
||||
// Apply the changes if requested
|
||||
if (Apply.IsPresent)
|
||||
{
|
||||
var applyTask = Task.Run(async () => await dhcpService.ApplyChangesAsync());
|
||||
var applyResult = applyTask.GetAwaiter().GetResult();
|
||||
|
||||
WriteVerbose($"DHCP changes applied: {applyResult.Status}");
|
||||
return;
|
||||
}
|
||||
|
||||
WriteObject(createResult.Uuid);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
HandleException(ex);
|
||||
WriteVerbose($"DHCP changes applied: {applyResult.Status}");
|
||||
}
|
||||
|
||||
WriteObject(createResult.Uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,105 +55,106 @@ namespace PSOPNSenseAPI.Cmdlets
|
||||
/// <summary>
|
||||
/// Processes the cmdlet
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
protected override void ProcessRecordInternal()
|
||||
{
|
||||
try
|
||||
if (!Force.IsPresent && !ShouldProcess("OPNSense firewall", "Restart"))
|
||||
{
|
||||
if (!Force.IsPresent && !ShouldProcess("OPNSense firewall", "Restart"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var systemService = new SystemService(ApiClient, Logger);
|
||||
|
||||
// Store connection information for reconnection
|
||||
string baseUrl = OPNSenseSession.BaseUrl;
|
||||
string apiKey = null;
|
||||
string apiSecret = null;
|
||||
bool skipCertificateCheck = false;
|
||||
|
||||
// Extract connection information from the current session
|
||||
if (ApiClient is OPNSenseApiClient client)
|
||||
{
|
||||
baseUrl = client.BaseUrl;
|
||||
apiKey = client.ApiKey;
|
||||
apiSecret = client.ApiSecret;
|
||||
skipCertificateCheck = client.SkipCertificateCheck;
|
||||
}
|
||||
|
||||
// If we couldn't get the credentials, we can't reconnect
|
||||
if (Wait.IsPresent && (string.IsNullOrEmpty(apiKey) || string.IsNullOrEmpty(apiSecret)))
|
||||
{
|
||||
WriteWarning("Could not retrieve API credentials from the current session. Will not attempt to reconnect after restart.");
|
||||
Wait = false;
|
||||
}
|
||||
|
||||
// Restart the firewall
|
||||
var task = Task.Run(async () => await systemService.RebootAsync());
|
||||
var result = task.GetAwaiter().GetResult();
|
||||
|
||||
WriteVerbose($"Firewall restart initiated: {result.Status}");
|
||||
WriteObject("Firewall restart initiated. The firewall is now restarting.");
|
||||
|
||||
// Wait for the firewall to come back online if requested
|
||||
if (Wait.IsPresent)
|
||||
{
|
||||
WriteVerbose($"Waiting for firewall to come back online (timeout: {Timeout} seconds, interval: {Interval} seconds)");
|
||||
WriteObject("Waiting for firewall to come back online...");
|
||||
|
||||
// Disconnect the current session
|
||||
OPNSenseSession.Current?.Dispose();
|
||||
OPNSenseSession.Current = null;
|
||||
|
||||
// Wait a bit for the firewall to start rebooting
|
||||
Thread.Sleep(5000);
|
||||
|
||||
// Try to reconnect
|
||||
DateTime startTime = DateTime.Now;
|
||||
bool reconnected = false;
|
||||
|
||||
while (DateTime.Now - startTime < TimeSpan.FromSeconds(Timeout))
|
||||
{
|
||||
try
|
||||
{
|
||||
WriteVerbose($"Attempting to reconnect to {baseUrl}...");
|
||||
|
||||
// Create a new logger
|
||||
var logger = new PowerShellLogger(this);
|
||||
|
||||
// Create a new API client
|
||||
var newClient = new OPNSenseApiClient(baseUrl, apiKey, apiSecret, skipCertificateCheck, logger);
|
||||
|
||||
// Try to get the system status
|
||||
var statusService = new SystemService(newClient, logger);
|
||||
var statusTask = Task.Run(async () => await statusService.GetStatusAsync());
|
||||
var statusResult = statusTask.GetAwaiter().GetResult();
|
||||
|
||||
// If we get here, the firewall is back online
|
||||
WriteVerbose("Successfully reconnected to the firewall");
|
||||
WriteObject($"Firewall is back online. Uptime: {statusResult.Uptime}");
|
||||
|
||||
// Set the new session
|
||||
OPNSenseSession.Current = newClient;
|
||||
reconnected = true;
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteVerbose($"Reconnection attempt failed: {ex.Message}");
|
||||
Thread.Sleep(Interval * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
if (!reconnected)
|
||||
{
|
||||
WriteWarning($"Timed out waiting for firewall to come back online after {Timeout} seconds");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
var systemService = new SystemService(ApiClient, Logger);
|
||||
|
||||
// Store connection information for reconnection
|
||||
string baseUrl = OPNSenseSession.BaseUrl;
|
||||
string apiKey = null;
|
||||
string apiSecret = null;
|
||||
bool skipCertificateCheck = false;
|
||||
|
||||
// Extract connection information from the current session
|
||||
if (ApiClient is OPNSenseApiClient client)
|
||||
{
|
||||
HandleException(ex);
|
||||
baseUrl = client.BaseUrl;
|
||||
apiKey = client.ApiKey;
|
||||
apiSecret = client.ApiSecret;
|
||||
skipCertificateCheck = client.SkipCertificateCheck;
|
||||
}
|
||||
|
||||
// If we couldn't get the credentials, we can't reconnect
|
||||
if (Wait.IsPresent && (string.IsNullOrEmpty(apiKey) || string.IsNullOrEmpty(apiSecret)))
|
||||
{
|
||||
WriteWarning("Could not retrieve API credentials from the current session. Will not attempt to reconnect after restart.");
|
||||
Wait = false;
|
||||
}
|
||||
|
||||
// Restart the firewall
|
||||
var result = ExecuteAsyncTask(() => systemService.RebootAsync());
|
||||
|
||||
// Only continue if no exception occurred
|
||||
if (ProcessingException != null || result == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
WriteVerbose($"Firewall restart initiated: {result.Status}");
|
||||
WriteObject("Firewall restart initiated. The firewall is now restarting.");
|
||||
|
||||
// Wait for the firewall to come back online if requested
|
||||
if (Wait.IsPresent)
|
||||
{
|
||||
WriteVerbose($"Waiting for firewall to come back online (timeout: {Timeout} seconds, interval: {Interval} seconds)");
|
||||
WriteObject("Waiting for firewall to come back online...");
|
||||
|
||||
// Disconnect the current session
|
||||
OPNSenseSession.Current?.Dispose();
|
||||
OPNSenseSession.Current = null;
|
||||
|
||||
// Wait a bit for the firewall to start rebooting
|
||||
Thread.Sleep(5000);
|
||||
|
||||
// Try to reconnect
|
||||
DateTime startTime = DateTime.Now;
|
||||
bool reconnected = false;
|
||||
|
||||
while (DateTime.Now - startTime < TimeSpan.FromSeconds(Timeout))
|
||||
{
|
||||
try
|
||||
{
|
||||
WriteVerbose($"Attempting to reconnect to {baseUrl}...");
|
||||
|
||||
// Create a new logger
|
||||
var logger = new PowerShellLogger(this);
|
||||
|
||||
// Create a new API client
|
||||
var newClient = new OPNSenseApiClient(baseUrl, apiKey, apiSecret, skipCertificateCheck, logger);
|
||||
|
||||
// Try to get the system status
|
||||
var statusService = new SystemService(newClient, logger);
|
||||
|
||||
// We need to use Task.Run here because we're creating a new client
|
||||
// and can't use ExecuteAsyncTask which uses the existing client
|
||||
var statusTask = Task.Run(async () => await statusService.GetStatusAsync());
|
||||
var statusResult = statusTask.GetAwaiter().GetResult();
|
||||
|
||||
// If we get here, the firewall is back online
|
||||
WriteVerbose("Successfully reconnected to the firewall");
|
||||
WriteObject($"Firewall is back online. Uptime: {statusResult.Uptime}");
|
||||
|
||||
// Set the new session
|
||||
OPNSenseSession.Current = newClient;
|
||||
reconnected = true;
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteVerbose($"Reconnection attempt failed: {ex.Message}");
|
||||
Thread.Sleep(Interval * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
if (!reconnected)
|
||||
{
|
||||
WriteWarning($"Timed out waiting for firewall to come back online after {Timeout} seconds");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,26 +34,25 @@ namespace PSOPNSenseAPI.Cmdlets
|
||||
/// <summary>
|
||||
/// Processes the cmdlet
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
protected override void ProcessRecordInternal()
|
||||
{
|
||||
try
|
||||
if (!Force.IsPresent && !ShouldProcess(Name, "Restart interface"))
|
||||
{
|
||||
if (!Force.IsPresent && !ShouldProcess(Name, "Restart interface"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var interfaceService = new InterfaceService(ApiClient, Logger);
|
||||
|
||||
var task = Task.Run(async () => await interfaceService.RestartInterfaceAsync(Name));
|
||||
var result = task.GetAwaiter().GetResult();
|
||||
|
||||
WriteVerbose($"Interface {Name} restarted: {result.Status}");
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
var interfaceService = new InterfaceService(ApiClient, Logger);
|
||||
|
||||
// Use our safe execution method
|
||||
var result = ExecuteAsyncTask(() => interfaceService.RestartInterfaceAsync(Name));
|
||||
|
||||
// Only continue if no exception occurred
|
||||
if (ProcessingException != null || result == null)
|
||||
{
|
||||
HandleException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
WriteVerbose($"Interface {Name} restarted: {result.Status}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
RootModule = 'lib\PSOPNSenseAPI.dll'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '2025.04.15.1253'
|
||||
ModuleVersion = '2025.04.15.1257'
|
||||
|
||||
# Supported PSEditions
|
||||
CompatiblePSEditions = @('Desktop', 'Core')
|
||||
|
||||
Reference in New Issue
Block a user