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.
Related
Ok i am working on an application which is basically an activity monitor.
This application will automatically log out a user if there is no activity for some time. I have successfully done the logout part.
But i am trying to automatically start the application when another or same user logged in again.
I tried startup code but it only works when windows starts up.
private void SetStartup()
{
RegistryKey rk = Registry.CurrentUser.OpenSubKey
("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
rk.SetValue("My_App", Application.ExecutablePath);
}
So is there any way to know when someone login in the system.
I am using winform and c#.
Let me know if someone needs more information
Thanks.
You can place a shortcut to your application in the "Startup" folder for all users. The location of this depends on your operating system.
Windows 10: press windows key+R, then type "shell:common startup". Put a shortcut to your application in here.
On Windows 7 it was at "C:\Documents and Settings\All Users\Start Menu\Programs\Startup".
If it's neither of those, add a comment...
Each time someone logs on, the application will be run.
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 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
I want to update my exe from remote server. So when the button clicked on my wpf application it will download the remote and also a remote txt file and replace the current ones in the same folder that exe running. So it will overwrite the current txt and and exe file while my exe is running. How can i achive this ?
Remote host is url like www.mydomain.com/MyAPP.exe
wpf application , c# 4.0
The way that we resolved this issue was to create a shell exe that as the one that was installed and deployed initially to the client machines.
The "real" executable program is stored in a subdirectory of this initial app. When the shell app is launched, after it has downloaded and installed any updates for the real app, it launches the real app's executable in a separate AppDomain.
Here is the core of the "real" app launching from within the shell app:
System.AppDomainSetup oSetup = new System.AppDomainSetup();
string sApplicationFile = null;
// Use this to ensure that if the application is running when the user performs the update, that we don't run into file locking issues.
oSetup.ShadowCopyFiles = "true";
oSetup.ApplicationName = sAppName;
// Generate the name of the DLL we are going to launch
sApplicationFile = System.IO.Path.Combine(sApplicationDirectory, sAppName + ".exe");
oSetup.ApplicationBase = sApplicationDirectory;
oSetup.ConfigurationFile = sApplicationFile + ".config";
oSetup.LoaderOptimization = LoaderOptimization.MultiDomain;
// Launch the application
System.AppDomain oAppDomain = AppDomain.CreateDomain(sAppName, AppDomain.CurrentDomain.Evidence, oSetup);
oAppDomain.SetData("App", sAppName);
oAppDomain.SetData("User", sUserName);
oAppDomain.SetData("Pwd", sUserPassword);
oAppDomain.ExecuteAssembly(sApplicationFile);
// When the launched application closes, close this application as well
Application.Exit();
Note that in our version, the shell app collects the user name and password from the user in order to access the update web site correctly. This data is then passed to the "real" app through the SetData method on the AppDomain.
The solution depends on your particular case. But there's no straight solution, because you can't update assemblies while they are loaded into memory and being used. I can propose 2 solutions: using shadow copying and using some sort of helper executable. I've used both of them.
Shadow copying.
The obvious way is to make your main executable to be shadow copied, replace it while your app is running and then restart the app. But you can't make your default app domain to be shadow copied, only secondary app domains can be. But you still can move all your code into another assembly (say, MainAppLib.dll) and rewrite your main app executable (MainApp.exe) so that it contains only "loader code". This loader code has to create another app domain, set it to be shadow copied and then run your program logic in the secondary app domain. Beware not to have any direct references from your main app domain into MainAppLib.dll because then this assembly will be loaded into your main app domain which is not shadow copied and the assembly file will get locked. In most cases you can go with AppDomain.ExecuteAssembly() methods.
Helper executable
The idea is to use some sort of update finisher. Your main app remains unchanged, you only add a little amount of code into it, so that your app will download update, put it into temporary folder, and then your main app starts update finisher (in separate process) and exits. Update finisher waits till your app closes and then copies new files from temporary folder into your app folder replacing all files. Update finisher can't replace it's own executable but it can be done by main application before it starts the update finisher. After copying files update finisher runs your application.
p.s. Personally I prefer the former solution because it involves some sort of voodoo magic using app domains, reflection, assemblies e.t.c. And it can be evolved into using plugins if you need (e.g. via MEF framework). But the latter is easier to understand especially if you have never worked with app domains and manual assemblies loading, it's quite straightforward.
You could probably use ClickOnce (based on your comment above that you would be prepared to have another assembly get the exe....as the other poster mentioned you can't replace a running assembly). You can configure it to check at various times (e.g. on startup) for new versions and it automatically downloads them. Its a very robust solution and you can do a lot with the deployment assemblies.
I'm using a book for studying for .NET certification, and I'm stumped on the issue of publisher certificates.
Background:
Windows Vista Home Basic SP2
Visual Studio 2008
.NET 3.5 SP1
Goal:
Write a simple C# console application that has its permission to read from a specific text file determined by the application's certificate.
Symptoms:
I am able to read from the file despite assigning the Nothing permission set to the code group that is conditioned by the application's certificate.
Steps taken:
Wrote C# console application that uses StreamReader to read the file and output to the console. The application works as expected.
On the application's properties, I used the Signing tab, set ON the checkbox for "Sign the ClickOnce manifest", clicked the Create Test Certificate button, and entered passwords.
Next, I clicked the More Details button, navigated to the Details tab, selected the Public Key row, and clicked the Copy to File button.
In the Certificate Export Wizard, I chose not to export the private key, chose the DER encoded binary X.509 format, and provided the path of the .CER file.
Next I rebuilt the application.
I opened the .NET Framework 2.0 Configuration tool.
I navigated to My Computer > Runtime Security > Machine > Code Groups > All_Code
Right clicked All_Code, and selected New to begin the Create Code Group wizard.
Gave the new code group a name, then selected the Publisher condition type.
Clicked the Import from Certificate File button, then selected the newly created .CER file.
Next I selected the Nothing permission set.
When running the application, which should now be a member of the new code group, it still works the same. I would expect that if it's a member of the Nothing permission set that it couldn't read the file.
Thanks for any insight you can provide. I'm probably missing one little detail. I wonder if this has anything to do with using Vista Home Basic.
Can your application read the file in question w/o any certificate?
Adding Nothing to a set of existing permissions won't change much.