I have a WPF application which is hooking into a DLL that I am also writing. The DLL scans a data folder of a 3rd Party application and handles all the interpretation of data within. The WPF is to provide a nice GUI on top of that; I separated them because it may be necessary in the future to write a command line interface for it too.
The scanning of the data folder takes some time so I wanted to save the state of the object (a Repository) and open that instead if the data folder has been scanned and retains the same ‘Last Modified’ state. I have marked the Repository object as [Serializable] however when I attempt to save the state (from either the WPF or the DLL) I get an exception that the WPF MainWindow is not [Serializable].
If I read the created .dat file it does have some (not sure if all) information from that class.
I don’t understand why it would be trying to save any information about the WPF windows. I have tried to mark the window as [Serializable] just to try however that class does not allow it. Searching around the web had me looking into AppDomains since I’m loading a DLL along with the application but that is a little over my head. Below is how I am currently trying to implement it. Edit: The call to serialize is at the bottom of the WPF code.
I should mention that I created an inline class within the WPF namespace and was able to successfully serialize that to a file.
Any help is appreciated.
This is the DLL:
namespace HPOO_XML_Parser
{
[Serializable]
public class HPOORepository
{
string _version;
string _path;
string _library;
string _uuid;
[NonSerialized]
BackgroundWorker bWorker = new BackgroundWorker();
[NonSerialized]
XElement _xmlRepo;
int _nodeCount;
List<Node> nodes;
...
Rest of properties and methods
}
And the WPF which calls it
namespace HPOO_Repository_Scanner
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
HPOORepository repo;
public MainWindow()
{
InitializeComponent();
StatusVisibility(); // Simply hides progress bar/cancel button
}
private void OpenRepository(object sender, RoutedEventArgs e)
{
string ooHome;
using (FolderBrowserDialog browser = new FolderBrowserDialog())
{
ooHome = Environment.GetEnvironmentVariable("ICONCLUDE_HOME");
if (ooHome != null)
{
browser.SelectedPath = ooHome;
}
browser.ShowNewFolderButton = false;
browser.Description = "Select a repository to open...";
if (browser.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
try
{
repo = new HPOORepository(browser.SelectedPath);
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.Message, "Invalid Repository Selected", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
repo.ProgressChanged += new ProgressChangedEventHandler(repo_ProgressChanged);
prgStatus.Maximum = 100;
repo.ReadRepository();
}
}
private void mnuSave_Click(object sender, RoutedEventArgs e)
{
SaveRepo(repo);
}
public void SaveRepo(object repository)
{
BinaryFormatter binFormat = new BinaryFormatter();
using (Stream fStream = new FileStream("test" + ".dat",
FileMode.Create, FileAccess.Write, FileShare.None))
{
binFormat.Serialize(fStream, repository);
}
}
Edit: And finally the exception:
System.Runtime.Serialization.SerializationException was unhandled
Message=Type 'HPOO_Repository_Scanner.MainWindow' in Assembly 'HPOO Repository Scanner, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
Source=mscorlib
StackTrace:
at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
at HPOO_Repository_Scanner.MainWindow.SaveRepo(Object repository) in \\tsclient\D\Dropbox\_Work\Visual Studio Projects\HPOO Repository Scanner\HPOO Repository Scanner\HPOO Repository Scanner\MainWindow.xaml.cs:line 179
at HPOO_Repository_Scanner.MainWindow.mnuSave_Click(Object sender, RoutedEventArgs e) in \\tsclient\D\Dropbox\_Work\Visual Studio Projects\HPOO Repository Scanner\HPOO Repository Scanner\HPOO Repository Scanner\MainWindow.xaml.cs:line 168
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)
at System.Windows.Controls.MenuItem.InvokeClickAfterRender(Object arg)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.ProcessQueue()
at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter)
at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.Run()
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at System.Windows.Application.Run(Window window)
at System.Windows.Application.Run()
at HPOO_Repository_Scanner.App.Main() in \\tsclient\D\Dropbox\_Work\Visual Studio Projects\HPOO Repository Scanner\HPOO Repository Scanner\HPOO Repository Scanner\obj\x86\Debug\App.g.cs:line 0
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
I feel like such an idiot; I was able to figure it out this morning.
I had to detach the ProgressChanged event handler from my repo object.
It was attached at object creation
And now removed before saving the object state
Hope that helps anyone else who runs into the same issue.