From 833b4a6e7fdd412e20ade9f865c44fc17ca1389c Mon Sep 17 00:00:00 2001 From: Andre Lafleur Date: Thu, 5 Feb 2026 23:58:08 +0800 Subject: [PATCH 1/3] fix: improve ImageExtractorSample code quality - Add proper component unregistration in SampleModule.Unload() - Add error handling with MessageBox in SampleImageExtractor - Fix VCardReader to correctly extract FirstName from N: field - Make photo regex more flexible for different vCard formats --- .../SampleImageExtractor.cs | 19 ++++++++++--- .../ImageExtractorSample/SampleModule.cs | 13 ++++++--- .../ImageExtractorSample/VCardReader.cs | 27 +++++++++++++++---- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/Samples/Workspace SDK/ImageExtractorSample/SampleImageExtractor.cs b/Samples/Workspace SDK/ImageExtractorSample/SampleImageExtractor.cs index 9f053b1..71ed29d 100644 --- a/Samples/Workspace SDK/ImageExtractorSample/SampleImageExtractor.cs +++ b/Samples/Workspace SDK/ImageExtractorSample/SampleImageExtractor.cs @@ -4,6 +4,7 @@ namespace Genetec.Dap.CodeSamples; using System; +using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; using Microsoft.Win32; @@ -17,16 +18,26 @@ public sealed class SampleImageExtractor : ImageExtractor public override Guid UniqueId { get; } = new Guid("5EDBB0B6-8253-433E-99A1-9021E498437A"); - public override ImageSource GetImage() { - var openFileDialog = new OpenFileDialog + var dialog = new OpenFileDialog { Filter = "vCard files (*.vcf)|*.vcf|All files (*.*)|*.*", - Title = "Open vCard File" + Title = "Select vCard File" }; - return openFileDialog.ShowDialog() == true ? VCardReader.ReadVCard(openFileDialog.FileName)?.Picture : null; + if (dialog.ShowDialog() != true) + return null; + + try + { + return VCardReader.ReadVCard(dialog.FileName)?.Picture; + } + catch (Exception ex) + { + MessageBox.Show($"Failed to read vCard file: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); + return null; + } } public override bool SupportsContext(ImageExtractorContext context) diff --git a/Samples/Workspace SDK/ImageExtractorSample/SampleModule.cs b/Samples/Workspace SDK/ImageExtractorSample/SampleModule.cs index f1f48d8..d443c47 100644 --- a/Samples/Workspace SDK/ImageExtractorSample/SampleModule.cs +++ b/Samples/Workspace SDK/ImageExtractorSample/SampleModule.cs @@ -7,16 +7,23 @@ namespace Genetec.Dap.CodeSamples; public class SampleModule : Module { + private SampleImageExtractor m_imageExtractor; + static SampleModule() => AssemblyResolver.Initialize(); public override void Load() { - var component = new SampleImageExtractor(); - component.Initialize(Workspace); - Workspace.Components.Register(component); + m_imageExtractor = new SampleImageExtractor(); + m_imageExtractor.Initialize(Workspace); + Workspace.Components.Register(m_imageExtractor); } public override void Unload() { + if (m_imageExtractor != null) + { + Workspace.Components.Unregister(m_imageExtractor); + m_imageExtractor = null; + } } } \ No newline at end of file diff --git a/Samples/Workspace SDK/ImageExtractorSample/VCardReader.cs b/Samples/Workspace SDK/ImageExtractorSample/VCardReader.cs index 8209c34..070770b 100644 --- a/Samples/Workspace SDK/ImageExtractorSample/VCardReader.cs +++ b/Samples/Workspace SDK/ImageExtractorSample/VCardReader.cs @@ -16,10 +16,14 @@ public class VCardReader public static VCard ReadVCard(string filePath) { string vCardText = File.ReadAllText(filePath); + + // N: field format is LastName;FirstName;MiddleName;Prefix;Suffix + string[] nameParts = ExtractField(vCardText, "N:").Split(';'); + var vcard = new VCard { - FirstName = ExtractField(vCardText, "FN:"), - LastName = ExtractField(vCardText, "N:").Split(';')[0], // Assuming last name is the first component in the N: field + LastName = nameParts.Length > 0 ? nameParts[0] : string.Empty, + FirstName = nameParts.Length > 1 ? nameParts[1] : string.Empty, Note = ExtractField(vCardText, "NOTE:"), Picture = ExtractPhoto(vCardText) }; @@ -42,12 +46,25 @@ private static List ExtractEmails(string vCardText) private static ImageSource ExtractPhoto(string vCardText) { - Match photoMatch = Regex.Match(vCardText, @"PHOTO;ENCODING=b;TYPE=image/jpeg:(.*?)(\n(?![ \t])|\r\n(?![ \t])|$)", RegexOptions.Singleline); + // Match various vCard photo formats: + // PHOTO;ENCODING=b;TYPE=image/jpeg: + // PHOTO;ENCODING=BASE64;TYPE=JPEG: + // PHOTO;TYPE=JPEG;ENCODING=b: + // PHOTO;ENCODING=b;TYPE=image/png: + var photoMatch = Regex.Match(vCardText, + @"PHOTO;[^:]*(?:ENCODING=(?:b|BASE64))[^:]*:(.*?)(\n(?![ \t])|\r\n(?![ \t])|$)", + RegexOptions.Singleline | RegexOptions.IgnoreCase); + if (photoMatch.Success) { - string base64Data = photoMatch.Groups[1].Value.Trim().Replace("\n", "").Replace("\r", ""); + string base64Data = photoMatch.Groups[1].Value + .Trim() + .Replace("\n", "") + .Replace("\r", ""); + + byte[] imageBytes = Convert.FromBase64String(base64Data); - using var stream = new MemoryStream(Convert.FromBase64String(base64Data)); + using var stream = new MemoryStream(imageBytes); var bitmap = new BitmapImage(); bitmap.BeginInit(); bitmap.StreamSource = stream; From 83c90b6623d16514b86b944f386bba531250df05 Mon Sep 17 00:00:00 2001 From: Andre Lafleur <158597251+alafleur-genetec@users.noreply.github.com> Date: Fri, 6 Feb 2026 09:24:52 +0800 Subject: [PATCH 2/3] Update Samples/Workspace SDK/ImageExtractorSample/VCardReader.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Samples/Workspace SDK/ImageExtractorSample/VCardReader.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Samples/Workspace SDK/ImageExtractorSample/VCardReader.cs b/Samples/Workspace SDK/ImageExtractorSample/VCardReader.cs index 070770b..da0b15c 100644 --- a/Samples/Workspace SDK/ImageExtractorSample/VCardReader.cs +++ b/Samples/Workspace SDK/ImageExtractorSample/VCardReader.cs @@ -18,7 +18,10 @@ public static VCard ReadVCard(string filePath) string vCardText = File.ReadAllText(filePath); // N: field format is LastName;FirstName;MiddleName;Prefix;Suffix - string[] nameParts = ExtractField(vCardText, "N:").Split(';'); + string nameField = ExtractField(vCardText, "N:"); + string[] nameParts = string.IsNullOrEmpty(nameField) + ? Array.Empty() + : nameField.Split(';'); var vcard = new VCard { From 3a9f4144e71b6eef540c31d5eec008d2915f092f Mon Sep 17 00:00:00 2001 From: Andre Lafleur Date: Fri, 6 Feb 2026 17:31:35 +0800 Subject: [PATCH 3/3] Refactor vCard reading: remove error handling and MessageBox Simplified the image extraction method by removing the try-catch block and MessageBox error notification when reading vCard files. Now, exceptions are not caught within the method, and the result is returned directly. Also adjusted using directives for clarity. --- .../ImageExtractorSample/SampleImageExtractor.cs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/Samples/Workspace SDK/ImageExtractorSample/SampleImageExtractor.cs b/Samples/Workspace SDK/ImageExtractorSample/SampleImageExtractor.cs index 71ed29d..809f5da 100644 --- a/Samples/Workspace SDK/ImageExtractorSample/SampleImageExtractor.cs +++ b/Samples/Workspace SDK/ImageExtractorSample/SampleImageExtractor.cs @@ -3,12 +3,11 @@ namespace Genetec.Dap.CodeSamples; +using Microsoft.Win32; +using Sdk.Workspace.Components.ImageExtractor; using System; -using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; -using Microsoft.Win32; -using Sdk.Workspace.Components.ImageExtractor; public sealed class SampleImageExtractor : ImageExtractor { @@ -29,15 +28,7 @@ public override ImageSource GetImage() if (dialog.ShowDialog() != true) return null; - try - { - return VCardReader.ReadVCard(dialog.FileName)?.Picture; - } - catch (Exception ex) - { - MessageBox.Show($"Failed to read vCard file: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); - return null; - } + return VCardReader.ReadVCard(dialog.FileName)?.Picture; } public override bool SupportsContext(ImageExtractorContext context)