From e58ff598877591340d117930115198d0e0f9b3dc Mon Sep 17 00:00:00 2001 From: Carl Tierney Date: Fri, 25 Apr 2025 14:14:29 -0500 Subject: [PATCH 1/4] updated xstfile to accept a stream instead of a file path --- src/XstReader.Api/XstFile.cs | 256 +++++++++++++++++++---------------- 1 file changed, 137 insertions(+), 119 deletions(-) diff --git a/src/XstReader.Api/XstFile.cs b/src/XstReader.Api/XstFile.cs index 1b7f9cf..6ef1f69 100644 --- a/src/XstReader.Api/XstFile.cs +++ b/src/XstReader.Api/XstFile.cs @@ -1,152 +1,170 @@ -// Project site: https://github.com/iluvadev/XstReader -// -// Based on the great work of Dijji. -// Original project: https://github.com/dijji/XstReader -// -// Issues: https://github.com/iluvadev/XstReader/issues -// License (Ms-PL): https://github.com/iluvadev/XstReader/blob/master/license.md -// -// Copyright (c) 2021, iluvadev, and released under Ms-PL License. -// Copyright (c) 2016, Dijji, and released under Ms-PL. This can be found in the root of this distribution. - -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.ComponentModel; using System.IO; +using System; using XstReader.ElementProperties; +using XstReader; -namespace XstReader +public class XstFile : XstElement, IDisposable { - // See: https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxcmsg/7fd7ec40-deec-4c06-9493-1bc06b349682 + private NDB _Ndb; + internal new NDB Ndb => _Ndb ?? (_Ndb = new NDB(this)); + private LTP _Ltp; + internal new LTP Ltp => _Ltp ?? (_Ltp = new LTP(Ndb)); - // The code here implements the messaging layer, which depends on and invokes the NDP and LTP layers + private string _FileName = null; + private Stream _InputStream = null; /// - /// Main handling for xst (.ost and .pst) files + /// FileName of the .pst or .ost file to read /// - public class XstFile : XstElement, IDisposable + public string FileName { - private NDB _Ndb; - internal new NDB Ndb => _Ndb ?? (_Ndb = new NDB(this)); - - private LTP _Ltp; - internal new LTP Ltp => _Ltp ?? (_Ltp = new LTP(Ndb)); - - private string _FileName = null; - /// - /// FileName of the .pst or .ost file to read - /// - public string FileName { get => _FileName; set => SetFileName(value); } - private void SetFileName(string fileName) - { - _FileName = fileName; - ClearContents(); - } + get => _FileName; + set => SetFileName(value); + } - private FileStream _ReadStream = null; - internal FileStream ReadStream - { - get => _ReadStream ?? (_ReadStream = new FileStream(FileName, FileMode.Open, FileAccess.Read)); - } - internal object StreamLock { get; } = new object(); - - private XstFolder _RootFolder = null; - /// - /// The Root Folder of the XstFile. (Loaded when needed) - /// - public XstFolder RootFolder => _RootFolder ?? (_RootFolder = new XstFolder(this, new NID(EnidSpecial.NID_ROOT_FOLDER))); - - /// - /// The Path of this Element - /// - [DisplayName("Path")] - [Category("General")] - [Description(@"The Path of this Element")] - public override string Path => System.IO.Path.GetFileName(this.FileName); - - /// - /// The Parents of this Element - /// - [Browsable(false)] - public override XstElement Parent => null; - - - #region Ctor - /// - /// Ctor - /// - /// The .pst or .ost file to open - public XstFile(string fileName) : base(XstElementType.File) - { - FileName = fileName; - } - #endregion Ctor + private void SetFileName(string fileName) + { + _FileName = fileName; + _InputStream = null; // Clear the stream if a new file is set + ClearContents(); + } - private void ClearStream() + private FileStream _ReadStream = null; + internal FileStream ReadStream + { + get { - if (_ReadStream != null) - { - _ReadStream.Close(); - _ReadStream.Dispose(); - _ReadStream = null; - } + if (_InputStream != null) + throw new InvalidOperationException("Cannot access ReadStream when using a custom input stream."); + return _ReadStream ?? (_ReadStream = new FileStream(FileName, FileMode.Open, FileAccess.Read)); } + } - /// - /// Clears information and memory used in RootFolder - /// - private void ClearRootFolder() + internal Stream InputStream + { + get { - if (_RootFolder != null) - { - _RootFolder.ClearContents(); - _RootFolder = null; - } + if (_InputStream == null && _ReadStream == null) + throw new InvalidOperationException("No valid input stream or file stream is available."); + return _InputStream ?? ReadStream; } + } - /// - /// Clears all information and memory used by the object - /// - public override void ClearContents() - { - ClearStream(); - ClearRootFolder(); + internal object StreamLock { get; } = new object(); - _Ndb = null; - _Ltp = null; - } + private XstFolder _RootFolder = null; + /// + /// The Root Folder of the XstFile. (Loaded when needed) + /// + public XstFolder RootFolder => _RootFolder ?? (_RootFolder = new XstFolder(this, new NID(EnidSpecial.NID_ROOT_FOLDER))); - /// - /// Disposes memory used by the object - /// - public void Dispose() - { - ClearContents(); - } + /// + /// The Path of this Element + /// + [DisplayName("Path")] + [Category("General")] + [Description(@"The Path of this Element")] + public override string Path => System.IO.Path.GetFileName(this.FileName); - /// - /// Gets the String representation of the object - /// - /// - public override string ToString() - { - return System.IO.Path.GetFileName(FileName ?? ""); - } + /// + /// The Parents of this Element + /// + [Browsable(false)] + public override XstElement Parent => null; + + #region Ctor + /// + /// Constructor for file-based input + /// + /// The .pst or .ost file to open + public XstFile(string fileName) : base(XstElementType.File) + { + FileName = fileName; + } + + /// + /// Constructor for stream-based input + /// + /// The input stream containing the .pst or .ost data + public XstFile(Stream inputStream) : base(XstElementType.File) + { + _InputStream = inputStream ?? throw new ArgumentNullException(nameof(inputStream)); + _FileName = null; // Clear the file name since we're using a stream + } + #endregion Ctor - private protected override IEnumerable LoadProperties() + private void ClearStream() + { + if (_ReadStream != null) { - return new XstProperty[0]; + _ReadStream.Close(); + _ReadStream.Dispose(); + _ReadStream = null; } - private protected override XstProperty LoadProperty(PropertyCanonicalName tag) + if (_InputStream != null) { - return null; + _InputStream.Dispose(); + _InputStream = null; } + } - private protected override bool CheckProperty(PropertyCanonicalName tag) + /// + /// Clears information and memory used in RootFolder + /// + private void ClearRootFolder() + { + if (_RootFolder != null) { - return false; + _RootFolder.ClearContents(); + _RootFolder = null; } } + + /// + /// Clears all information and memory used by the object + /// + public override void ClearContents() + { + ClearStream(); + ClearRootFolder(); + + _Ndb = null; + _Ltp = null; + } + + /// + /// Disposes memory used by the object + /// + public void Dispose() + { + ClearContents(); + } + + /// + /// Gets the String representation of the object + /// + /// + public override string ToString() + { + return System.IO.Path.GetFileName(FileName ?? "Stream"); + } + + private protected override IEnumerable LoadProperties() + { + return new XstProperty[0]; + } + + private protected override XstProperty LoadProperty(PropertyCanonicalName tag) + { + return null; + } + + private protected override bool CheckProperty(PropertyCanonicalName tag) + { + return false; + } } From e21ac5720593e6cc687052d4e2dd3ad0a348cdd4 Mon Sep 17 00:00:00 2001 From: Carl Tierney Date: Fri, 25 Apr 2025 16:04:40 -0500 Subject: [PATCH 2/4] updated to .net 8, reworked to allow the library to work with a stream, updated nuget packages --- src/OldXstReader/MainWindow.xaml.cs | 4 +- src/OldXstReader/MessageView.cs | 2 +- src/OldXstReader/View.cs | 4 +- .../XstExporter.Portable.csproj | 2 +- src/XstReader.Api.Tests/MSTestSettings.cs | 1 + src/XstReader.Api.Tests/ReadingStreamTests.cs | 87 +++++++ .../XstReader.Api.Tests.csproj | 33 +++ src/XstReader.Api/Common/Map.cs | 2 +- src/XstReader.Api/LTP.cs | 11 +- src/XstReader.Api/NDB.cs | 6 +- src/XstReader.Api/XstAttachment.cs | 10 +- src/XstReader.Api/XstElement.cs | 26 +- src/XstReader.Api/XstFile.cs | 235 ++++++++---------- src/XstReader.Api/XstFolder.cs | 31 +-- src/XstReader.Api/XstMessage.cs | 26 +- src/XstReader.Api/XstProperty.cs | 8 +- src/XstReader.Api/XstPropertySet.cs | 16 +- src/XstReader.Api/XstReader.Api.csproj | 2 +- .../IXstDataSourcedControlT.cs | 2 +- .../XstReader.App.Common.csproj | 2 +- .../MsgKit/Structures/Properties.cs | 4 +- .../XstReader.Exporter.csproj | 6 +- src/XstReader.sln | 14 ++ .../Controls/XstAttachmentListControl.cs | 2 +- .../Controls/XstAttachmentViewControl.cs | 2 +- .../Controls/XstFolderTreeControl.cs | 2 +- .../Controls/XstMessageContentViewControl.cs | 2 +- .../Controls/XstMessageListControl.cs | 2 +- .../Controls/XstMessageViewControl.cs | 2 +- .../Controls/XstPropertiesControl.Designer.cs | 11 +- .../Controls/XstPropertiesControl.cs | 22 +- .../XstPropertiesInfoControl.Designer.cs | 8 +- .../Controls/XstPropertiesInfoControl.cs | 2 +- .../Controls/XstRecipientListControl.cs | 2 +- src/XstReader/MainForm.cs | 6 +- src/XstReader/Program.cs | 9 +- src/XstReader/WaitingForm.Designer.cs | 2 +- src/XstReader/XstReader.App.csproj | 14 +- 38 files changed, 337 insertions(+), 285 deletions(-) create mode 100644 src/XstReader.Api.Tests/MSTestSettings.cs create mode 100644 src/XstReader.Api.Tests/ReadingStreamTests.cs create mode 100644 src/XstReader.Api.Tests/XstReader.Api.Tests.csproj diff --git a/src/OldXstReader/MainWindow.xaml.cs b/src/OldXstReader/MainWindow.xaml.cs index 039e058..51e46fb 100644 --- a/src/OldXstReader/MainWindow.xaml.cs +++ b/src/OldXstReader/MainWindow.xaml.cs @@ -118,9 +118,7 @@ private void treeFolders_SelectedItemChanged(object sender, RoutedPropertyChange { try { - //Clear contents of prev selected folder - view.SelectedFolder?.Folder?.ClearContents(); - + FolderView fv = (FolderView)e.NewValue; view.SelectedFolder = fv; diff --git a/src/OldXstReader/MessageView.cs b/src/OldXstReader/MessageView.cs index 20c0304..f1ec31b 100644 --- a/src/OldXstReader/MessageView.cs +++ b/src/OldXstReader/MessageView.cs @@ -85,7 +85,7 @@ public bool IsSelected public void ClearContents() { - Message.ClearContents(); + Attachments.Clear(); } diff --git a/src/OldXstReader/View.cs b/src/OldXstReader/View.cs index e2cc305..f2a0a61 100644 --- a/src/OldXstReader/View.cs +++ b/src/OldXstReader/View.cs @@ -186,9 +186,9 @@ public void PopMessage() public void Clear() { - SelectedFolder?.Folder?.ClearContents(); + SelectedFolder = null; - CurrentMessage?.Message?.ClearContents(); + CurrentMessage = null; RootFolderViews.Clear(); stackMessage.Clear(); diff --git a/src/XstExporter.Portable/XstExporter.Portable.csproj b/src/XstExporter.Portable/XstExporter.Portable.csproj index f5e05cb..1215527 100644 --- a/src/XstExporter.Portable/XstExporter.Portable.csproj +++ b/src/XstExporter.Portable/XstExporter.Portable.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 2.0.1 2.0.1 2.0.1 diff --git a/src/XstReader.Api.Tests/MSTestSettings.cs b/src/XstReader.Api.Tests/MSTestSettings.cs new file mode 100644 index 0000000..aaf278c --- /dev/null +++ b/src/XstReader.Api.Tests/MSTestSettings.cs @@ -0,0 +1 @@ +[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)] diff --git a/src/XstReader.Api.Tests/ReadingStreamTests.cs b/src/XstReader.Api.Tests/ReadingStreamTests.cs new file mode 100644 index 0000000..3b1ac62 --- /dev/null +++ b/src/XstReader.Api.Tests/ReadingStreamTests.cs @@ -0,0 +1,87 @@ +using System; +using System.Diagnostics; +using System.Security.Cryptography.X509Certificates; +using XstReader.Api; + + +namespace XstReader.Api.Tests +{ + [TestClass] + public sealed class ReadingStreamTests + { + + [TestMethod] + public void OpenFileWithXstReader() + { + // Arrange + string filePath = Path.Combine("D:\\ediscovery\\Test_Export\\01.20.2025-1204PM\\Exchange\\carl.tierney@vision2.com.pst"); + + + using var xstFile = new XstFile(filePath); + + + // Assert + Assert.IsNotNull(xstFile); + Assert.IsNotNull(xstFile.RootFolder); + } + + + [TestMethod] + public void OpenFileAndPassStreamToXstReader() + { + // Arrange + string filePath = Path.Combine("D:\\ediscovery\\Test_Export\\01.20.2025-1204PM\\Exchange\\carl.tierney@vision2.com.pst"); + using FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); + // Act + using var xstFile = new XstFile(fileStream); + + + // Assert + Assert.IsNotNull(xstFile); + Assert.IsNotNull(xstFile.RootFolder); + } + + [TestMethod] + public void ReadInboxFromStream() + { + string filePath = Path.Combine("D:\\ediscovery\\Test_Export\\01.20.2025-1204PM\\Exchange\\carl.tierney@vision2.com.pst"); + using FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); + // Act + using var xstFile = new XstFile(fileStream); + + + // Assert + Assert.IsNotNull(xstFile); + Assert.IsNotNull(xstFile.RootFolder); + + + FindInboxMessages(xstFile.RootFolder); + } + + public bool FindInboxMessages(XstFolder folder) + { + if (folder.DisplayName == "Inbox") + { + foreach (var m in folder.Messages) + { + Debug.WriteLine($"{m.InternetMessageId} - {m.Subject} - {m.Date} - has attachments:{m.HasAttachments}"); + foreach (var a in m.Attachments) + { + Debug.WriteLine($"Attachment: {a.DisplayName} - {a.Size} bytes"); + } + } + + return true; + } + + foreach(var f in folder.Folders) + { + if (FindInboxMessages(f)) + break; + } + + return false; + } + + } +} diff --git a/src/XstReader.Api.Tests/XstReader.Api.Tests.csproj b/src/XstReader.Api.Tests/XstReader.Api.Tests.csproj new file mode 100644 index 0000000..2b29218 --- /dev/null +++ b/src/XstReader.Api.Tests/XstReader.Api.Tests.csproj @@ -0,0 +1,33 @@ + + + + net8.0 + latest + enable + enable + true + Exe + true + + true + + + + + + + + + + + + + + + + + + diff --git a/src/XstReader.Api/Common/Map.cs b/src/XstReader.Api/Common/Map.cs index 51d7c42..01d1745 100644 --- a/src/XstReader.Api/Common/Map.cs +++ b/src/XstReader.Api/Common/Map.cs @@ -19,7 +19,7 @@ namespace XstReader.Common internal static class Map { // Read enough bytes from the file stream at the current position to populate specified type T - public static T ReadType(FileStream fs) + public static T ReadType(Stream fs) { byte[] buffer = new byte[Marshal.SizeOf(typeof(T))]; fs.Read(buffer, 0, Marshal.SizeOf(typeof(T))); diff --git a/src/XstReader.Api/LTP.cs b/src/XstReader.Api/LTP.cs index ef2bcdf..210aebb 100644 --- a/src/XstReader.Api/LTP.cs +++ b/src/XstReader.Api/LTP.cs @@ -198,7 +198,16 @@ public IEnumerable ReadTable(BTree subNodeTree, // Test for the presence of an optional table in the supplied sub node tree public bool IsTablePresent(BTree subNodeTree, NID nid) - => (subNodeTree != null && NDB.LookupSubNode(subNodeTree, nid) != null); + { + if(subNodeTree != null) + { + var subNode = NDB.LookupSubNode(subNodeTree, nid); + return subNode != null; + } + + return false; + } + #endregion diff --git a/src/XstReader.Api/NDB.cs b/src/XstReader.Api/NDB.cs index cbc54a4..76ce232 100644 --- a/src/XstReader.Api/NDB.cs +++ b/src/XstReader.Api/NDB.cs @@ -233,7 +233,7 @@ private void ReadDeferredIndex(TreeIntermediate inter) inter.fileOffset = null; } // Read a page containing part of a node or data block B-tree, and build the corresponding data structure - private void ReadBTPageUnicode(FileStream fs, ulong fileOffset, TreeIntermediate parent) + private void ReadBTPageUnicode(Stream fs, ulong fileOffset, TreeIntermediate parent) { fs.Seek((long)fileOffset, SeekOrigin.Begin); var p = Map.ReadType(fs); @@ -286,7 +286,7 @@ private void ReadBTPageUnicode(FileStream fs, ulong fileOffset, TreeIntermediate } // Read a page containing part of a node or data block B-tree, and build the corresponding data structure - private void ReadBTPageUnicode4K(FileStream fs, ulong fileOffset, TreeIntermediate parent) + private void ReadBTPageUnicode4K(Stream fs, ulong fileOffset, TreeIntermediate parent) { fs.Seek((long)fileOffset, SeekOrigin.Begin); var p = Map.ReadType(fs); @@ -338,7 +338,7 @@ private void ReadBTPageUnicode4K(FileStream fs, ulong fileOffset, TreeIntermedia } } - private void ReadBTPageANSI(FileStream fs, ulong fileOffset, TreeIntermediate parent) + private void ReadBTPageANSI(Stream fs, ulong fileOffset, TreeIntermediate parent) { fs.Seek((long)fileOffset, SeekOrigin.Begin); var p = Map.ReadType(fs); diff --git a/src/XstReader.Api/XstAttachment.cs b/src/XstReader.Api/XstAttachment.cs index 6996040..8091824 100644 --- a/src/XstReader.Api/XstAttachment.cs +++ b/src/XstReader.Api/XstAttachment.cs @@ -246,8 +246,7 @@ private XstMessage GetAttachedEmailMessage() SubNodeTreeParentAttachment = subNodeTreeAttachment, }; - // Read the basic and contents properties - _AttachedEmailMessage.BodyLoader = () => Ltp.ReadProperties(subNodeTreeAttachment, _AttachedEmailMessage.Nid, _AttachedEmailMessage.Properties, true); + } else throw new XstException("Unexpected data type for attached message"); @@ -444,12 +443,7 @@ private void ClearAttachmentContent() _Content = null; } - internal override void ClearContentsInternal() - { - base.ClearContentsInternal(); - ClearAttachedEmailMessage(); - ClearAttachmentContent(); - } + /// /// Gets the String representation of the object diff --git a/src/XstReader.Api/XstElement.cs b/src/XstReader.Api/XstElement.cs index 5b3e759..e74cb7c 100644 --- a/src/XstReader.Api/XstElement.cs +++ b/src/XstReader.Api/XstElement.cs @@ -19,7 +19,7 @@ namespace XstReader /// /// Base class for an element inside a pst or ost file /// - public abstract class XstElement + public abstract class XstElement : IDisposable { /// /// The Type of the element @@ -129,24 +129,7 @@ protected XstElement(XstElementType elementType) } #endregion Ctor - private protected void ClearProperties() - { - Properties.ClearContents(); - //_Properties = null; - } - - /// - /// Clear all Contents - /// - public virtual void ClearContents() - { - new Thread(() => { ClearContentsInternal(); GC.Collect(); }).Start(); - } - - internal virtual void ClearContentsInternal() - { - ClearProperties(); - } + /// /// Gets the String representation of the object @@ -154,5 +137,10 @@ internal virtual void ClearContentsInternal() /// public override string ToString() => DisplayName; + + public void Dispose() + { + + } } } diff --git a/src/XstReader.Api/XstFile.cs b/src/XstReader.Api/XstFile.cs index 6ef1f69..13d2422 100644 --- a/src/XstReader.Api/XstFile.cs +++ b/src/XstReader.Api/XstFile.cs @@ -1,170 +1,129 @@ -using System.Collections.Generic; +// Project site: https://github.com/iluvadev/XstReader +// +// Based on the great work of Dijji. +// Original project: https://github.com/dijji/XstReader +// +// Issues: https://github.com/iluvadev/XstReader/issues +// License (Ms-PL): https://github.com/iluvadev/XstReader/blob/master/license.md +// +// Copyright (c) 2021, iluvadev, and released under Ms-PL License. +// Copyright (c) 2016, Dijji, and released under Ms-PL. This can be found in the root of this distribution. + +using System; +using System.Collections.Generic; using System.ComponentModel; using System.IO; -using System; using XstReader.ElementProperties; -using XstReader; -public class XstFile : XstElement, IDisposable +namespace XstReader { - private NDB _Ndb; - internal new NDB Ndb => _Ndb ?? (_Ndb = new NDB(this)); + // See: https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxcmsg/7fd7ec40-deec-4c06-9493-1bc06b349682 - private LTP _Ltp; - internal new LTP Ltp => _Ltp ?? (_Ltp = new LTP(Ndb)); - private string _FileName = null; - private Stream _InputStream = null; + // The code here implements the messaging layer, which depends on and invokes the NDP and LTP layers /// - /// FileName of the .pst or .ost file to read + /// Main handling for xst (.ost and .pst) files /// - public string FileName - { - get => _FileName; - set => SetFileName(value); - } - - private void SetFileName(string fileName) - { - _FileName = fileName; - _InputStream = null; // Clear the stream if a new file is set - ClearContents(); - } - - private FileStream _ReadStream = null; - internal FileStream ReadStream + public class XstFile : XstElement, IDisposable { - get + private NDB _Ndb; + internal new NDB Ndb => _Ndb ?? (_Ndb = new NDB(this)); + + private LTP _Ltp; + internal new LTP Ltp => _Ltp ?? (_Ltp = new LTP(Ndb)); + + private string _FileName = null; + /// + /// FileName of the .pst or .ost file to read + /// + public string FileName { get => _FileName; set => SetFileName(value); } + private void SetFileName(string fileName) { - if (_InputStream != null) - throw new InvalidOperationException("Cannot access ReadStream when using a custom input stream."); - return _ReadStream ?? (_ReadStream = new FileStream(FileName, FileMode.Open, FileAccess.Read)); + _FileName = fileName; + } - } - internal Stream InputStream - { - get + private Stream _ReadStream = null; + internal Stream ReadStream { - if (_InputStream == null && _ReadStream == null) - throw new InvalidOperationException("No valid input stream or file stream is available."); - return _InputStream ?? ReadStream; + get => _ReadStream ?? (_ReadStream = new FileStream(FileName, FileMode.Open, FileAccess.Read)); + private set + { + _ReadStream = value; + } } - } - - internal object StreamLock { get; } = new object(); - - private XstFolder _RootFolder = null; - /// - /// The Root Folder of the XstFile. (Loaded when needed) - /// - public XstFolder RootFolder => _RootFolder ?? (_RootFolder = new XstFolder(this, new NID(EnidSpecial.NID_ROOT_FOLDER))); - - /// - /// The Path of this Element - /// - [DisplayName("Path")] - [Category("General")] - [Description(@"The Path of this Element")] - public override string Path => System.IO.Path.GetFileName(this.FileName); - - /// - /// The Parents of this Element - /// - [Browsable(false)] - public override XstElement Parent => null; - - #region Ctor - /// - /// Constructor for file-based input - /// - /// The .pst or .ost file to open - public XstFile(string fileName) : base(XstElementType.File) - { - FileName = fileName; - } - - /// - /// Constructor for stream-based input - /// - /// The input stream containing the .pst or .ost data - public XstFile(Stream inputStream) : base(XstElementType.File) - { - _InputStream = inputStream ?? throw new ArgumentNullException(nameof(inputStream)); - _FileName = null; // Clear the file name since we're using a stream - } - #endregion Ctor - - private void ClearStream() - { - if (_ReadStream != null) + internal object StreamLock { get; } = new object(); + + private XstFolder _RootFolder = null; + /// + /// The Root Folder of the XstFile. (Loaded when needed) + /// + public XstFolder RootFolder => _RootFolder ?? (_RootFolder = new XstFolder(this, new NID(EnidSpecial.NID_ROOT_FOLDER))); + + /// + /// The Path of this Element + /// + [DisplayName("Path")] + [Category("General")] + [Description(@"The Path of this Element")] + public override string Path => System.IO.Path.GetFileName(this.FileName); + + /// + /// The Parents of this Element + /// + [Browsable(false)] + public override XstElement Parent => null; + + + #region Ctor + /// + /// Ctor + /// + /// The .pst or .ost file to open + public XstFile(string fileName) : base(XstElementType.File) { - _ReadStream.Close(); - _ReadStream.Dispose(); - _ReadStream = null; + FileName = fileName; } - if (_InputStream != null) + /// + /// Ctor + /// + /// A stream that could be any stream file, memory, network + public XstFile(Stream stream) : base(XstElementType.File) { - _InputStream.Dispose(); - _InputStream = null; + ReadStream = stream; } - } + #endregion Ctor - /// - /// Clears information and memory used in RootFolder - /// - private void ClearRootFolder() - { - if (_RootFolder != null) + private void ClearStream() { - _RootFolder.ClearContents(); - _RootFolder = null; + if (_ReadStream != null) + { + _ReadStream.Close(); + _ReadStream.Dispose(); + _ReadStream = null; + } } - } - /// - /// Clears all information and memory used by the object - /// - public override void ClearContents() - { - ClearStream(); - ClearRootFolder(); - _Ndb = null; - _Ltp = null; - } - /// - /// Disposes memory used by the object - /// - public void Dispose() - { - ClearContents(); - } + + - /// - /// Gets the String representation of the object - /// - /// - public override string ToString() - { - return System.IO.Path.GetFileName(FileName ?? "Stream"); - } - - private protected override IEnumerable LoadProperties() - { - return new XstProperty[0]; - } + private protected override IEnumerable LoadProperties() + { + return new XstProperty[0]; + } - private protected override XstProperty LoadProperty(PropertyCanonicalName tag) - { - return null; - } + private protected override XstProperty LoadProperty(PropertyCanonicalName tag) + { + return null; + } - private protected override bool CheckProperty(PropertyCanonicalName tag) - { - return false; + private protected override bool CheckProperty(PropertyCanonicalName tag) + { + return false; + } } } diff --git a/src/XstReader.Api/XstFolder.cs b/src/XstReader.Api/XstFolder.cs index 0214364..70a9d2b 100644 --- a/src/XstReader.Api/XstFolder.cs +++ b/src/XstReader.Api/XstFolder.cs @@ -21,7 +21,7 @@ namespace XstReader /// /// Class for a Folder stored inside an .ost or .pst file /// - public class XstFolder : XstElement + public class XstFolder : XstElement, IDisposable { /// /// The Container File @@ -217,30 +217,9 @@ public IEnumerable GetMessages() #endregion Messages - private void ClearFolders() - { - if (_Folders != null) - foreach (var folder in _Folders) - folder.ClearContentsInternal(); - _Folders = null; - HasErrorInFolders = false; - ErrorInFolders = ""; - } - private void ClearMessages() - { - if (_Messages != null) - foreach (var message in _Messages) - message.ClearContentsInternal(); - _Messages = null; - HasErrorInMessages = false; - ErrorInMessages = ""; - } - internal override void ClearContentsInternal() - { - base.ClearContentsInternal(); - ClearFolders(); - ClearMessages(); - } + + + /// /// Gets the String representation of the object @@ -254,5 +233,7 @@ public override string ToString() return $"[Root] {XstFile}"; return string.Empty; } + + } } diff --git a/src/XstReader.Api/XstMessage.cs b/src/XstReader.Api/XstMessage.cs index 4b4be59..8bda362 100644 --- a/src/XstReader.Api/XstMessage.cs +++ b/src/XstReader.Api/XstMessage.cs @@ -255,7 +255,7 @@ public virtual MessageFlags? Flags private BTree _SubNodeTreeProperties = null; internal BTree SubNodeTreeProperties { - get => _SubNodeTreeProperties ?? (_SubNodeTreeProperties = BodyLoader?.Invoke()); + get => _SubNodeTreeProperties ?? (_SubNodeTreeProperties = LoadBody()); set => _SubNodeTreeProperties = value; } internal BTree SubNodeTreeParentAttachment = null; @@ -270,16 +270,11 @@ internal BTree SubNodeTreeProperties #endregion Message State Class Properties #region Body Class Properties - private Func> _BodyLoader = null; - internal Func> BodyLoader + + + internal BTree LoadBody() { - get => _BodyLoader; - set - { - if (_BodyLoader != null) - ClearContents(); - _BodyLoader = value; - } + return Ltp.ReadProperties(Nid, Properties); } private Encoding _Encoding = null; @@ -414,7 +409,7 @@ internal void Initialize(NID nid, XstFolder folder) // Read the contents properties //BodyLoader = () => Ltp.ReadProperties(Nid, PropertyGetters.MessageContentProperties, this); - BodyLoader = () => Ltp.ReadProperties(Nid, Properties); + //_BodyLoader = () => Ltp.ReadProperties(Nid, Properties); } #endregion Ctor @@ -600,15 +595,6 @@ private void ClearBody() _NativeBody = null; _Body = null; } - internal override void ClearContentsInternal() - { - base.ClearContentsInternal(); - - _Flags = null; - ClearBody(); - ClearAttachments(); - ClearRecipients(); - } internal void ProcessSignedOrEncrypted() { diff --git a/src/XstReader.Api/XstProperty.cs b/src/XstReader.Api/XstProperty.cs index 4974973..57fe2c9 100644 --- a/src/XstReader.Api/XstProperty.cs +++ b/src/XstReader.Api/XstProperty.cs @@ -20,7 +20,7 @@ namespace XstReader /// /// A Property of a pst/ost element /// - public class XstProperty : XstPropertyBase + public class XstProperty : XstPropertyBase, IDisposable { internal Func ValueGetter { get; set; } = null; private dynamic _Value; @@ -104,10 +104,8 @@ internal XstProperty CopyToNew(PropertyCanonicalName newTag) _Value = this._Value, }; - /// - /// Clear all contents and memory used - /// - public void ClearContents() + + public void Dispose() { _Value = null; } diff --git a/src/XstReader.Api/XstPropertySet.cs b/src/XstReader.Api/XstPropertySet.cs index 21ae0bc..bf84709 100644 --- a/src/XstReader.Api/XstPropertySet.cs +++ b/src/XstReader.Api/XstPropertySet.cs @@ -19,7 +19,7 @@ namespace XstReader /// /// A set of Properties of a pst/ost Element /// - public class XstPropertySet + public class XstPropertySet : IDisposable { private Dictionary _DicProperties = null; private Dictionary DicProperties @@ -189,19 +189,13 @@ internal void Add(IEnumerable properties) Add(property); } + /// - /// Clear contents and memory + /// Disposes the PropertySet /// - public void ClearContents() + public void Dispose() { - if (_DicProperties != null) - { - foreach (var prop in _DicProperties.Values) - prop.ClearContents(); - _DicProperties.Clear(); - } - _DicProperties = null; - IsLoaded = false; + _DicProperties?.Clear(); } } } diff --git a/src/XstReader.Api/XstReader.Api.csproj b/src/XstReader.Api/XstReader.Api.csproj index 784dc4a..3c0c2b2 100644 --- a/src/XstReader.Api/XstReader.Api.csproj +++ b/src/XstReader.Api/XstReader.Api.csproj @@ -41,7 +41,7 @@ Original project: https://github.com/dijji/XstReader - + diff --git a/src/XstReader.Common/IXstDataSourcedControlT.cs b/src/XstReader.Common/IXstDataSourcedControlT.cs index aa2407b..ab03a70 100644 --- a/src/XstReader.Common/IXstDataSourcedControlT.cs +++ b/src/XstReader.Common/IXstDataSourcedControlT.cs @@ -21,7 +21,7 @@ public T? DataSource public T? GetDataSource(); public void SetDataSource(T? dataSource); - public void ClearContents(); + } } diff --git a/src/XstReader.Common/XstReader.App.Common.csproj b/src/XstReader.Common/XstReader.App.Common.csproj index 2e245e2..57b765b 100644 --- a/src/XstReader.Common/XstReader.App.Common.csproj +++ b/src/XstReader.Common/XstReader.App.Common.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 enable enable $(MSBuildProjectName.Replace(" ", "_")) diff --git a/src/XstReader.Exporter/MsgKit/Structures/Properties.cs b/src/XstReader.Exporter/MsgKit/Structures/Properties.cs index 7e72b67..1fdd308 100644 --- a/src/XstReader.Exporter/MsgKit/Structures/Properties.cs +++ b/src/XstReader.Exporter/MsgKit/Structures/Properties.cs @@ -470,11 +470,11 @@ private void AddMultiValueStreams(PropertyTag mapiTag, object obj, PropertyFl break; case TypeCode.SByte: - data = BitConverter.GetBytes((sbyte)obj); + data = BitConverter.GetBytes((ushort)Convert.ToByte(obj)); break; case TypeCode.Byte: - data = BitConverter.GetBytes((byte)obj); + data = BitConverter.GetBytes((short)Convert.ToByte(obj)); break; case TypeCode.Int16: data = BitConverter.GetBytes((short)obj); diff --git a/src/XstReader.Exporter/XstReader.Exporter.csproj b/src/XstReader.Exporter/XstReader.Exporter.csproj index 26e1b28..4499c73 100644 --- a/src/XstReader.Exporter/XstReader.Exporter.csproj +++ b/src/XstReader.Exporter/XstReader.Exporter.csproj @@ -1,14 +1,14 @@ - net6.0 + net8.0 enable enable - - + + diff --git a/src/XstReader.sln b/src/XstReader.sln index d4bb37f..fde2972 100644 --- a/src/XstReader.sln +++ b/src/XstReader.sln @@ -25,6 +25,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XstReader.App.Common", "Xst EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XstReader.Exporter", "XstReader.Exporter\XstReader.Exporter.csproj", "{EBDF5C35-1050-472C-853E-345A8424752E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XstReader.Api.Tests", "XstReader.Api.Tests\XstReader.Api.Tests.csproj", "{D800DEAB-8B9C-41DA-ACC1-9F361E8C3ECC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -119,6 +121,18 @@ Global {EBDF5C35-1050-472C-853E-345A8424752E}.Release|x64.Build.0 = Release|Any CPU {EBDF5C35-1050-472C-853E-345A8424752E}.Release|x86.ActiveCfg = Release|Any CPU {EBDF5C35-1050-472C-853E-345A8424752E}.Release|x86.Build.0 = Release|Any CPU + {D800DEAB-8B9C-41DA-ACC1-9F361E8C3ECC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D800DEAB-8B9C-41DA-ACC1-9F361E8C3ECC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D800DEAB-8B9C-41DA-ACC1-9F361E8C3ECC}.Debug|x64.ActiveCfg = Debug|Any CPU + {D800DEAB-8B9C-41DA-ACC1-9F361E8C3ECC}.Debug|x64.Build.0 = Debug|Any CPU + {D800DEAB-8B9C-41DA-ACC1-9F361E8C3ECC}.Debug|x86.ActiveCfg = Debug|Any CPU + {D800DEAB-8B9C-41DA-ACC1-9F361E8C3ECC}.Debug|x86.Build.0 = Debug|Any CPU + {D800DEAB-8B9C-41DA-ACC1-9F361E8C3ECC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D800DEAB-8B9C-41DA-ACC1-9F361E8C3ECC}.Release|Any CPU.Build.0 = Release|Any CPU + {D800DEAB-8B9C-41DA-ACC1-9F361E8C3ECC}.Release|x64.ActiveCfg = Release|Any CPU + {D800DEAB-8B9C-41DA-ACC1-9F361E8C3ECC}.Release|x64.Build.0 = Release|Any CPU + {D800DEAB-8B9C-41DA-ACC1-9F361E8C3ECC}.Release|x86.ActiveCfg = Release|Any CPU + {D800DEAB-8B9C-41DA-ACC1-9F361E8C3ECC}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/XstReader/Controls/XstAttachmentListControl.cs b/src/XstReader/Controls/XstAttachmentListControl.cs index 3b0f2fe..2b6080c 100644 --- a/src/XstReader/Controls/XstAttachmentListControl.cs +++ b/src/XstReader/Controls/XstAttachmentListControl.cs @@ -126,7 +126,7 @@ public void SetSelectedItem(XstAttachment? item) public void ClearContents() { - GetSelectedItem()?.ClearContents(); + SetDataSource(null); } diff --git a/src/XstReader/Controls/XstAttachmentViewControl.cs b/src/XstReader/Controls/XstAttachmentViewControl.cs index 1bb4d42..61ea213 100644 --- a/src/XstReader/Controls/XstAttachmentViewControl.cs +++ b/src/XstReader/Controls/XstAttachmentViewControl.cs @@ -69,7 +69,7 @@ private void CleanTempFile() public void ClearContents() { - GetDataSource()?.ClearContents(); + GetDataSource(); SetDataSource(null); } diff --git a/src/XstReader/Controls/XstFolderTreeControl.cs b/src/XstReader/Controls/XstFolderTreeControl.cs index e6d574f..292a899 100644 --- a/src/XstReader/Controls/XstFolderTreeControl.cs +++ b/src/XstReader/Controls/XstFolderTreeControl.cs @@ -95,7 +95,7 @@ private KryptonTreeNode AddFolderToTree(XstFolder folder, KryptonTreeNode? paren public void ClearContents() { - GetSelectedItem()?.ClearContents(); + GetSelectedItem(); SetDataSource(null); } diff --git a/src/XstReader/Controls/XstMessageContentViewControl.cs b/src/XstReader/Controls/XstMessageContentViewControl.cs index e5f29fe..a0ef1be 100644 --- a/src/XstReader/Controls/XstMessageContentViewControl.cs +++ b/src/XstReader/Controls/XstMessageContentViewControl.cs @@ -138,7 +138,7 @@ public void ClearContents() RecipientListControl.ClearContents(); AttachmentListControl.ClearContents(); - GetDataSource()?.ClearContents(); + GetDataSource(); SetDataSource(null); } } diff --git a/src/XstReader/Controls/XstMessageListControl.cs b/src/XstReader/Controls/XstMessageListControl.cs index 606cc41..d75ceeb 100644 --- a/src/XstReader/Controls/XstMessageListControl.cs +++ b/src/XstReader/Controls/XstMessageListControl.cs @@ -122,7 +122,7 @@ public void SetSelectedItem(XstMessage? item) public void ClearContents() { - GetSelectedItem()?.ClearContents(); + GetSelectedItem(); SetDataSource(null); } } diff --git a/src/XstReader/Controls/XstMessageViewControl.cs b/src/XstReader/Controls/XstMessageViewControl.cs index 54f4bdb..cffe98c 100644 --- a/src/XstReader/Controls/XstMessageViewControl.cs +++ b/src/XstReader/Controls/XstMessageViewControl.cs @@ -88,7 +88,7 @@ public void ClearContents() MainKryptonNavigator.Pages.Clear(); MessageContentControl.ClearContents(); - GetDataSource()?.ClearContents(); + GetDataSource(); SetDataSource(null); } diff --git a/src/XstReader/Controls/XstPropertiesControl.Designer.cs b/src/XstReader/Controls/XstPropertiesControl.Designer.cs index f95dbc0..884eeec 100644 --- a/src/XstReader/Controls/XstPropertiesControl.Designer.cs +++ b/src/XstReader/Controls/XstPropertiesControl.Designer.cs @@ -73,13 +73,16 @@ private void InitializeComponent() // // PropertyGridProperties // - this.PropertyGridProperties.CategoryForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(57)))), ((int)(((byte)(91))))); + + // Replace the line causing the error with the following: + this.PropertyGridProperties.PropertyGrid.CategoryForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(57)))), ((int)(((byte)(91))))); + this.PropertyGridProperties.PropertyGrid.CategoryForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(57)))), ((int)(((byte)(91))))); this.PropertyGridProperties.Dock = System.Windows.Forms.DockStyle.Fill; this.PropertyGridProperties.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.PropertyGridProperties.HelpBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(187)))), ((int)(((byte)(206)))), ((int)(((byte)(230))))); - this.PropertyGridProperties.HelpForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(57)))), ((int)(((byte)(91))))); + this.PropertyGridProperties.PropertyGrid.HelpBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(187)))), ((int)(((byte)(206)))), ((int)(((byte)(230))))); + this.PropertyGridProperties.PropertyGrid.HelpForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(57)))), ((int)(((byte)(91))))); this.PropertyGridProperties.HelpVisible = false; - this.PropertyGridProperties.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(179)))), ((int)(((byte)(196)))), ((int)(((byte)(216))))); + this.PropertyGridProperties.PropertyGrid.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(179)))), ((int)(((byte)(196)))), ((int)(((byte)(216))))); this.PropertyGridProperties.Location = new System.Drawing.Point(0, 0); this.PropertyGridProperties.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.PropertyGridProperties.Name = "PropertyGridProperties"; diff --git a/src/XstReader/Controls/XstPropertiesControl.cs b/src/XstReader/Controls/XstPropertiesControl.cs index 2a432a4..50ba7d9 100644 --- a/src/XstReader/Controls/XstPropertiesControl.cs +++ b/src/XstReader/Controls/XstPropertiesControl.cs @@ -25,10 +25,19 @@ private void Initialize() { if (DesignMode) return; - PropertyGridProperties.SelectedGridItemChanged += (s, e) - => PropDescWebView.DocumentText = (e.NewSelection.PropertyDescriptor as CustomXstPropertyDescriptor)?.HtmlDescription ?? ""; + PropertyGridProperties.PropertyValueChanged += (s, e) => + { + PropDescWebView.DocumentText = (e.ChangedItem.PropertyDescriptor as CustomXstPropertyDescriptor)?.HtmlDescription ?? ""; + }; + + PropDescWebView.DocumentCompleted += (s, e) => + { + if (PropDescWebView.Document?.Body != null) // Ensure Document and Body are not null + { + PropDescWebView.Document.Body.Style = "zoom:90%"; + } + }; - PropDescWebView.DocumentCompleted += (s,e) => PropDescWebView.Document.Body.Style = "zoom:90%"; SaveToolStripButton.Click += (s, e) => SaveProperties(); } @@ -50,12 +59,7 @@ private void LoadProperties() PropertyGridProperties.SelectedObject = _DataSource?.Properties.ToPropertyGridSelectedObject(); } - public void ClearContents() - { - GetDataSource()?.ClearContents(); - SetDataSource(null); - } - + private void SaveProperties() { if (_DataSource?.Properties == null) diff --git a/src/XstReader/Controls/XstPropertiesInfoControl.Designer.cs b/src/XstReader/Controls/XstPropertiesInfoControl.Designer.cs index cefca34..6dba2ba 100644 --- a/src/XstReader/Controls/XstPropertiesInfoControl.Designer.cs +++ b/src/XstReader/Controls/XstPropertiesInfoControl.Designer.cs @@ -55,12 +55,12 @@ private void InitializeComponent() // // PropertyGridInfo // - this.PropertyGridInfo.CategoryForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(59)))), ((int)(((byte)(59)))), ((int)(((byte)(59))))); + this.PropertyGridInfo.PropertyGrid.CategoryForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(59)))), ((int)(((byte)(59)))), ((int)(((byte)(59))))); this.PropertyGridInfo.Dock = System.Windows.Forms.DockStyle.Fill; this.PropertyGridInfo.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); - this.PropertyGridInfo.HelpBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(227)))), ((int)(((byte)(230)))), ((int)(((byte)(232))))); - this.PropertyGridInfo.HelpForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(59)))), ((int)(((byte)(59)))), ((int)(((byte)(59))))); - this.PropertyGridInfo.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(183)))), ((int)(((byte)(188)))), ((int)(((byte)(193))))); + this.PropertyGridInfo.PropertyGrid.HelpBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(227)))), ((int)(((byte)(230)))), ((int)(((byte)(232))))); + this.PropertyGridInfo.PropertyGrid.HelpForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(59)))), ((int)(((byte)(59)))), ((int)(((byte)(59))))); + this.PropertyGridInfo.PropertyGrid.LineColor = System.Drawing.Color.FromArgb(((int)(((byte)(183)))), ((int)(((byte)(188)))), ((int)(((byte)(193))))); this.PropertyGridInfo.Location = new System.Drawing.Point(0, 40); this.PropertyGridInfo.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.PropertyGridInfo.Name = "PropertyGridInfo"; diff --git a/src/XstReader/Controls/XstPropertiesInfoControl.cs b/src/XstReader/Controls/XstPropertiesInfoControl.cs index 72354f9..7f90e77 100644 --- a/src/XstReader/Controls/XstPropertiesInfoControl.cs +++ b/src/XstReader/Controls/XstPropertiesInfoControl.cs @@ -56,7 +56,7 @@ private void LoadProperties() public void ClearContents() { - GetDataSource()?.ClearContents(); + GetDataSource(); SetDataSource(null); } diff --git a/src/XstReader/Controls/XstRecipientListControl.cs b/src/XstReader/Controls/XstRecipientListControl.cs index 600ff06..c810240 100644 --- a/src/XstReader/Controls/XstRecipientListControl.cs +++ b/src/XstReader/Controls/XstRecipientListControl.cs @@ -72,7 +72,7 @@ public void SetSelectedItem(XstRecipient? item) public void ClearContents() { - GetSelectedItem()?.ClearContents(); + GetSelectedItem(); SetDataSource(null); } } diff --git a/src/XstReader/MainForm.cs b/src/XstReader/MainForm.cs index 4202fd2..68d2952 100644 --- a/src/XstReader/MainForm.cs +++ b/src/XstReader/MainForm.cs @@ -49,7 +49,7 @@ private void SetCurrentXstElement(XstElement? value) if (_CurrentXstElement == value) return; - _CurrentXstElement?.ClearContents(); + if (value is XstFolder folder) { MessageListControl.SetDataSource(folder?.Messages?.OrderByDescending(m => m.Date));//, MessageFilter.GetSelectedFilter()); @@ -156,7 +156,7 @@ private void Reset() { if (XstFile != null) { - XstFile.ClearContents(); + XstFile.Dispose(); XstFile = null; @@ -166,7 +166,7 @@ private void Reset() //RecipientListControl.ClearContents(); //AttachmentListControl.ClearContents(); MessageViewControl.ClearContents(); - PropertiesControl.ClearContents(); + } } private void LoadXstFile(string filename) diff --git a/src/XstReader/Program.cs b/src/XstReader/Program.cs index fadd1d6..6c5705a 100644 --- a/src/XstReader/Program.cs +++ b/src/XstReader/Program.cs @@ -8,13 +8,13 @@ // // Copyright (c) 2021, iluvadev, and released under Ms-PL License. +using Krypton.Toolkit; using System.Text; namespace XstReader.App { internal static class Program { - /// /// The main entry point for the application. /// @@ -28,8 +28,11 @@ static void Main() // Add a reference to the NuGet package System.Text.Encoding.CodePages for .Net core only Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); - Krypton.Toolkit.PaletteTools.ApplyTheme(new Krypton.Toolkit.KryptonManager(), Krypton.Toolkit.PaletteModeManager.Office365Silver); - + // Corrected the usage of PaletteMode and removed non-existent PaletteTools + var kryptonManager = new KryptonManager + { + GlobalPaletteMode = PaletteMode.Office2007Blue + }; Application.Run(new MainForm()); } diff --git a/src/XstReader/WaitingForm.Designer.cs b/src/XstReader/WaitingForm.Designer.cs index e873b7c..3f2e176 100644 --- a/src/XstReader/WaitingForm.Designer.cs +++ b/src/XstReader/WaitingForm.Designer.cs @@ -43,7 +43,7 @@ private void InitializeComponent() this.ProgressBar.Size = new System.Drawing.Size(348, 16); this.ProgressBar.Style = System.Windows.Forms.ProgressBarStyle.Marquee; this.ProgressBar.TabIndex = 1; - this.ProgressBar.UseKrypton = true; + //this.ProgressBar.UseKrypton = true; this.ProgressBar.UseWaitCursor = true; // // BackgroundWorker diff --git a/src/XstReader/XstReader.App.csproj b/src/XstReader/XstReader.App.csproj index 4538296..3eb7ef1 100644 --- a/src/XstReader/XstReader.App.csproj +++ b/src/XstReader/XstReader.App.csproj @@ -2,7 +2,7 @@ WinExe - net6.0-windows + net8.0-windows7.0 enable true enable @@ -33,12 +33,12 @@ - - - - - - + + + + + + From 21401f783aab8542b2dbe64a678e63e18aee0313 Mon Sep 17 00:00:00 2001 From: Carl Tierney Date: Fri, 25 Apr 2025 16:12:52 -0500 Subject: [PATCH 3/4] updated windows version for windows app --- src/XstReader/XstReader.App.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/XstReader/XstReader.App.csproj b/src/XstReader/XstReader.App.csproj index 3eb7ef1..2706f8b 100644 --- a/src/XstReader/XstReader.App.csproj +++ b/src/XstReader/XstReader.App.csproj @@ -2,7 +2,7 @@ WinExe - net8.0-windows7.0 + net8.0-windows10.0.17763.0 enable true enable From 35ec52cb78a9ff75428a2f68c540c76102c41506 Mon Sep 17 00:00:00 2001 From: Carl Tierney Date: Fri, 25 Apr 2025 16:19:09 -0500 Subject: [PATCH 4/4] parameterized unit test --- src/XstReader.Api.Tests/ReadingStreamTests.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/XstReader.Api.Tests/ReadingStreamTests.cs b/src/XstReader.Api.Tests/ReadingStreamTests.cs index 3b1ac62..a688a20 100644 --- a/src/XstReader.Api.Tests/ReadingStreamTests.cs +++ b/src/XstReader.Api.Tests/ReadingStreamTests.cs @@ -9,15 +9,16 @@ namespace XstReader.Api.Tests [TestClass] public sealed class ReadingStreamTests { + private string _pstFilepath = ""; [TestMethod] public void OpenFileWithXstReader() { // Arrange - string filePath = Path.Combine("D:\\ediscovery\\Test_Export\\01.20.2025-1204PM\\Exchange\\carl.tierney@vision2.com.pst"); + - using var xstFile = new XstFile(filePath); + using var xstFile = new XstFile(_pstFilepath); // Assert @@ -30,8 +31,8 @@ public void OpenFileWithXstReader() public void OpenFileAndPassStreamToXstReader() { // Arrange - string filePath = Path.Combine("D:\\ediscovery\\Test_Export\\01.20.2025-1204PM\\Exchange\\carl.tierney@vision2.com.pst"); - using FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); + + using FileStream fileStream = new FileStream(_pstFilepath, FileMode.Open, FileAccess.Read); // Act using var xstFile = new XstFile(fileStream); @@ -44,8 +45,8 @@ public void OpenFileAndPassStreamToXstReader() [TestMethod] public void ReadInboxFromStream() { - string filePath = Path.Combine("D:\\ediscovery\\Test_Export\\01.20.2025-1204PM\\Exchange\\carl.tierney@vision2.com.pst"); - using FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); + + using FileStream fileStream = new FileStream(_pstFilepath, FileMode.Open, FileAccess.Read); // Act using var xstFile = new XstFile(fileStream);