c# Form Project won't save Setting changes of Console Project - c#

Background
Console Application:
I have a console application that retrieves data from a spreadsheet using the google sheets API. This application is automated by running it every 5 minutes with windows scheduler.
Form Application:
In the same solution I have created a windows form project that can be run manually, outside of the automation process to tweak any settings without disturbing the 5 minute process. (i.e. If we want to change spreadsheet ID to fetch data form a different spreadsheet, or if i want to change the output folder of where the data is being fetched)
My Goal
I'm trying to develop a form project that will edit the "settings.settings" file of another project in the same solution. Below is a screenshot of how i have my solution laied out:
What I've done so far
I've already added a reference from my sheetstocsv project in my SettingsUI Project, and i've successfully created a form that accesses sheetstocsv's Settings and edits them when a save button is clicked. Shown below is the function that's supposed to save the new settings from the form.
private void Save_Button_Click(object sender, EventArgs e)
{
sheetstocsv.Properties.Settings.Default.outputdir = OutputDirectory_TextBox.Text;
sheetstocsv.Properties.Settings.Default.spreadsheetID = SpreadsheetID_Textbox.Text;
sheetstocsv.Properties.Settings.Default.Entity = Entity_Texbox.Text;
sheetstocsv.Properties.Settings.Default.headernum = (int)Columns_NumericUpDown.Value;
string headers = "";
for (int i = 0; i < (int)Columns_NumericUpDown.Value; i++)
{
headers = headers + Columns_DataGridView.Rows[0].Cells[i].Value.ToString() + ",";
}
sheetstocsv.Properties.Settings.Default.headers = headers;
sheetstocsv.Properties.Settings.Default.configured = true;
sheetstocsv.Properties.Settings.Default.Save();
MessageBox.Show("Saving Complete!", "Settings",
MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
}
How I'm trying to do it
Below is a code snippet of how i'm only letting the sheetstocsv project continue if the configuration file has configured it first
//Check for if configured
if (Properties.Settings.Default.configured == false)
{
Console.WriteLine("Program has not been configured yet! Please Run SettingsUI first to start this program.");
Console.ReadLine();
Environment.Exit(0);
}
My Problem
Whenever I run my settingsUI, save, and then run my sheetstocsv project the changes that were supposed to be saved are not. and it will not allow the program move foward.
Edit
Below is the full form .cs that shows how i'm editing the properties of the other project
using sheetstocsv;
namespace SettingsUI
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Columns_DataGridView.RowCount = 1;
Columns_DataGridView.ColumnCount =(int)Columns_NumericUpDown.Value;
}
// Event handlers for other UI elemets here.......
private void Save_Button_Click(object sender, EventArgs e)
{
sheetstocsv.Properties.Settings.Default.outputdir = OutputDirectory_TextBox.Text;
sheetstocsv.Properties.Settings.Default.spreadsheetID = SpreadsheetID_Textbox.Text;
sheetstocsv.Properties.Settings.Default.Entity = Entity_Texbox.Text;
sheetstocsv.Properties.Settings.Default.headernum = (int)Columns_NumericUpDown.Value;
string headers = "";
for (int i = 0; i < (int)Columns_NumericUpDown.Value; i++)
{
headers = headers + Columns_DataGridView.Rows[0].Cells[i].Value.ToString() + ",";
}
sheetstocsv.Properties.Settings.Default.headers = headers;
sheetstocsv.Properties.Settings.Default.configured = true;
sheetstocsv.Properties.Settings.Default.Save();
MessageBox.Show("Saving Complete!", "Settings", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
}
}
}

I don't quite have enough info from your question (see comment from Rufus), but I am guessing that your console app launches your WinForm? If this is the case, what is likely happening is this:
1) Console app starts, and loads the config file into memory.
2) Your Winform launches and changes the config file.
3) Console app overwrites the changes to the config file on exit since it read it before the changes were made.
You could just move the winform into your console project, then just do something like this:
Properties.Settings.Default.outputdir = OutputDirectory_TextBox.Text;
...
Adding More Info (Oct 1):
I must be honest, doing what you're doing is a little strange, and I would really rethink referencing an executable to change its default settings. Just because VS lets you do this, doesn't necessarily mean you should. But if you must, there are a couple other things you can try:
1) You can simply parse the xml settings file and change node values of the settings you want to change. System.Xml namespace will make very short work of this. The post below has good examples:
Change xml node value
2) Try wrapping the code that is currently in your button click event handler with some method inside the console project. This way, you're calling a method that changes the settings, rather than trying to change the settings from an external assembly.
Note: neither of those methods will work if your console app is running while you're making changes to its config file. On shut down, the console app will overwrite the settings file with the settings it loaded into memory when it started up. If the console app isn't running, 1) will definitely work.

Related

How do I save multiple user settings in runtime in C#

