fix image generation when null

This commit is contained in:
misya 2025-05-21 17:23:29 +08:00
parent d9fe781343
commit a2ee35d462
2 changed files with 104 additions and 86 deletions

View File

@ -3,31 +3,38 @@ using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.ComponentModel; using System.ComponentModel;
using System.Threading;
public class NetworkShareAccess : IDisposable public class NetworkShareAccess : IDisposable
{ {
private readonly string _networkPath; private readonly string _networkPath;
private readonly string _username; private readonly string _username;
private readonly string _password; private readonly string _password;
private bool _isConnected = false; private bool _isConnected = false;
private static readonly object _lock = new object();
public NetworkShareAccess(string networkPath, string username, string password) public NetworkShareAccess(string networkPath, string username, string password)
{ {
// Validate and normalize the network path
_networkPath = networkPath?.Trim().Replace('/', '\\') ?? throw new ArgumentNullException(nameof(networkPath)); _networkPath = networkPath?.Trim().Replace('/', '\\') ?? throw new ArgumentNullException(nameof(networkPath));
if (!_networkPath.StartsWith(@"\\")) if (!_networkPath.StartsWith(@"\\"))
{
throw new ArgumentException("Network path must start with \\\\"); throw new ArgumentException("Network path must start with \\\\");
}
_username = username ?? throw new ArgumentNullException(nameof(username)); _username = username ?? throw new ArgumentNullException(nameof(username));
_password = password ?? throw new ArgumentNullException(nameof(password)); _password = password ?? throw new ArgumentNullException(nameof(password));
} }
public void ConnectToNetworkPath() public void ConnectToNetworkPath()
{
lock (_lock)
{ {
if (_isConnected) return; if (_isConnected) return;
int retries = 0;
while (retries < 3)
{
try
{
var netResource = new NetResource var netResource = new NetResource
{ {
Scope = ResourceScope.GlobalNetwork, Scope = ResourceScope.GlobalNetwork,
@ -38,18 +45,35 @@ public class NetworkShareAccess : IDisposable
int result = WNetAddConnection2(netResource, _password, _username, 0); int result = WNetAddConnection2(netResource, _password, _username, 0);
if (result != 0) if (result == 0)
{ {
string errorMessage = GetNetworkErrorDescription(result); _isConnected = true;
Console.WriteLine($"Failed to connect to {_networkPath}. Error {result}: {errorMessage}"); Console.WriteLine($"Connected to {_networkPath}");
throw new IOException($"Failed to connect to network path. Error {result}: {errorMessage}"); return;
} }
_isConnected = true; if (result == 1219) // Multiple connections
Console.WriteLine($"Successfully connected to {_networkPath}"); {
WNetCancelConnection2(_networkPath, 0, true);
Thread.Sleep(1000);
retries++;
continue;
}
throw new IOException($"Failed to connect. Error {result}: {GetNetworkErrorDescription(result)}");
}
catch
{
if (++retries >= 3) throw;
Thread.Sleep(1000);
}
}
}
} }
public void DisconnectFromNetworkShare() public void DisconnectFromNetworkShare()
{
lock (_lock)
{ {
if (!_isConnected) return; if (!_isConnected) return;
@ -57,36 +81,18 @@ public class NetworkShareAccess : IDisposable
{ {
int result = WNetCancelConnection2(_networkPath, 0, true); int result = WNetCancelConnection2(_networkPath, 0, true);
if (result != 0) if (result != 0)
{ Console.WriteLine($"Warning: Disconnect failed (Error {result})");
string errorMessage = GetNetworkErrorDescription(result);
Console.WriteLine($"Failed to disconnect from {_networkPath}. Error {result}: {errorMessage}");
throw new IOException($"Failed to disconnect from network path. Error {result}: {errorMessage}");
}
Console.WriteLine($"Successfully disconnected from {_networkPath}");
} }
finally finally
{ {
_isConnected = false; _isConnected = false;
} }
} }
public void Dispose()
{
try
{
DisconnectFromNetworkShare();
}
catch (Exception ex)
{
Console.WriteLine($"Error during disposal: {ex.Message}");
// Suppress disposal errors
}
} }
private string GetNetworkErrorDescription(int errorCode) public void Dispose() => DisconnectFromNetworkShare();
{
return errorCode switch private string GetNetworkErrorDescription(int errorCode) => errorCode switch
{ {
5 => "Access denied", 5 => "Access denied",
53 => "Network path not found", 53 => "Network path not found",
@ -96,7 +102,6 @@ public class NetworkShareAccess : IDisposable
1219 => "Multiple connections to a server or shared resource not allowed", 1219 => "Multiple connections to a server or shared resource not allowed",
_ => new Win32Exception(errorCode).Message _ => new Win32Exception(errorCode).Message
}; };
}
[DllImport("mpr.dll", CharSet = CharSet.Unicode)] [DllImport("mpr.dll", CharSet = CharSet.Unicode)]
private static extern int WNetAddConnection2(NetResource netResource, string password, string username, int flags); private static extern int WNetAddConnection2(NetResource netResource, string password, string username, int flags);
@ -104,9 +109,6 @@ public class NetworkShareAccess : IDisposable
[DllImport("mpr.dll", CharSet = CharSet.Unicode)] [DllImport("mpr.dll", CharSet = CharSet.Unicode)]
private static extern int WNetCancelConnection2(string name, int flags, bool force); private static extern int WNetCancelConnection2(string name, int flags, bool force);
[DllImport("mpr.dll", CharSet = CharSet.Unicode)]
private static extern int WNetGetConnection(string localName, StringBuilder remoteName, ref int length);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private class NetResource private class NetResource
{ {

View File

@ -49,18 +49,18 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator
private Image? LoadImage(string? imagePath) private Image? LoadImage(string? imagePath)
{ {
if (string.IsNullOrEmpty(imagePath)) if (string.IsNullOrEmpty(imagePath)) //check if photo is missing
{ {
return null; return null; // returns 'nothing' (safe)
} }
try try
{ {
return Image.FromFile(imagePath); return Image.FromFile(imagePath); //load photo
} }
catch catch
{ {
return null; return null; //if loading fails, returns 'nothing' (safe)
} }
} }
@ -208,7 +208,7 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator
{ {
text.Span(_classifyID == "SD" ? "☑ Sand " : "☐ Sand ").Style(TextStyle.Default.FontSize(10)); text.Span(_classifyID == "SD" ? "☑ Sand " : "☐ Sand ").Style(TextStyle.Default.FontSize(10));
text.Span(_classifyID == "NS" ? " ☑ Non-sandy " : " ☐ Non-sandy ").Style(TextStyle.Default.FontSize(10)); text.Span(_classifyID == "NS" ? " ☑ Non-sandy " : " ☐ Non-sandy ").Style(TextStyle.Default.FontSize(10));
text.Span(_classifyID == "CO" ? "☑ Coquina" : "☐ Coquina").Style(TextStyle.Default.FontSize(10)); text.Span(_classifyID == "CQ" ? "☑ Coquina" : "☐ Coquina").Style(TextStyle.Default.FontSize(10));
}); });
column.Item() column.Item()
@ -237,7 +237,7 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator
// Row 1: Photos ==================================== // Row 1: Photos ====================================
table.Cell().Element(CellStyle).Height(150) table.Cell().Element(CellStyle).Height(150)
.Image(LoadImage(_photoPath1) ?? null) // Just pass null if no image .Image(LoadImage(_photoPath1) ?? null) // Loads image or uses null. if exist, fill cell. if null, cell stay empty
.FitArea(); .FitArea();
table.Cell().Element(CellStyle).Height(150) table.Cell().Element(CellStyle).Height(150)
@ -288,28 +288,44 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator
columns.RelativeColumn(1); columns.RelativeColumn(1);
}); });
table.Cell().Element(CellStyle).Height(150) // Helper function to safely add image cells
.Image(LoadImage(_photoPath5) ?? null) // Just pass null if no image void AddOptionalImageCell(string imagePath)
.FitArea(); {
table.Cell().Element(CellStyle).Height(150) table.Cell().Element(CellStyle).Height(150).Element(cell =>
.Image(LoadImage(_photoPath6) ?? null) // Just pass null if no image {
.FitArea(); var image = LoadImage(imagePath);
if (image != null)
{
cell.Image(image).FitArea();
}
// If null, leaves an empty cell
});
}
table.Cell().Element(CellStyle).Text($"Figure 5: {_optionalName1}") // Row 1: Optional images 5 & 6
.FontSize(12).AlignLeft(); AddOptionalImageCell(_photoPath5);
table.Cell().Element(CellStyle).Text($"Figure 6: {_optionalName2}") AddOptionalImageCell(_photoPath6);
// Row 2: Captions
table.Cell().Element(CellStyle)
.Text(string.IsNullOrEmpty(_photoPath5) ? "" : $"Figure 5: {_optionalName1}")
.FontSize(12).AlignLeft(); .FontSize(12).AlignLeft();
table.Cell().Element(CellStyle).Height(150) table.Cell().Element(CellStyle)
.Image(LoadImage(_photoPath7) ?? null) // Just pass null if no image .Text(string.IsNullOrEmpty(_photoPath6) ? "" : $"Figure 6: {_optionalName2}")
.FitArea();
table.Cell().Element(CellStyle).Height(150)
.Image(LoadImage(_photoPath8) ?? null) // Just pass null if no image
.FitArea();
table.Cell().Element(CellStyle).Text($"Figure 7: {_optionalName3}")
.FontSize(12).AlignLeft(); .FontSize(12).AlignLeft();
table.Cell().Element(CellStyle).Text($"Figure 8: {_optionalName4}")
// Row 3: Optional images 7 & 8
AddOptionalImageCell(_photoPath7);
AddOptionalImageCell(_photoPath8);
// Row 4: Captions
table.Cell().Element(CellStyle)
.Text(string.IsNullOrEmpty(_photoPath7) ? "" : $"Figure 7: {_optionalName3}")
.FontSize(12).AlignLeft();
table.Cell().Element(CellStyle)
.Text(string.IsNullOrEmpty(_photoPath8) ? "" : $"Figure 8: {_optionalName4}")
.FontSize(12).AlignLeft(); .FontSize(12).AlignLeft();
}); });