none
How can I save persistent user settings without using My.Settings (or a text file)? RRS feed

  • Question

  • Hello,

    I'm looking for ideas on how to save a "default" file without using My.Settings.  The specifics are as follows:

    Me: I'm a beginner/intermediate user who has used VB on and off since it first came out (and lots of other BASIC programs before that). But it's always been a hobby at best, never a job, and completely self taught so there are lots of gaps in my knowledge.

    The project: I'm writing a Windows Forms App with VS2019 to be used on Windows computers by only a handful of people.  The users want a standalone exe (no installer, they already have the .NET framework) that will read through thousands of files which are of one specific type.  These files have headers that contain keywords with info about the file.  My application will let the users chose which keyword/value pairs they want to export to a CSV file so it can be read in to Excel and sorted any way they want.  The users do NOT want the app to create additional folders anywhere else on their system but it's OK if the exe needs or creates additional files in the root directory of the exe.

    What persistent user info I need to save:  The user needs the ability to save a list of keywords for export, two paths to directories, and a few other strings.  Things like the form's position, fonts, etc are not required but it would be great if I could save those, too.

    The problem:  I have the app working perfectly using My.Settings, but that creates the user.config file in a location like C:\user\<username>\appdata\local\<myappname>\version\  or something similar.  I can't have my app creating a directory in that location or using a file from there.  I could save all of these settings with a text file, but it seems like a lot of room for error.  They don't all get saved at once; a user may change one setting at one point and another later on.  I'd like to learn a better way.

    What I'd like the most:  The best solution for this specific problem would be to change the location of where the user.config file is saved from "MachineToLocalUser" to "MachineToApplication".  It looks like the location of the user.config file is handled by AllowExeDefinition, but I don't understand enough about the VB Namespaces to make the change.

    Other options:  I found this article explaining how to make a custom user settings file, but it's above my head.
    https://docs.microsoft.com/en-us/visualstudio/ide/managing-application-settings-dotnet?view=vs-2019#use-customized-settings-files

    Another option would be to create my own XML file to hold the settings but this requires making a class to handle the get/set to XML which I don't know how to do yet.

    My biggest frustration with Microsoft Docs is that most of the examples are in C#.  Is there a way to view the Docs so the examples are for Visual Basic?

    If anyone has any comments or suggestions, I would sincerely appreciate any help or advice offered.  Learning a way to solve this issue will add a lot to my VB knowledge toolkit.

    Thank you,
    Shannon

    Saturday, March 7, 2020 10:06 PM

Answers

  • After weeks of searching and testing examples I found online, I have two ways to solve the issue of saving persistent user settings that will work for my project.

    I had originally ruled out using My.Settings due to where it saved the user.config file (in the users local app data directory).  Then I found this example where a custom settings provider class is added so the user's settings can be saved in the location of your choice which is fantastic!  It allowed me to work with My.Settings exactly as before but with complete control of the file's path. The example code I found was written in 2007 but it still works fine in VB 2019.

    https://www.codeproject.com/Articles/20917/Creating-a-Custom-Settings-Provider

    The other way was to write the settings to an XML file instead.  Using a JSON file makes more sense, but I didn't want to add packages that weren't built into the .NET framework already.

    While I was very happy to see creating a custom settings provider worked, I ultimately decided to stick with an XML file instead. I came across a number of comments and articles where the authors mentioned that My.Settings could have unexpected behavior and I don't know enough about it to determine if that's an accurate statement or not.  For me, it made more sense to use the option I understood more which is an XML file.

    When I have more time, I'll try creating my own custom settings provider class so I can get a better understanding of how that entire process works.  I think for now the XML file will be my best bet.

    Thank you all for your suggestions, I appreciate it!

    Shannon
    • Marked as answer by ShannonM42 Friday, March 20, 2020 3:33 AM
    Friday, March 20, 2020 3:28 AM

