I am using the Properties.Settings class to save the application settings. I would like to know, once I deploy in the client system, whether the settings would be saved across application restart and system restart.
Consider the scenario :
Once the application is deployed, the user would save the Mobile Number through a UI as
Phone : 1xxxx - 45678
Now, I would save the Phone number as
Properties.Settings.Default.ClientPhone = this.PhoneText.Text;
Properties.Settings.Default.Save();
Am I understand, that the phone number would be saved in the application across app.restarts and reboots?
This is the difference about application and user settings. Application settings are read only. User settings are stored permanently on a per-user basis. Your code is exactly what it takes to change and save a user setting.
Please note: As they are called "user settings", they will be stored separately for every user on the machine! You can not, using the default .NET settings mechanism, create changeable settings that are the same for all users.
Do not re-invent the wheel! Use the .NET settings mechanism - you're doing it right in your example :-)
This will work fine, however one thing to bear in mind is that if you install a new version of the program, it will "lose" the old settings (because the settings are specific to a particular version of your program). (By "version" I mean the AssemblyVersion)
Fortunately, you can deal with this by calling the following function at or near the beginning of Main(). For this to work you will need to add a new boolean setting property called NeedSettingsUpgrade and default it to 'true':
/// <summary>Upgrades the application settings, if required.</summary>
private static void upgradeProgramSettingsIfNecessary()
{
// Application settings are stored in a subfolder named after the full #.#.#.# version
// number of the program. This means that when a new version of the program is installed,
// the old settings will not be available.
//
// Fortunately, there's a method called Upgrade() that you can call to upgrade the settings
// from the old to the new folder.
//
// We control when to do this by having a boolean setting called 'NeedSettingsUpgrade' which
// is defaulted to true. Therefore, the first time a new version of this program is run, it
// will have its default value of true.
//
// This will cause the code below to call "Upgrade()" which copies the old settings to the new.
// It then sets "NeedSettingsUpgrade" to false so the upgrade won't be done the next time.
if (Settings.Default.NeedSettingsUpgrade)
{
Settings.Default.Upgrade();
Settings.Default.NeedSettingsUpgrade = false;
}
}
A quick google should have done it for you.
Yes they will according to msdn: .NET allows you to create and access values (settings) that are persisted between application execution sessions.
http://msdn.microsoft.com/en-us/library/aa730869(v=vs.80).aspx
Related
I have a C# WindowsForms application that uses Properties.Settings.Default to store application and user settings. Reading and writing custom user values works correct.
Application is set to automatically run on system startup or user sign on. Here's the problem: when the app starts on system startup it cant load any user-specific settings. They're all set to their default values. When i close the app and restart it - all user settings are back.
After debugging and logging i narrowed down the issue: on normal start application's working directory is set to the directory it was installed into. On system start (or user sign in) working directory is set to C:\system32 (or similar). That's when user settings are not loaded.
Is this a proper behavior ? If so, how would i correctly load (or reload) user settings?
NOTE: My application is deployed with ClickOnce so i can't really control where the settings file is stored. Also, i don't have any issues persisting the settings between the version upgrades.
Found a solution, although i'm not sure how "correct" it is.
In my application when user clicks on "Start on boot" checkbox option, i was writing the following into the registry:
string keyname = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
RegistryKey key = Registry.CurrentUser.OpenSubKey(keyname, true);
key.SetValue("MyApp", Application.ExecutablePath.ToString());
The issue was resolved when i changed the app path to:
var startPath = Environment.GetFolderPath(Environment.SpecialFolder.Programs)
+ #"\Published\App.appref-ms";
key.SetValue("MyApp", startPath);
I think it has something to do with how ClickOnce apps are typically launched. I start the app using the desktop shortcut, not directly running exe file.
I have a C# program that runs on startup via an entry in SOFTWARE\Microsoft\Windows\CurrentVersion\Run. On startup, it seems that it can't read Whatever.exe.config (Settings file).
I'm aware that the "current dir" on boot is somewhere in %windir%. At the moment, I'm trying to load the config file by concatenating the config file name and Application.ExecutablePath, but I'm not sure how to implement that.
How do I use Properties.Settings.Default on Windows Startup?
EDIT: I'm on HKCU. I'm using Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
Do not load the file yourself and leave the paths alone!
The Microsoft .NET settings mechanism does it all for you. The settings file will be automatically read when the application starts. And the user settings will be read from the user's profile.
What you didn't say is whether the application start through a user's registry entry (HKCU) or through the machine (HKLM). If you have user settings, they will be looked for in the current user's directory. That means that things may not work as expected when running the application with no used logged in.
I've written a win forms application that uses Attachmate EXTRA. The application itself works great but I was just notified that there is a need to be able to switch to different device names for the sessions. The names would be set before the sessions are launched and then the session would go through the connection process. The only way I can think to do this is create and save a separate session with each device name needed and go that route but I would like to be able to do this dynamically instead if possible.
I've tried doing this during debug to look at the object but have been unable to find a method or property to set.
After having a support ticket entered and getting confirmation, the only way to change the device name programatically is to open the .EDP file, replace the string with the new device name, save the file and then run that .EDP file.
Apparently their new application, Reflection, can handle these types of things with calls without making changes to the files.
I have an application that can be launched from the explorer context menu for a Windows drive. When you click the menu item the drive letter is passed to the new instance. I want to make sure that any old instance is closed.
I also want to make sure that the last drive that was selected is persisted, so that when I start the application again from the start-menu, it will remember the drive I originally selected.
It would be best if the already running application would receive an event so that it can update without having to kill and restart.
I tried the following, but that doesn't seem to be working:
This is my Class library method(it is just a line that define a variable so just i have a DLL that there a variable in it and no more)
namespace Dispatch
{
public class cls_get_drive_letter
{
public static string drive_letter;
}
}
This is my loading form code: (Here i will fill the DLL's variable)
private void Frm_loading_Load(object sender, EventArgs e)
{
Dispatch.cls_get_drive_letter.drive_letter = "XXX";
Process currentProcess = Process.GetCurrentProcess();
if (Process.GetProcessesByName(currentProcess.ProcessName, currentProcess.MachineName).Length >1)
{
currentProcess.Kill();
}
}
So when i run this for first time the "XXX" will be stored in DLL but when the current instance of application is running and i am going to run next instance of it the application will be closed because of this code:
Process currentProcess = Process.GetCurrentProcess();
if (Process.GetProcessesByName(currentProcess.ProcessName, currentProcess.MachineName).Length >1)
{
currentProcess.Kill();
}
So when closing code occurs with this code the new "XXX" will not stored in DLL and the last string will be in dll.
All variables, in this case a static field, will only remain the same for the running instance of your application.
When the application is started again the field is empty
A static variable is not stored 'inside a dll' but is stored inside the memory of the application that loads the dll. When a second instance of the application starts, it will have its own memory space and it will have its own version of the string variable. The variable is also not kept between instances, so as soon as you start a new instance it will have its own, empty string variable.
When the application is stopped, the memory for that instance is released and the variable is 'forgotten'.
If you want to share state between applications, there are all kinds of solutions, one could be the System.Configuration.Settings API, a file somewhere, a memory mapped file shared between multiple processes, a Named Pipe, a Kernel Semaphore. Options aplenty.
Until we understand exactly what it is you're trying to accomplish with this shared state, we can't provide you with a better alternative than the explanation that what you're doing right now, will not work do to the way static variables work.
Update based on new information:
You can store your currently selected drive in a Settings file for your project. You can add such file from the project properties in Visual Studio. There's a tab called settings. Create a new setting for "Selected Drive" and make it a User setting (that way you can update it without Admin rights).
To communicate a new drive letter to your already running application, you have a number of options.
For one, you could check whether your executable is already running (like you're doing now) and in that case update the settings file and exit the new instance. Your already running instance could periodically refresh the settings to pick up new values.
When your application starts, you can open a named pipe on your machine on which you listen for drive changes. When the 2nd instance starts, it can detect that the pipe is already there, write the new drive to the pipe and close. The already running application can pick up this message and change its configuration.
You can send a WindowMessage to the other application
You can host a simple WCF service to receive the notification
You can write the new drive letter to a file stored in a known location and have the other instance use a FileSystemWatcher to detect the changes to that file.
As I said the possibilities are endless.
If I were you I'd first make sure that the value is persisted between relaunches by implementing the Settings file in your application. Then investigate the options I described above, do some experimentation and then ask new questions when you cannot figure out how to make it work.
I developed a XAML browser application (XBAP) that is embedded within an ASP.NET web page. I am having a problem getting the latest version of the XBAP to update on the client computer. During development, I have had to use the Mage.exe tool to clear out the application cache so that my changes will be seen when running on my local computer. Besides executing Mage.exe -cc in the command line, I have also found rundll32 dfshim CleanOnlineAppCache to work just as well.
However, I do not want to ask customers to run any commands in the command line. What will I have to do to make the XBAP automatically update on the client computer? Instead of the updated XBAP refreshing on the client computer, the previous version of the XBAP continues to run.
Update
I created a bounty on this question because I have the same issue. From what I read online, XBAPs are supposed to compare the cached version # with the version # of the one on the webserver, and download the new version if it's different. I've verified that my version numbers are different, but the cached copy is still the one that is running when I launch the XBAP.
The cached copy also comes if I launch the XBAP outside of the asp.net page, although I do get the new version if I change the url parameters.
Update #2
I've discovered that the XBAP does automatically update on XP 32-bit machines, but not on my Windows 7 64-bit machine.
You could try something like this, although I use it in XAPs not XBAPs it might work for you too:
(snippet follows)
public partial class App : Application
{
/// <summary>
/// Creates a new <see cref="App"/> instance.
/// </summary>
public App()
{
Application.Current.CheckAndDownloadUpdateAsync();
// rest of code
EDIT
Was gonna suggest incrementing version number between publishes but it seems that's already been taken care of. Does this behavior happen on all browsers ? Might be some IE-specific bug/oddity (i've seen plenty of IE-only misbehaviors... wouldn't surprise me)
Years ago, we had this problem with an ordinary website. It kept haunting us, and in the end, we ended up changing the url prefix for each new version. The very first page was never cached, and forwarded to the updated url.
Its a workaround, I know, but a very reliable one.
You can use ClickOnce to deploy your application. If you want to force user to update just set minimum required version for the application (it's in Application Updates dialog box).
without the correct cache headers your browser may be preventing downloading the xbap.
clear cache to see if this fixes it.
alternatively use:
<%string versionInfo = typeof (AVSTX.POS.WebMvc.Controllers.HomeController).Assembly.GetName().Version.ToString(); %>
<param name="source" value="<%=ResolveUrl("~/ClientBin/AVSTX.POS.WebRia.xap?version=" + versionInfo) %>"/>
to create a new url which the browser cannot cache at this point.
It is based on inspecting the host assembly version so make sure to increment
[assembly: AssemblyVersion("3.4.9.0")]
[assembly: AssemblyFileVersion("3.4.9.0")]
this solution won't solve the dynamic modules you may download in the future. you will need to fix the actual cache headers if this is your problem.
edit 1: code to disable browser caching
//http://stackoverflow.com/questions/1160105/asp-net-mvc-disable-browser-cache
//http://developer.yahoo.com/performance/rules.html#expires
//http://ray.jez.net/prevent-client-side-caching-with-httpmodules/
//http://stackoverflow.com/questions/2281919/expiry-silverlight-xap-file-from-browser-cache-programmatically
public class XapFileHttpModule : IHttpModule
{
#region IHttpModule Members
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
}
public void Dispose()
{
}
private void context_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
if(context.Request.FilePath.Contains(".xap"))
{
context.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
context.Response.Cache.SetValidUntilExpires(false);
context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.Cache.SetNoStore();
}
}
#endregion
}
Application caching is done via manifest files caching, when manifests signatures changes, runtime will upgrade the local files (moreover it just upgrade the changed files). Just sure that you has the right headers sent on HTTP responses. Sometimes dynamic pages cache settings or hosting providers global settings interfere. For me, it always works out of the box.
ClickOnce worked for me like a charm. Also make sure that you're versioning your XBAP properly.
I deploy my Xbap by simply copying filest to ClientBin directory in my web project.
I display it in iframe.
To make application "refresh" version I have to change "Publish Version" in Xbap project before build.
Project Properties -> Publish -> Publish Version.
This changes version in xbap and manifest file forcing clients to download newest version.