0

I started doing some applications in VB.Net in the past year and a half and despite all my research for an answer, nothing has worked fine enough for me, so here I am, asking my question.

I have an application which allows the user to save the following data in an XML file:

  1. Custom name for the saved data above (inputted in a text box called txtName)
  2. Email (inputted in a text box called txtEmail)
  3. Password (inputted in a text box called txtPassword)

The XML file (with the name: appData.xml - see below for directory of executable file along with directory of xml file) looks like this template shown below. The xml file stores a total of 10 passwords and each password is being attributed an ID number. I have thought that I would need to attribute an ID number (from 01 to 10) to refer it in the code of my application. If there is an easier way to identify where to store the saved data, feel free to modify my xml file.

<?xml version="1.0" encoding="UTF-8"?>
<savedData>
    <savedPassword id="01">
        <name>Stored Name</name>
        <email>storedname@email.com<email>
        <password>storedPassword</password>
    </savedPassword>
    <savedPassword id="02">
        <name>Stored Name</name>
        <email>storedemail@email.com<email>
        <password>storedPassword</password>
    </savedPassword>
    <-- Other data modules for ids 03 to 09 --!>
    <savedPassword id="10">
        <name />
        <email />
        <password />
    </savedPassword>
</savedData>

The XML is located in the following folder: C:\VelocityDK Codes\Password Manager and the application's executable is located in the following folder: [USERPROFILE]\Documents\VelocityDK Codes ("[USERPROFILE]" being the partial path to my documents folder on my Hard Drive). As I am quite new to XML handling in VB.Net (windows forms), I have no idea if the name of the form is needed to retrieve the data from the xml - but if it is, here it is: frmMain.

Sadly, I do not have enough experience in storing data from external data files and pulling that data from a file located in a completely different directory than the application file withing the load of the executable files, so I do not actually have any code to provide... Therefore, what I want to do is the following: I need to retrieve the data from my XML file at each launch automatically.

  • Is your problem you don't know to load an XML file? Or is it how to add code which is run at the program's start? Or is it that you don't know how to access a file in the file system in a different folder than the current directory? Please clarify. – Doc Brown Nov 22 '19 at 21:36
  • You show some some, ahem, *variations* from the locations Microsoft say should be used for programs and data. Have a look at [Environment.SpecialFolder Enum](https://learn.microsoft.com/en-us/dotnet/api/system.environment.specialfolder?view=netframework-4.8) to see where things should be stored. Your own directory (i.e. you pick a sensible name) in ApplicationData or CommonApplicationData would be the ideal place to store the XML file. – Andrew Morton Nov 22 '19 at 21:41
  • @DocBrown I would need to know how I can read the data from the XML file from a different directory/folder. – Velocity DK Nov 22 '19 at 21:42
  • @AndrewMorton Ok, I will take care of it a bit later on. Thanks for the advice. – Velocity DK Nov 22 '19 at 21:43
  • Then, regarding the passwords, [Salted Password Hashing - Doing it Right](https://crackstation.net/hashing-security.htm) is well worth reading. – Andrew Morton Nov 22 '19 at 21:44
  • @VelocityDK For using the data, perhaps [LINQ To XML Tutorials with Examples](https://www.dotnetcurry.com/linq/564/linq-to-xml-tutorials-examples) could be helpful. – Andrew Morton Nov 22 '19 at 21:50
  • Thanks for your help @AndrewMorton . The thing is that I couldn't find anywhere on the web where it shows how to read an XML file in a different directory... – Velocity DK Nov 22 '19 at 21:52
  • For C#: https://stackoverflow.com/questions/9105009/read-xml-file-into-xmldocument, I am sure you can easily adapt this to VB.Net. You can specify the location as a parameter of the Load method like `doc.Load("C:\VelocityDK Codes\Password Manager\YourXmlFile.xml");` should work – Doc Brown Nov 22 '19 at 21:58
  • @VelocityDK All you need to do is give the Load function the complete path to the XML file, which is easy to do if you use the Environment.SpecialFolder way. – Andrew Morton Nov 22 '19 at 21:59
  • @VelocityDK your xml is invalid. The comment open/close tags are reversed and you didn't close the `email` tags properly – djv Nov 22 '19 at 22:23
  • @djv Thank you, did not notice that error. – Velocity DK Nov 22 '19 at 22:56
  • 1
    @AndrewMorton Thank you! That works perfect! – Velocity DK Nov 22 '19 at 22:57

1 Answers1

2

Use XML Serialization. IMO this is superior to using XDocuments in most cases. You will have an object with children which represent your xml file contents. You can iterate of the children, and everything is strongly-typed.

Start by creating VB.NET classes to represent your data

Option Strict On

Imports System.IO
Imports System.Xml.Serialization
<XmlRoot("savedData")>
Public Class SavedData
    <XmlElement("savedPassword")>
    Public Property SavedPasswords As List(Of SavedPassword)
End Class

Public Class SavedPassword
    <XmlAttribute("id")>
    Public Property ID As Byte
    <XmlElement("name")>
    Public Property Name As String
    <XmlElement("email")>
    Public Property Email As String
    <XmlElement("password")>
    Public Property Password As String
End Class

Once you have that, reading the file into your classes is pretty simple. Use the following code

Dim filename = "filename.xml"
Dim data As SavedData
Dim serializer As New XmlSerializer(GetType(SavedData))
Using sr = New StreamReader(filename)
    data = CType(serializer.Deserialize(sr), SavedData)
End Using
For Each sp In data.SavedPasswords
    Console.WriteLine($"id: '{sp.ID}', name: '{sp.Name}', email: '{sp.Email}', password: '{sp.Password}'")
Next

The only thing you need to do is to set the correct filename instead of Dim filename = "filename.xml". If the path is fixed, you can simply hard-code it

Dim filename = "C:\VelocityDK Codes\Password Manager\filename.xml"

If the path can vary such as being based on the Environment.SpecialFolder Enum you can incorporate it into the assignment:

The executing assembly needn't be in the same folder as the xml file.

djv
  • 15,168
  • 7
  • 48
  • 72