From a2ee35d462774d3615bea32abb4657756d93dcd8 Mon Sep 17 00:00:00 2001 From: misya Date: Wed, 21 May 2025 17:23:29 +0800 Subject: [PATCH] fix image generation when null --- Areas/MMS/Models/NetworkAccessService.cs | 126 ++++++++++---------- Areas/MMS/Models/PDFGenerator/TarBallPDF.cs | 64 ++++++---- 2 files changed, 104 insertions(+), 86 deletions(-) diff --git a/Areas/MMS/Models/NetworkAccessService.cs b/Areas/MMS/Models/NetworkAccessService.cs index 68c1dcd..545e48a 100644 --- a/Areas/MMS/Models/NetworkAccessService.cs +++ b/Areas/MMS/Models/NetworkAccessService.cs @@ -3,22 +3,22 @@ using System.IO; using System.Runtime.InteropServices; using System.Text; using System.ComponentModel; +using System.Threading; public class NetworkShareAccess : IDisposable { private readonly string _networkPath; private readonly string _username; private readonly string _password; + private bool _isConnected = false; + private static readonly object _lock = new object(); public NetworkShareAccess(string networkPath, string username, string password) { - // Validate and normalize the network path _networkPath = networkPath?.Trim().Replace('/', '\\') ?? throw new ArgumentNullException(nameof(networkPath)); if (!_networkPath.StartsWith(@"\\")) - { throw new ArgumentException("Network path must start with \\\\"); - } _username = username ?? throw new ArgumentNullException(nameof(username)); _password = password ?? throw new ArgumentNullException(nameof(password)); @@ -26,77 +26,82 @@ public class NetworkShareAccess : IDisposable public void ConnectToNetworkPath() { - if (_isConnected) return; - - var netResource = new NetResource + lock (_lock) { - Scope = ResourceScope.GlobalNetwork, - ResourceType = ResourceType.Disk, - DisplayType = ResourceDisplayType.Share, - RemoteName = _networkPath - }; + if (_isConnected) return; - int result = WNetAddConnection2(netResource, _password, _username, 0); + int retries = 0; + while (retries < 3) + { + try + { + var netResource = new NetResource + { + Scope = ResourceScope.GlobalNetwork, + ResourceType = ResourceType.Disk, + DisplayType = ResourceDisplayType.Share, + RemoteName = _networkPath + }; - if (result != 0) - { - string errorMessage = GetNetworkErrorDescription(result); - Console.WriteLine($"Failed to connect to {_networkPath}. Error {result}: {errorMessage}"); - throw new IOException($"Failed to connect to network path. Error {result}: {errorMessage}"); + int result = WNetAddConnection2(netResource, _password, _username, 0); + + if (result == 0) + { + _isConnected = true; + Console.WriteLine($"Connected to {_networkPath}"); + return; + } + + if (result == 1219) // Multiple connections + { + 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); + } + } } - - _isConnected = true; - Console.WriteLine($"Successfully connected to {_networkPath}"); } public void DisconnectFromNetworkShare() { - if (!_isConnected) return; - - try + lock (_lock) { - int result = WNetCancelConnection2(_networkPath, 0, true); - if (result != 0) + if (!_isConnected) return; + + try { - 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}"); + int result = WNetCancelConnection2(_networkPath, 0, true); + if (result != 0) + Console.WriteLine($"Warning: Disconnect failed (Error {result})"); + } + finally + { + _isConnected = false; } - - Console.WriteLine($"Successfully disconnected from {_networkPath}"); - } - finally - { - _isConnected = false; } } - public void Dispose() + public void Dispose() => DisconnectFromNetworkShare(); + + private string GetNetworkErrorDescription(int errorCode) => errorCode switch { - try - { - DisconnectFromNetworkShare(); - } - catch (Exception ex) - { - Console.WriteLine($"Error during disposal: {ex.Message}"); - // Suppress disposal errors - } - } - - private string GetNetworkErrorDescription(int errorCode) - { - return errorCode switch - { - 5 => "Access denied", - 53 => "Network path not found", - 67 => "Network name not found", - 85 => "Network connection already exists", - 86 => "Invalid password", - 1219 => "Multiple connections to a server or shared resource not allowed", - _ => new Win32Exception(errorCode).Message - }; - } + 5 => "Access denied", + 53 => "Network path not found", + 67 => "Network name not found", + 85 => "Network connection already exists", + 86 => "Invalid password", + 1219 => "Multiple connections to a server or shared resource not allowed", + _ => new Win32Exception(errorCode).Message + }; [DllImport("mpr.dll", CharSet = CharSet.Unicode)] 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)] 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)] private class NetResource { diff --git a/Areas/MMS/Models/PDFGenerator/TarBallPDF.cs b/Areas/MMS/Models/PDFGenerator/TarBallPDF.cs index da2f52e..597c9aa 100644 --- a/Areas/MMS/Models/PDFGenerator/TarBallPDF.cs +++ b/Areas/MMS/Models/PDFGenerator/TarBallPDF.cs @@ -49,18 +49,18 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator 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 { - return Image.FromFile(imagePath); + return Image.FromFile(imagePath); //load photo } 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 == "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() @@ -237,7 +237,7 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator // Row 1: Photos ==================================== 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(); table.Cell().Element(CellStyle).Height(150) @@ -288,28 +288,44 @@ namespace PSTW_CentralSystem.Areas.MMS.Models.PDFGenerator columns.RelativeColumn(1); }); - table.Cell().Element(CellStyle).Height(150) - .Image(LoadImage(_photoPath5) ?? null) // Just pass null if no image - .FitArea(); - table.Cell().Element(CellStyle).Height(150) - .Image(LoadImage(_photoPath6) ?? null) // Just pass null if no image - .FitArea(); + // Helper function to safely add image cells + void AddOptionalImageCell(string imagePath) + { + table.Cell().Element(CellStyle).Height(150).Element(cell => + { + 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}") - .FontSize(12).AlignLeft(); - table.Cell().Element(CellStyle).Text($"Figure 6: {_optionalName2}") + // Row 1: Optional images 5 & 6 + AddOptionalImageCell(_photoPath5); + AddOptionalImageCell(_photoPath6); + + // Row 2: Captions + table.Cell().Element(CellStyle) + .Text(string.IsNullOrEmpty(_photoPath5) ? "" : $"Figure 5: {_optionalName1}") .FontSize(12).AlignLeft(); - table.Cell().Element(CellStyle).Height(150) - .Image(LoadImage(_photoPath7) ?? null) // Just pass null if no image - .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}") + table.Cell().Element(CellStyle) + .Text(string.IsNullOrEmpty(_photoPath6) ? "" : $"Figure 6: {_optionalName2}") .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(); });