I am trying to make my app stay the way I left it after closing the app. Therefore I want to save set of items from ListView to the settings and I can't figure out how to do that. I've found some solutions but I believe they are outdated as they don't seem to work.
Image shows set of items in ListView which I want to save so they appear there after restarting the app:
Items
This is where I want them to appear:
Settings
And this is part of code that I've tried out so far
private void btn_SaveConfig_Click(object sender, EventArgs e)
{
int i = 0;
Settings.Default["IP"] = tBox_discoverServerFrom.Text;
Settings.Default["DiscoveredServers"] = cBox_discoveredServers.Text;
foreach (var item in lV_groups.Items)
{
var property = new System.Configuration.SettingsProperty("Group"+i);
property.PropertyType = typeof(string);
property.Name = "Group " + i;
Settings.Default.Properties.Add(property);
Settings.Default.Save();
i++;
}
}
I do not think using the Settings API is a great idea if you want to save any significant amount of data.
I would recommend the following
Create a class describing all the data you want to save. To make serialization easier it should have a parameter less constructor and public setters for all properties. This is sometimes called a Data-Transfer-Object (DTO)
Use json to serialize the object to a file. You would normally place the file in a subfolder in the local app data folder: Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData).
Do the reverse when you start the application. If there is a file, use Json to deserialize it and use it however you want.
You may optionally add logic to save the file periodically, this would allow recovery in case of application crashes. You might also want some system to keep more than one file, in case the application or computer crashes in the middle of a save operation, and the file becomes corrupt.

Application setting doesn't work well

