Hello, I wrote a small rudimentary program in C# for testing computers and their functionality at work. Just makes my job simpler/easier. I’ve been working to improve the program as needed by expanding it’s functionality and one feature I want is the ability to save the state of checkboxes. Properties.Settings was used in tandem with the following code:
This works running off a thumb drive with a very annoying caveat. If I unplug the thumb drive and plug it back into the same computer the settings were saved and reload. Perfect.
But, if I unplug it and then plug it into another computer it was never connected to before the settings do not persist. They go back to the forms checkbox defaults. This kind of defeats the purpose of what I want to use it for.
Now I should probably have stated this at the top but I’m a complete programming novice. I’ve been doing my best to research this on my own but I’m running out of word combinations to type into Google. The behavior tells me Properties.Settings doesn’t save the settings relative to the programs executable. Ie. They don’t get saved to the thumb drive but the system itself. Is there a simple work around? Or do I have to go down the rabbit hole that is figuring out how to write and load a custom .XML file?
Unfortunately the purpose of my position is to physically test the condition of the computers hardware and software functionality. A tool that I can swap between 30, 40, 50+ computers a day is a necessity for the application. A localized install is not an option, neither is a network based service (working on convincing them to let me run a server though).
To be fully honest I’m amazed they’re letting me use this tool at all especially off a thumb drive. That’s usually one of the highest security risks but…I’m not going to complain.
Settings in C# are saved under the users profile or in a system folder depending if you select per user or system storage.
You can either implement IPersistComponentSettings. Or perhaps the easier way: just save the settings in your own file on the USB stick by writing and reading the file.
All of the computers are logged in a Microsoft Access database via their S/N and to access this database I have to log in, meaning every computer S/N I worked on is tied to my login credentials. If any customer calls up the company saying they found something malicious on multiple PC’s that would very quickly come strait back to me. I know.
I could show you the full code if you want. Just be prepared to raise both eyebrows because I don’t entirely know what I was writing. Just that it works.
I’ll read the document you linked when I have time later today. Reading and writing the settings from the USB from a file would be most desirable. This would offer on the fly edits or debugging. The format I read about seems to typically be .XML. I’m just struggling to find forum posts or documentation my brain can decipher what I’m looking at so I can add the code and the .XML script if that’s what you had in mind.
It does look as though this will be the easier of the two. I finally tracked down something that provides a adequate example that I sort of understand: Writing XML with the XmlDocument class
Next question will be after I adapt this and write this…how do I read it…I know where to put it so it loads when the form loads just not what to write.
I think it would be easier to just write a text file with one line for each value. XML is a bit overkill for your example (if thats all the data you need to save, that you showed in your first post).
You could save each line as
checkCamera=true
for example.
And then you can extract the value by parsing each line.
index = line.IndexOf( “=” ) will get you the position of the = sign.
and then
valueName = line.Substring( 0, index )
valueData = line.Substring( index, line.Length )
For the time being saving the state of these checkboxes is the only requirement but I do like the idea of having options. If going the .XML route opens up more possibilities to add considerably more complex features down the road I don’t mind investing the time.
Besides, even though it’s rough and it’s only one checkbox I just got it to work.
Got it working this time, tested before deployment so hopefully their computers don’t interfere somehow. I know there are better ways of coding this but at my current skill level it’s what I could come up with. I welcome criticism so long as it’s constructive.
The code:
private void xml(string input)
{
string[] checkboxes = { "Camera", "ArrowKeys", "InternetAudio", "KeyboardLCD", "ScreenBright100", "ConnectWiFi" };
int count = 0;
XmlDocument xmlDoc = new XmlDocument();
if (input == "Load")
{
xmlDoc.Load("./xml/checkboxes.xml");
XmlNodeList functionNodes = xmlDoc.SelectNodes("//checkboxes/checkbox");
foreach (XmlNode functionNode in functionNodes)
{
if (count == 0) { if (functionNode.Attributes["Camera"].Value == "True") { checkCamera.Checked = true; } }
else if (count == 1) { if (functionNode.Attributes["ArrowKeys"].Value == "True") { checkArrowKeys.Checked = true; } }
else if (count == 2) { if (functionNode.Attributes["InternetAudio"].Value == "True") { checkInternetAudio.Checked = true; } }
else if (count == 3) { if (functionNode.Attributes["KeyboardLCD"].Value == "True") { checkKeyboardLCD.Checked = true; } }
else if (count == 4) { if (functionNode.Attributes["ScreenBright100"].Value == "True") { checkScreenBright100.Checked = true; } }
else if (count == 5) { if (functionNode.Attributes["ConnectWiFi"].Value == "True") { checkConnectWiFi.Checked = true; } }
count += 1;
}
}
else if (input == "Save")
{
XmlNode rootNode = xmlDoc.CreateElement("checkboxes");
xmlDoc.AppendChild(rootNode);
foreach (string check in checkboxes)
{
XmlNode functionNode = xmlDoc.CreateElement("checkbox");
XmlAttribute attribute = xmlDoc.CreateAttribute(check);
if (count == 0) { attribute.Value = checkCamera.Checked.ToString();}
else if (count == 1) { attribute.Value = checkArrowKeys.Checked.ToString(); }
else if (count == 2) { attribute.Value = checkInternetAudio.Checked.ToString(); }
else if (count == 3) { attribute.Value = checkKeyboardLCD.Checked.ToString(); }
else if (count == 4) { attribute.Value = checkScreenBright100.Checked.ToString(); }
else if (count == 5) { attribute.Value = checkConnectWiFi.Checked.ToString(); }
functionNode.Attributes.Append(attribute);
rootNode.AppendChild(functionNode);
count += 1;
}
xmlDoc.Save("./xml/checkboxes.xml");
}
}
This is called from Form_Load with xml("Load") and the Save Button with xml("Save")
This is the .XML file produced by the Save IF statement:
I’m not a fan if using so many if, else if, and worse nested ifs but…I couldn’t think of anything else to make this work given I’m not calling simple variables but the form object.properties themselves.
If anybody wants to share how to do the same thing but better/smarter I’m open to learn something new.
If would probably change the xml to something like this
<settings>
<camera>true</camera>
</settings>
That way you can much easier access each setting with GetElementsByTagName. And you dont need the loop with the if count stuff.
Or if you want to keep the current structure. Instead of using the count variable. Check the attribute name and use that to control things. I think it would be good to keep the save and load function in such way its not dependent on the order of things. Especially if the file is opened in other programs or editors. XML does not guarantee the order of nodes.