All replies

  • Hello,

    The following is to be considered conceptual with many possibilities. If you don't understand something take time to study the code. If this does not help then simply move on :-)

    Requires Json.net available on NuGet. https://www.nuget.org/packages/Json.Net/

    The following reads and writes to a json file using, in this case a simple class with a nested class were implementation happens in MySettings partial class so you can use My.Settings to get at the read and write methods, use your imagination to add other functionality that you can think of following this path.

    Classes to represent data when read in and write out to json.

    <Serializable()>
    Public Class SearchItem
        Public Property Name() As String
        Public Property TokenList() As List(Of Token)
        Public Sub New()
            TokenList = New List(Of Token)()
        End Sub
    End Class
    <Serializable()>
    Public Class Token
        Public Property Value() As String
    End Class
    

    Our partial class, not the path and file name are hard coded but you can always expose a procedure or property to pass path and filename in.

    Imports System.IO
    Namespace My
        Partial Class MySettings
            Private _fileName As String
            Private _fileOperations As New FileOperations
            Public ReadOnly Property ReadSetting() As List(Of SearchItem)
                Get
                    Return _fileOperations.LoadApplicationData(_fileName)
                End Get
            End Property
            Public Sub SaveSettings(settings As List(Of SearchItem))
                _fileOperations.SaveApplicationData(settings, _fileName)
            End Sub
            Public Sub New()
                _fileName = Path.Combine(
                    AppDomain.CurrentDomain.BaseDirectory, "Settings.json")
            End Sub
        End Class
    End Namespace

    Backend read/write operations

    Imports System.IO
    Imports Newtonsoft.Json
    
    Public Class FileOperations
        Public Function LoadApplicationData(fileName As String) As List(Of SearchItem)
    
            Using streamReader = New StreamReader(fileName)
                Dim json = streamReader.ReadToEnd()
                Return JsonConvert.DeserializeObject(Of List(Of SearchItem))(json)
            End Using
    
        End Function
        Public Sub SaveApplicationData(searchItems As List(Of SearchItem), fileName As String)
    
            Using streamWriter = File.CreateText(fileName)
    
                Dim serializer = New JsonSerializer With {.Formatting = Formatting.Indented}
                serializer.Serialize(streamWriter, searchItems)
    
            End Using
    
        End Sub
    
    End Class

    Very simple and down to earth mockup of data, writes in the first button, reads in the second button. In the wild (in production) you decide how to create, manage the data.

    Public Class Form1
        Private Sub CreateButton_Click(sender As Object, e As EventArgs) Handles CreateButton.Click
            Dim items = New List(Of SearchItem) From {
                        New SearchItem() With {.Name = "Item1",
                            .TokenList = New List(Of Token) From {
                                    New Token() With {.Value = "A1"},
                                    New Token() With {.Value = "A2"},
                                    New Token() With {.Value = "A3"}}},
                        New SearchItem() With {.Name = "Item2",
                            .TokenList = New List(Of Token) From {
                                    New Token() With {.Value = "B1"},
                                    New Token() With {.Value = "B2"}}}
                    }
    
    
    
    
            My.Settings.SaveSettings(items)
        End Sub
    
        Private Sub ReadButton_Click(sender As Object, e As EventArgs) Handles ReadButton.Click
            Dim items = My.Settings.ReadSetting
    
            For Each searchItem As SearchItem In items
                Console.WriteLine($"{searchItem.Name}")
                For Each token As Token In searchItem.TokenList
                    Console.WriteLine($"   {token.Value}")
                Next
                Console.WriteLine()
            Next
        End Sub
    End Class

    Output from read button

    Item1
       A1
       A2
       A3

    Item2
       B1
       B2

    Json file created

    [
      {
        "Name": "Item1",
        "TokenList": [
          {
            "Value": "A1"
          },
          {
            "Value": "A2"
          },
          {
            "Value": "A3"
          }
        ]
      },
      {
        "Name": "Item2",
        "TokenList": [
          {
            "Value": "B1"
          },
          {
            "Value": "B2"
          }
        ]
      }
    ]
    The option is to use a binary file, serialize and deserialize but the resulting file can not be manually edited at runtime while the above solution can be modified.

    EDIT: I took a few minutes to make the above user friendly by hooking up a PropertyGrid to show and edit items, did not add in the save portion. Some of the cool things are you can have a property named Value and in the PropertyGrid display it as Token for instance. If you want the full code I can upload it.

      


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange


    Saturday, March 7, 2020 11:21 PM
    Moderator
  • Hi

    Here is one of many possibilities.

    This version, saves/reads file stored in a user set path, here I store it in the Application.Startup location (where .exe is Release/Debug folder). If deployed, then it would default to wherever the .exe is placed. The settings are stored in a Plain Text file.

    There are a few defined types in this example, by no means extensive, but cover some of the common ones. Others can be added following the same template. There are several commonly used ones which I haven't included here.

    This is a stand alone example, needs a DataGridView named DGV and a Label1 on Form1. Just copy/replace default code.

    There are several functions left out - such as delete a setting etc., but can easily be added.

    I would imagine this Form/Code would only be useful as an additional Form in a Project, and I think it can easily be incorporated as such.

    There is NO ERROR checking included.

    Example usage is added - see results in Console.

    ' SETTINGS LOAD SAVE OWN PATH TEXT FILE
    ' Form1 with DataGridView named DGV,
    ' Label1 and Button1 (DEETE SETTING)
    Option Strict On
    Option Explicit On
    Public Class Form1
        Dim settings As New DataTable("Settings")
        Dim SettPath As String = IO.Path.Combine(Application.StartupPath, "MySettings.txt")
        Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
            SaveSettings()
        End Sub
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            With settings
                .Columns.Add("Name", GetType(String))
                .Columns.Add("Type", GetType(String))
                .Columns.Add("Value", GetType(Object))
    
                If IO.File.Exists(SettPath) Then
                    ReadSettings()
                    Label1.Text = "Data from file"
                Else
                    ' some test entries, only used for
                    ' testing and setting initial values
                    .Rows.Add("One", "String", "Freddy")
                    .Rows.Add("Two", "Integer", 123)
                    .Rows.Add("Three", "Double", 1.234)
                    .Rows.Add("Four", "Color", Color.Red)
                    .Rows.Add("Five", "Point", New Point(100, 200))
                    .Rows.Add("Six", "Size", New Size(100, 200))
                    Label1.Text = "Data explicitly set in code"
                End If
            End With
            DGV.DataSource = settings
            With DGV
                .SelectionMode = DataGridViewSelectionMode.CellSelect
                .Columns("Value").AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
            End With
            ' usage example
            Dim s As String = Gstring("One")
            Dim i As Integer = Ginteger("Two")
            Dim d As Double = Gdouble("Three")
            Dim c As Color = Gcolor("Four")
            Dim p As Point = Gpoint("Five")
            Dim sz As Size = Gsize("Six")
    
            ' check console for variable values
            Console.WriteLine(s)
            Console.WriteLine(i)
            Console.WriteLine(d)
            Console.WriteLine(c)
            Console.WriteLine(p)
            Console.WriteLine(sz)
        End Sub
        Function Gstring(name As String) As String
            Dim r() As DataRow = settings.Select("Name = '" & name & "'")
            If r.Count < 1 Then Return Nothing
            Return r.FirstOrDefault.Item("Value").ToString
        End Function
        Function Ginteger(name As String) As Integer
            Dim r() As DataRow = settings.Select("Name = '" & name & "'")
            If r.Count < 1 Then Return Nothing
            Return CInt(r.FirstOrDefault.Item("Value"))
        End Function
        Function Gdouble(name As String) As Double
            Dim r() As DataRow = settings.Select("Name = '" & name & "'")
            If r.Count < 1 Then Return Nothing
            Return CDbl(r.FirstOrDefault.Item("Value"))
        End Function
        Function Gcolor(name As String) As Color
            Dim r() As DataRow = settings.Select("Name = '" & name & "'")
            If r.Count < 1 Then Return Nothing
            Return DirectCast(r.FirstOrDefault.Item("Value"), Color)
        End Function
        Function Gpoint(name As String) As Point
            Dim r() As DataRow = settings.Select("Name = '" & name & "'")
            If r.Count < 1 Then Return Nothing
            Return DirectCast(r.FirstOrDefault.Item("Value"), Point)
        End Function
        Function Gsize(name As String) As Size
            Dim r() As DataRow = settings.Select("Name = '" & name & "'")
            If r.Count < 1 Then Return Nothing
            Return DirectCast(r.FirstOrDefault.Item("Value"), Size)
        End Function
        Sub SaveSettings()
            Using sw As New IO.StreamWriter(SettPath)
                For Each r As DataRow In settings.Rows
                    Dim s As String = r.Item("Type").ToString.ToLower
                    Select Case s
                        Case "string", "integer", "double"
                            With r
                                sw.WriteLine(.Item("Name").ToString & "," & .Item("Type").ToString & "," & .Item("Value").ToString)
                            End With
                        Case "color"
                            With r
                                Dim c As Color = DirectCast(.Item("Value"), Color)
                                sw.WriteLine(.Item("Name").ToString & "," & .Item("Type").ToString & "," & c.A.ToString & "|" & c.R.ToString & "|" & c.G.ToString & "|" & c.B.ToString)
                            End With
                        Case "point"
                            With r
                                Dim p As Point = DirectCast(.Item("Value"), Point)
                                sw.WriteLine(.Item("Name").ToString & "," & .Item("Type").ToString & "," & p.X.ToString & "|" & p.Y.ToString)
                            End With
                        Case "size"
                            With r
                                Dim sz As Size = DirectCast(.Item("Value"), Size)
                                sw.WriteLine(.Item("Name").ToString & "," & .Item("Type").ToString & "," & sz.Width.ToString & "|" & sz.Height.ToString)
                            End With
                        Case Else
                            With r
                                sw.WriteLine(.Item("Name").ToString & "," & .Item("Type").ToString & "," & .Item("Value").ToString)
                            End With
                    End Select
                Next
            End Using
        End Sub
        Sub ReadSettings()
            settings.Clear()
            Using sr As New IO.StreamReader(SettPath)
                Dim line As String = sr.ReadLine
                While Not line Is Nothing
                    Dim a() As Object = line.Split(","c)
                    Dim t As String = a(1).ToString
                    Select Case a(1).ToString.ToLower
                        Case "string", "integer", "double"
                            settings.Rows.Add(a(0).ToString, a(1).ToString, a(2))
                        Case "color"
                            Dim aa() As String = a(2).ToString.Split("|"c)
                            Dim c As Color = Color.FromArgb(CInt(aa(0)), CInt(aa(1)), CInt(aa(2)), CInt(aa(3)))
                            settings.Rows.Add(a(0).ToString, a(1).ToString, c)
                        Case "point"
                            Dim aa() As String = a(2).ToString.Split("|"c)
                            Dim p As Point = New Point(CInt(aa(0)), CInt(aa(1)))
                            settings.Rows.Add(a(0).ToString, a(1).ToString, p)
                        Case "size"
                            Dim aa() As String = a(2).ToString.Split("|"c)
                            Dim sz As Size = New Size(CInt(aa(0)), CInt(aa(1)))
                            settings.Rows.Add(a(0).ToString, a(1).ToString, sz)
                        Case Else
                            settings.Rows.Add(a(0).ToString, a(1).ToString, a(2))
                    End Select
                    line = sr.ReadLine
                End While
            End Using
        End Sub
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim r As Integer = DGV.SelectedCells(0).RowIndex
            If r < DGV.NewRowIndex Then
                DGV.Rows.RemoveAt(r)
            End If
        End Sub
    End Class



    Regards Les, Livingston, Scotland





    • Edited by leshay Sunday, March 8, 2020 3:59 PM Had said DataGridView called DGV - now actually correct code Added DELETE Button
    Sunday, March 8, 2020 1:14 AM
  • Hi Les and Karen,

    Thank you both for your responses, I appreciate it.

    Les - your method is very similar to what I was doing before which was saving the settings to a text file.  Your example included a few things I wasn't using before so if I do decide to use a text file again then your example will give me more flexibility, so thank you.

    Karen - I'm still working through your example trying to understand how to use it.  Even if I don't go this direction with my current project, your code will no doubt help me in the future. I'm curious why you decided to use a JSON file instead of XML since VB has the ability to use XML files without needing to add anything to it. I'm sure there's a very good reason I just don't understand yet!

    You wrote, " you can always expose a procedure or property to pass path and filename in" but I don't know how to "expose" a procedure or property.  I have a feeling if I knew how to do that, I would understand more about this all fits together.

    Thanks again to you both!
    Shannon

    Monday, March 9, 2020 8:30 PM
  • Why did I use Json rather than xml?

    Reading and writing is four lines each which includes strongly typing each setting. There is zero reason to test what a value is as the class and class properties are set in stone so that is automatic.



    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Monday, March 9, 2020 9:10 PM
    Moderator
  • Hi Karen,

    While I managed to get your example to work, there are quite a few new concepts involved I don't fully understand yet so unfortunately it won't help me with this specific problem but I appreciate your time in creating this example for me to study more. It's given me insight into areas of VB I need to add to my toolkit.

    Do you know if there is a way I can tell VB to store the user.config file at my app location instead of in the local user directory?  It's very frustrating that such a simple change doesn't seem to be mentioned online anywhere... but perhaps I don't know the correct terms to search for.  I've been searching since March 4 and feel ready to give up and go back to a text file instead.

    Thank you again for your help,
    Shannon



    Sunday, March 15, 2020 4:02 AM

  • What persistent user info I need to save:  The user needs the ability to save a list of keywords for export, two paths to directories, and a few other strings.  Things like the form's position, fonts, etc are not required but it would be great if I could save those, too.

    You can save those data in Registry, like most of applications do

    In my freewares, I save them in HKEY_CURRENT_USER\Software\[application name]



    • Edited by Castorix31 Sunday, March 15, 2020 7:10 AM
    Sunday, March 15, 2020 7:08 AM
  • Hi Karen,

    While I managed to get your example to work, there are quite a few new concepts involved I don't fully understand yet so unfortunately it won't help me with this specific problem but I appreciate your time in creating this example for me to study more. It's given me insight into areas of VB I need to add to my toolkit.

    Do you know if there is a way I can tell VB to store the user.config file at my app location instead of in the local user directory?  It's very frustrating that such a simple change doesn't seem to be mentioned online anywhere... but perhaps I don't know the correct terms to search for.  I've been searching since March 4 and feel ready to give up and go back to a text file instead.

    Thank you again for your help,
    Shannon



    From the top:

    "Do you know if there is a way I can tell VB to store the user.config file at my app location instead of in the local user directory?  "

    Your application will not have permission to write in the program files folder.

    It is a security issue. We cant let the average user change the program files.


    "The best solution for this specific problem would be to change the location of where the user.config file is saved from "MachineToLocalUser" to "MachineToApplication".  "

    Then all local users would have the same file. When Bob sets the folder to Bobs things then when Betty runs the app the folder is Bobs things.

    ANd security...


    "The users do NOT want the app to create additional folders anywhere else on their system"

    Why not? A hacker can access the data anywhere on the system including the program folder or the registry.

    If you have secure info you want saved you need to encript it and even then...

    You can always create a new folder on drive c:\myfolder\ if you like you just cant create or write into "C:\Program Files (x86)\..."

    Is that what Karen's example does?

    Using the registry as Castor mentions is an option?? If you have real security issues encrypt the values???

    PS In fact, the only reason I can think of not to use the local app data folder (if I understand) is to hide in a potentialy maliacious manner??

    Sunday, March 15, 2020 12:52 PM
  • Hi Karen,

    While I managed to get your example to work, there are quite a few new concepts involved I don't fully understand yet so unfortunately it won't help me with this specific problem but I appreciate your time in creating this example for me to study more. It's given me insight into areas of VB I need to add to my toolkit.

    Do you know if there is a way I can tell VB to store the user.config file at my app location instead of in the local user directory?  It's very frustrating that such a simple change doesn't seem to be mentioned online anywhere... but perhaps I don't know the correct terms to search for.  I've been searching since March 4 and feel ready to give up and go back to a text file instead.

    Thank you again for your help,
    Shannon



    Hello,

    Unfortunately my next idea would also be a concept that would most likely be in a uncomfortable zone for you. My perspective is not to  look for a simple solution but the right solution to a problem which may very well turn out to be simple to most developers but than again may not.


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Sunday, March 15, 2020 3:01 PM
    Moderator
  • Shannon,

    Do it likewise companies as Microsoft in almost all their desktop programs always did. Use the registry. It is easier than the settings. The only problem is that it is not portable.

    https://docs.microsoft.com/en-us/dotnet/visual-basic/developing-apps/programming/computer-resources/reading-from-and-writing-to-the-registry


    Success
    Cor

    Sunday, March 15, 2020 6:56 PM
  • Hello everyone,

    Thank you for the many replies. My project is an unusual one since it will only be used by a small group of people and none will be working on the same computer, so there's no worry about individual users needing their own settings saved in their own user\appdata directory.

    I'm attempting to provide a utility app for the scientists I work with to easily extract keyword/value pairs (to a .CSV file) located in the headers of specialized file formats. Some of the machines will be government property and touching the registry is out of the question.  Pretty much any "installer" is a no go.

    There will not be an installer with this app, so it will not be in the Program Files directory.  I will build it on my machine and send them a zipped folder containing the exe and the handful of files they'll also need (such as a lot of reference material about the keyword/value pairs) as well as any other files the app may need.  They all have the .NET framework - frequently we pass around .NET apps like this and use them from a thumb drive or copy them to some directory that has full read/write permissions.  I've contributed to our group in the past, but always with a text file for the settings.

    There are zero security issues with the data, it is not sensitive in any way so hackers are not a concern.

    I have it working fine with a text file for the settings that are critical, but I wanted to see if I could improve my app by taking advantage of the other things the user.config file can store.

    Perhaps I should change my question to this:  Can I build a standalone app that can run completely from a thumb drive (the .NET framework is on each machine) without writing anything on the user's local machine?

    Karen, if you have the time and inclination to give me a hint as to how to change the location of the user.config file, I would be forever grateful.  Even if I didn't understand everything in your previous example, it doesn't mean your advice on changing this path won't click for me.  I've been reading every Microsoft Doc I can find and have a loose understanding, but it's possible your explanation might be the missing piece that makes it suddenly fall into place.  The addition of the JSON package was what gave me pause with your example since so far we have done everything without having to add packages not available in the basic .NET framework.  This is the part I wasn't sure of when it comes to passing around utility apps we make for our group.

    I hope I've answered everyone's questions as to why I want to do it a certain way and am unable to use any of the current ideas (other than to use a text file, which I've already done).  If I could solve this user.config path issue so I could use my.settings normally when working with VB, I could add a ton of bells and whistles which aren't specifically necessary, but would help make the app more user friendly.

    Thank you again, everyone, for your time and ideas.

    Shannon

    Tuesday, March 17, 2020 7:47 AM
  •  Some of the machines will be government property and touching the registry is out of the question.  

    I don't see why.

    HKEY_CURRENT_USER is done for Apps

    As Cor Ligthert said, all MS applications use registry

    Tuesday, March 17, 2020 7:52 AM


  • Perhaps I should change my question to this:  Can I build a standalone app that can run completely from a thumb drive (the .NET framework is on each machine) without writing anything on the user's local machine?

    Shanon,

    In every religion is used with different names the sentence "Can the almighty lift a stone he can't carry himself".

    Your question is likewise that telling you don't want to use a file written on that  thumb drive, but I assume presume some data which the user changes. (And therefore the App settings or in other words the Config file was made). 


    Success
    Cor

    Tuesday, March 17, 2020 12:19 PM
  • Your question is likewise that telling you don't want to use a file written on that  thumb drive, but I assume presume some data which the user changes.

    Cor,

    I'm not sure I understand your reply. The users have no concerns about the app writing settings/config files to a thumb drive (or a directory of their choosing). For this specific project it can't be in the local users app data directory or the registry.

    I never imagined changing the path to the "user.config" file would be such a difficult task.

    Shannon

    Tuesday, March 17, 2020 9:57 PM
  • I don't see why.


    Castorix13,

    Because it is a requirement we all agreed to since none of us are full time professional programmers.

    Shannon

    Tuesday, March 17, 2020 10:18 PM
  •  Some of the machines will be government property and touching the registry is out of the question.  

    I don't see why.

    HKEY_CURRENT_USER is done for Apps

    As Cor Ligthert said, all MS applications use registry

    Hi Castorix31,

    Could You please give an example about Saving (My App Settings In Registry) I followed COR's Link but I'm confused ... My Scenario is to put numbers like (200) in My Settings

    To tell my app after this number (The app must stop working) how to do that by using the registry ..... I know how to do that by using My Settings but i don't know how to do that by using your recommendation of using registry ...............Thanks


    Regards From Egypt

    Wednesday, March 18, 2020 1:16 PM
  • Oh sorry, I thought that your main question was 

    "How can I save persistent user settings without using My.Settings (or a text file)?

    But you mean. "How can I save the settings on another then the regular place." 

    You wrote you are a beginner. Then first lesson. "Be clear to the computer and too those who you ask questions" And know, the less code you use. The more clear it is. 


    Success
    Cor



    Wednesday, March 18, 2020 2:10 PM
  • Amr, 

    In past replies which were hacking other peoples threads were never answered. I've seen that changed. I use myself seldom that My class. (Except with recources where VB and C# have complete different solutions). 

    Here some code to use the registry. Be aware I changed from a program from my so it can contain some mistakes. 

    Imports Microsoft.Win32
    
    Public Class Form1
        Private ValueNeeded As Integer
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
            Dim rk As RegistryKey = Registry.Users
            Dim keyName = "HKEY_CURRENT_USER\Software\Whatever"
            Dim theValue As Object = Registry.GetValue(keyName, "200", "Empty")
            If theValue Is Nothing OrElse theValue.ToString = "Empty" Then
                theValue = ""
                Registry.SetValue(keyName, "Whatever", theValue)
            Else
                ValueNeeded = CInt(theValue.ToString)
            End If
        End Sub
    End Class


    Success
    Cor

    Wednesday, March 18, 2020 2:15 PM
  • Oh sorry, I thought that your main question was 

    "How can I save persistent user settings without using My.Settings (or a text file)?

    But you mean. "How can I save the settings on another then the regular place." 

    You wrote you are a beginner. Then first lesson. "Be clear to the computer and too those who you ask questions" And know, the less code you use. The more clear it is. 


    Success
    Cor



    Cor,

    I'll be more precise.  I'd be thrilled to learn a solution to saving settings that:
    1 - doesn't use text files
    2 - doesn't use the registry
    3 - doesn't add files to the users local app data or anywhere else the user can't control
    4 - doesn't require packages that aren't built into the .NET framework

    You have replied twice with responses that add nothing helpful to the discussion. If you aren't able to follow the conversation in this thread to see why I mentioned changing the location of the user.config file then please move on to helping other people instead of giving me cryptic god/stone metaphors or criticizing me for asking a follow up question.

    Shannon

    Wednesday, March 18, 2020 7:06 PM
  • Shanon,

    What you wrote is not the same as you have posted in this thread. Nothing about that flash drive for instance. 

    But be happy, at least I will not give any solution anymore to your question. Probably somebody writes something which answers your question in the same way as drinking beer rectally and you wil mark that as answer and tell that it wonderful does fit for you as solution.


    Success
    Cor


    Wednesday, March 18, 2020 7:28 PM
  • Shanon,

    What you wrote is not the same as you have posted in this thread. Nothing about that flash drive for instance. 

    But be happy, at least I will not give any solution anymore to your question. Probably somebody writes something which answers your question in the same way as drinking beer rectally and you wil mark that as answer and tell that it wonderful does fit for you as solution.


    Success
    Cor


    Cor,

    Now you're up to three replies which add nothing helpful to the discussion. I'm respectfully asking you to stop posting to this thread - your condescending insults are out of line and unwarranted.

    Shannon, not "Shanon"

    Wednesday, March 18, 2020 9:57 PM
  • After weeks of searching and testing examples I found online, I have two ways to solve the issue of saving persistent user settings that will work for my project.

    I had originally ruled out using My.Settings due to where it saved the user.config file (in the users local app data directory).  Then I found this example where a custom settings provider class is added so the user's settings can be saved in the location of your choice which is fantastic!  It allowed me to work with My.Settings exactly as before but with complete control of the file's path. The example code I found was written in 2007 but it still works fine in VB 2019.

    https://www.codeproject.com/Articles/20917/Creating-a-Custom-Settings-Provider

    The other way was to write the settings to an XML file instead.  Using a JSON file makes more sense, but I didn't want to add packages that weren't built into the .NET framework already.

    While I was very happy to see creating a custom settings provider worked, I ultimately decided to stick with an XML file instead. I came across a number of comments and articles where the authors mentioned that My.Settings could have unexpected behavior and I don't know enough about it to determine if that's an accurate statement or not.  For me, it made more sense to use the option I understood more which is an XML file.

    When I have more time, I'll try creating my own custom settings provider class so I can get a better understanding of how that entire process works.  I think for now the XML file will be my best bet.

    Thank you all for your suggestions, I appreciate it!

    Shannon
    • Marked as answer by ShannonM42 Friday, March 20, 2020 3:33 AM
    Friday, March 20, 2020 3:28 AM
  • Thanks Cor ,

    It works well now ,With your first link 

    Any way thanks for your help 


    Regards From Egypt

    Saturday, March 21, 2020 5:23 PM