I have a checkbox(Name:tarahi_algouritm) and a button(Name:button1) on my form(Name:frm_choose).I want to save the latest changes on my checkbox as user clicked on the button.it means user run the program and check the checkbox and then click on button and then close the program.when he/she Rerun it,checkbox should be checked.or someway he disable the checkbox and click on button and after another run,checkbox should be disabled.
for this, in application setting(table part) put a checkbox (Name:s_tarahi_algouritm)and choose USER in scope part..as I said changes are apply on checkbox and s_tarahi_algouritm is used for save the latest changes on checkbox.I wrote these codes:
private void frm_choose_Load(object sender, EventArgs e)
{
if (Properties.Settings.Default.s_tarahi_algouritm!=null)
tarahi_algouritm= Properties.Settings.Default.s_tarahi_algouritm;
}
private void button1_Click(object sender, EventArgs e)
{
Properties.Settings.Default.s_tarahi_algouritm = tarahi_algouritm;
Properties.Settings.Default.Save();
}
but When I make changes on checkbox and close the debug and Rerun it,changes are not applied.
what should I do?where is wrong?I am partly beginner so explain explicit.
thank you all
The problem is the settings files are written out in two parts: one to the application settings (which you can't save to) and the other to the user settings (which you can save to). You need to save the user settings (it gets written to your c:\users{userid}... directory).
Look at the most up-voted response to Farzin's link. It explains the issue as well.
Here's a more thorough explanation: App.config: User vs Application Scope
Here's an example.
I created a webform app and added a Settings file to it (called TestSettings.settings). I added two values:
When you run this application it creates a file in the application directory named the same as your executable with .config appended that contains (among other things) a element and a element. But this file only contains the initial values. If you change the value under the element and call Save() it will not update this file. It will create a file:
c:\Users{username}\AppData\Local{appname}{random_dir_name}{version}\user.config
My code to demonstrate this was:
Console.WriteLine(TestSettings.Default["UserValue"]);
TestSettings.Default["UserValue"] = "def";
TestSettings.Default.Save();
I tested many things like:
Properties.Settings.Default.Properties.Add(new System.Configuration.SettingsProperty("a"));
Properties.Settings.Default.Properties["a"].DefaultValue = "b";
Properties.Settings.Default.Save();
it has not error but do not save. In this link:
C# Settings.Default.Save() not saving?
Answered you must add Properties.Settings.Default.Reload(); after saving, I did that but not changed. It seems no one knows the answer.(I read many articles).
It looks like a cancer to me! I suggest you to easily save your settings to a xml file.
Below i add an easy xml saving method:
using System.Xml.Linq;
And
XElement settings;
try
{
settings = XElement.Load("settings.xml"); //beside the app .exe file
}
catch (Exception) // it is first time and you have not file yet.
{
settings = new XElement("settings");
settings.Save("settings.xml");
}
If you want to add new element:
settings.Add(new XElement("firstKey", tarahi_algouritm.Checked.ToString()));
settings.Save("settings.xml");
If you want to read or edit element:
XElement settings = XElement.Load("settings.xml");
string firstKey = settings.Element("firstKey").Value; //reading value
settings.Element("firstKey").Value = "New Value"; //Edit
settings.Save("settings.xml"); //Save
Remember that firstKey is only a name and you can use another names instead.

Clicking a button on a windows from from a webform

I have created a windows form program that does some Business Intelligence but have subsequently needed to access this via a webform. I am fairly new to programming so I don't know what can be achieved here. But essentially I am wanting someone to go on to the net and when the user presses a button it sends a message to the windows form executable in a file and tells it to run and then press a button on the form, which runs a method to generate images of graphs. Is this possible?
Here is the relevant code.
In the webform I have this button.
protected void rolloutSmartSheets(object sender, EventArgs e)
{
string message = string.Format("Starting processes");
ltMessage.Text = message;
Process process = new Process();
process.StartInfo.FileName = #"P:\Visual Studio 2013\Projects\Smartsheet\SmartsheetAPI\obj\Debug\SmartSheetAPI.exe";
process.Start();
message = string.Format("Ended all processes");
ltMessage.Text = message;
}
That runs the executable but it opens the windows form and I imagine if the executable is sitting on another computer wouldn't that open on that computer? In which case i want it to tell it to press this button on the windows form which runs the method I need and then the user doesn't need to worry about it.
public void commitToDatabase_Click(object sender, EventArgs e)
{
commitToDataBase();
}
If you are able to have the clients install something in advance, you can provide this functionality using a custom protocol handler.
Example protocol handler from MSDN Article
HKEY_CLASSES_ROOT
alert
(Default) = "URL:Alert Protocol"
URL Protocol = ""
DefaultIcon
(Default) = "alert.exe,1"
shell
open
command
(Default) = "C:\Program Files\Alert\alert.exe" "%1"
Then add a link onto your webform like this
href="alert://test"
As long as the client has the handler installed, both in the registry and the executable file, it will run C:\Program Files\Alert\alert.exe, passing "test" to it as the first paramater.
You can easily change this to provide the ability to run the local graph generator, and pass any parameters from the webform you might need.

How to add entity-framework to console application (images are included)

I try to add entity-framework to console application:
I press "add new item" and
then
then
then I added code:
class Program
{
static void Main(string[] args)
{
try
{
Database1Entities db = new Database1Entities();
db.AddToTableTest(new TableTest { name = "name" });
db.SaveChanges();
int count = db.TableTest.Count();
int ui = 9 + 0;
}
catch (Exception e)
{
}
}
}
It gives no error, but I don't see any changes in database.
I described the issue better here
I did the same steps you did to setup a EF model. your database.mdf file has the Copy to Output Directory set to Copy always, that means that every time you hit F5 (build or debug your app) the file is getting replaced by the empty one on your project.
Changing the Copy to Output Directory on the Properties window of the mdf file should solve your problem.
If you use Copy if newer you are going to be persisting any modifications on the contents of the database until you edit the database (mdf) itself.
With Do not copy any change to the mdf file is not going to get reflected on your application and will probably generate problems with EF.
I recommend for this scenario that you use Copy if newer and fill your basic data in the mdf file so you will have it always available.

Count the number of times the Program has been launched

How can I get the number of times a program has previously run in c# without keeping a file and tallying. Is there a Application class or something in c# to check the count.
Please give a detailed explantion as i know nothing about it.This is A windows console application not windows forms.
You can do that my creating an Entry in the Registry. And another way is by using an Application Settings.
But I prefer Application Settings because it has less task to do.
See HERE: Creating an Application Settings.
Tutorial From Youtube
Recent versions of Windows automatically maintain this information in the registry under HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist.
The data is obfuscated with ROT13, but that's easy to "decrypt". A free utility (with source code) is available and can serve as your starting point.
You could send a message to a database or webservice every time the program starts up (assuming there's a network connection).
You could keep a count on some form of hardware thet's not a standard storage device (therefore not technically being a file).
You could make a registry entry that you keep the count in (if you ignore the fact that the registry entry is, at some level, persisted into a file somewhere).
You could just have a file somewhere that keeps track of the count. Not sure why you're so opposed to this one in the first place....
If you are running a Winforms application, the you can easily use the Application Settings. Right click on your Solution Name --> Properties --> Settings Tab. More info and tutorial here.
Then, every time your program starts, increment this setting and save it.
Ref: Count the number of times the Program has been launched
In my knowledge Windows does not keep this information for you. You would have to tally the value somewhere (file, database, registry setting).
Better way is Application Settings as:
Create setting in app.config and then use it as:
Properties.Settings.Default.FirstUserSetting = "abc";
then, you usually do this in the Closing event handler of the main form. The following statement to Save settings method.
Properties.Settings.Default.Save();
Implementation using Registry:
static string AppRegyPath = "Software\\Cheeso\\ApplicationName";
static string rvn_Runs = "Runs";
private Microsoft.Win32.RegistryKey _appCuKey;
public Microsoft.Win32.RegistryKey AppCuKey
{
get
{
if (_appCuKey == null)
{
_appCuKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(AppRegyPath, true);
if (_appCuKey == null)
_appCuKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(AppRegyPath);
}
return _appCuKey;
}
set { _appCuKey = null; }
}
public int UpdateRunCount()
{
int x = (Int32)AppCuKey.GetValue(rvn_Runs, 0);
x++;
AppCuKey.SetValue(rvn_Runs, x);
return x;
}
If it's a WinForms app, you can hook the Form's OnClosing event to run UpdateCount.
Then Check tutorial to Read, write and delete from registry with C#

Categories