Using My.Settings
in this instance is not the best solution. While yes, .NET will take care of saving the data and loading it for you, the data in My.Settings
is volatile. If your application compiles as ManagedCode (which most all .NET code does), the My.Settings
items are tied to the Assembly version of the application. If you change the version of your assembly, you will lose the data stored in My.Settings
as the .NET code will look at your assembly as a completely new application. Further more, if the .exe
file is moved and executed from a different path, the settings will also be lost as .NET will look at the application and a completely different instance.
The better option would be to save the data yourself. You can do this by serializing an object and saving it to a file. When you deserialize the file, the return will be the exact same object that was saved. I would suggest creating a class that is a wrapper for the array or even better a List(Of String)
. Here is a sample Console application to use as a reference:
' Always, always, always use these (unless you have a few edge cases, usually reflection)
Option Strict On
Option Explicit On
' Makes for shorter code
Imports System.Runtime
Module Module1
Sub Main()
' File path to save the file, hardcoded here just for an example
Dim filePath As String = "C:\StackOverflow\usernames.dat"
' Set it to Nothing to prove that the below methods work, if they don't you'll get an NRE
Dim userNames As UsernameWrapper = Nothing
Console.Write("do you want to read from the file or write to a file? [r / w] ")
If Console.ReadKey.Key = ConsoleKey.W Then
Console.WriteLine() : Console.WriteLine("Enter three usernames:")
' Create the object that we want to save
userNames = New UsernameWrapper({Console.ReadLine, Console.ReadLine, Console.ReadLine})
'Save the object to a file
userNames.SaveToFile(filePath)
Else
' Get the object from the file
userNames = UsernameWrapper.ReadFromFile(filePath)
Console.WriteLine() : Console.WriteLine("Saved usernames loaded from file:")
' Output the contents
userNames.UserNames.ForEach(Sub(x) Console.Write(x & " ")) : Console.WriteLine()
End If
Console.WriteLine()
Console.Write("Run Again? [y / n] ")
If Console.ReadKey.Key = ConsoleKey.Y Then
Console.WriteLine() : Console.WriteLine()
' Set it to nothing to prove that the above methods are working,
' if they didn't work you'd get a NRE on next run
userNames = Nothing
' Call Main() again for a new run
Main()
End If
End Sub
End Module
' This is the key to the whole thing, this attribute is what allows the object to be serialized
<Serializable()>
Public Class UsernameWrapper
Public Property UserNames As List(Of String)
' Just a few ways of instantiating the object
Public Sub New()
Me.UserNames = New List(Of String)
End Sub
Public Sub New(ByVal usernameArray() As String)
Me.UserNames = usernameArray.ToList()
End Sub
Public Sub New(ByVal userNameList As List(Of String))
Me.UserNames = userNameList
End Sub
''' <summary>
''' Save the current object to a file
''' </summary>
''' <param name="filePath">Path to save the file to</param>
''' <remarks>http://stackoverflow.com/users/2659234</remarks>
Public Sub SaveToFile(ByVal filePath As String)
' Create the formatter that will do the serialization
Dim formatter As Serialization.IFormatter = New Serialization.Formatters.Binary.BinaryFormatter()
Using fs As New IO.FileStream(filePath, IO.FileMode.Create, IO.FileAccess.Write)
' Serialize the data
formatter.Serialize(fs, Me)
End Using
End Sub
''' <summary>
''' Load object from file
''' </summary>
''' <param name="filePath">Path of the file to read from</param>
''' <returns>The deseerailized object</returns>
''' <remarks>http://stackoverflow.com/users/2659234</remarks>
Public Shared Function ReadFromFile(ByVal filePath As String) As UsernameWrapper
' Create the formatter that will do the serialization
Dim formatter As Serialization.IFormatter = New Serialization.Formatters.Binary.BinaryFormatter()
' The deserialized object will be saved to this
Dim _usernameWrapper As UsernameWrapper = Nothing
Using fs As New IO.FileStream(filePath, IO.FileMode.Open, IO.FileAccess.Read)
' Deserialize the object and cast it to the correct type
_usernameWrapper = TryCast(formatter.Deserialize(fs), UsernameWrapper)
End Using
' If the deserializing failed, throw an error
If IsNothing(_usernameWrapper) Then Throw New Runtime.Serialization.SerializationException(String.Format("Could not deserialize {0}.", filePath))
Return _usernameWrapper
End Function
End Class