I wrote a simple c# wpf code as below,
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
label1.Content = "Before restart";
System.Diagnostics.Process.Start("ShutDown", "-r"); //restart
label2.Content = "After restart";
}
}
Now the problem is I wanted to resume my application automatically after restart and and display message as "After restart". Please help me how to achieve this...
The solution to this problem is maintain the state in hard disk or some permanent memory like custom transaction file.
For e.g.
There will be different stage in the application. I will enter each stage after processing into file. one the machine is stopped then if the application launch automatically it will read the stage from this file and then process from that stage.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//Read stage from transaction file as **Stage**
if(Stage == Stage1)
{
label1.Content = "Before restart";
WriteTransaction(Stage2);
}
System.Diagnostics.Process.Start("ShutDown", "-r"); //restart
if(Stage == Stage2)
{
label2.Content = "After restart";
//Finish transaction and delete the transaction file.
}
}
This way you can solve the problem.
To restart the application automatically you can put your executable under start up folder or even you can think of making it as windows service.
Here's a concept (pseudo code):
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// initialize defaults
bool isRestarted = false;
label1.Content = "";
label2.Content = "";
// Check the state
if (stateFile.Exists) // stateFile is something like type FileInfo
{
var text = File.ReadAllText(stateFile.FullName);
isRestarted = ParseForBool(text);
label1.Content = ParseForLabel(text); // if you want that to be restored as well
}
if (isRestarted)
{
label2.Content = "After restart";
DoSomeMagicRemoveAutostart(); // just if you want to restart only once
}
else
{
label1.Content = "Before restart";
stateFile.Write(true); // is restarted
stateFile.Write(label1.Content); // if you want to restore that as well
DoSomeMagicAutoStartOperation(); // TODO: Autostart folder or Registry key
System.Diagnostics.Process.Start("ShutDown", "-r"); //restart
}
}
You have two choices: Adding the application to Startup Folder or adding the appropiate key to the run key in Windows registry.
http://msdn.microsoft.com/en-us/library/aa376977(v=vs.85).aspx
Related
I am trying to restart my application and run a command. For example, when the user clicks the language he wants it goes checked true and ignores the other one with checked = false. When that is done, the application restarts and checks what language the users checked after the restart and gets the language.
public Application()
{
InitializeComponent();
check_language();
languages();
}
private void lang_english_Click(object sender, EventArgs e)
{
// problem *******
Application.Restart();
// if i remove this is works ok.
// when app is restarted it is like starting it so i dont think
// this works at all. is there an other way to read this?
// maybe with a bool?
lang_english.Checked = true;
//Ignore
lang_portuguese.Checked = false;
MessageBox.Show("Language was set to English.\r\nCliente will now restart.", "Language", MessageBoxButtons.OK, MessageBoxIcon.Information);
check_language();
}
private void lang_portuguese_Click(object sender, EventArgs e)
{
lang_portuguese.Checked = true;
//Ignore
lang_english.Checked = false;
MessageBox.Show("Language was set to Portuguese.\r\nCliente will now restart.", "Language", MessageBoxButtons.OK, MessageBoxIcon.Information);
check_language();
}
private void languages()
{
//Languages
}
}
private void check_language()
{
if (lang_english.Checked == true)
{
languages(); //Get the languages
//Ignore
lang_portuguese.Checked = false;
}
else if (lang_portuguese.Checked == true)
{
languages(); //Get the languages
//Ignore
lang_english.Checked = false;
}
}
First I would save the selected language in the app.config file, the you can check the config on start-up and check the appropriate language.
Second for restarting the application I would use one of two options:
1) Application.Restart()
2) Start a second application and then end the first. See this post: Restart WinForms Application
You may also want to look into changing the language at run-time Change language at run-time
You are checking your language AFTER restarting the application inside the SAME application controls. You should write and read the language in a file so you can check it in there:
private void lang_portuguese_Click(object sender, EventArgs e)
{
new System.IO.StreamWriter(new System.IO.FileStream("File.ext", System.IO.FileMode.Create)).Write("Portuguese");
}
private void check_language()
{
String lang = new System.IO.StreamReader("YouFile.ext").ReadLine();
if (lang == "English")
{
languages(); //Get the languages
//Ignore
lang_portuguese.Checked = false;
}
else if (lang == "Portuguese")
{
languages(); //Get the languages
//Ignore
lang_english.Checked = false;
}
}
This are EXAMPLES. you should write and read with validation and creating instances of your stream, so you close it after finishing Reading/writting.
This is the idea I can give you.
public Main()
{
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//Do Work
}
private void Start()
{
backgroundWorker1.RunWorkerAsync(); //This works perfectly
//////////This isthe offending code////////////
try
{
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\" + "FileName.ini";
using (var stream = File.Create(path)) { }
File.WriteAllText(path, "Text to write");
file = txtFilePath.Text;
}
catch (Exception ex)
{
MessageBox.Show(
"Error saving configuration file.");
}
//////////////////////////////////////////
backgroundWorker1.RunWorkerAsync(); //If moved here it does not fire!
//Program contines here...
}
Not sure what the problem could be.
I can think of 2 things here.
Start method is not being invoked (but you say that you can debug it, so thats not really an issue?)
Background worker is, well, a backgroundworker thread, if the foreground thread ends even before it starts; it will end, even though abruptly.
EDIT 1:
Can you try the following?
private void Start()
{
backgroundWorker1.RunWorkerAsync(); //This works perfectly
Thread.Sleep(10000);
...
...
// rest of your code.
Try adding this line:
bool running = backgroundWorker1.IsBusy();
Right after RunWorkerAsync() being called. And check its value with debugger or print message.
This will indicates the state of the thread - I suspect it finished its works right away (?)
My Excel AddIn is written in NetOffice, ExcelDNA, C#
It calls web service to get data. It takes a while to fetch a large amount of data.
During the process of data fetch, if network connection is lost, then Excel will hung, shows like "not responding". Now if I try to close Excel, it will ask you to close or debug. I simply close it.
Then when I restart Excel, there is an annoying message box comes up saying
"Excel experienced a serious problem with the 'commodity add-in' add-in. If you have seen this message multiple times, you should disable this add-in and check to see if an update is available. Do you want to disable this add-in?."
I wonder how to handle the situation when connection is lost appropriately? Thanks
Make the web service call asynchronously, if possible. Most WS will provide async versions and non-async versions of the calls that you can make.
If this is not possible, consider executing the web service data fetch within a separate thread.
In both scenarios, you should put some plumbing code in place to kill the job after a certain period, and probably some means to notify the user that not all is well.
"Excel experienced a serious problem with the 'XXX add-in' add-in. If
you have seen this message multiple times, you should disable this
add-in and check to see if an update is available. Do you want to
disable this add-in?."
You get this problem when an unhandled exception occurs. Excel will prompt you to disable the Add-In next start up. This can lead users to posts like this to fix it.
The pain is worse when you have to support clients using Citrix in non-admin environments. To get around the problem of Excel wanting to diable the add-In you have to add a Global Exception handler so the exception isn't referred back to Excel to avoid prompting users to disable the Add-In.
public YouAddInCtrl()
{
InitializeComponent();
// Add the event handler for handling UI thread exceptions to the event.
System.Windows.Forms.Application.ThreadException += ApplicationThreadException;
// Add the event handler for handling non-UI thread exceptions to the event.
AppDomain.CurrentDomain.UnhandledException += ApplicationUnhandledException;
}
private void ApplicationThreadException(object sender, ThreadExceptionEventArgs e)
{
addInManager.TopLevelExceptionHandler(e.Exception);
}
private void ApplicationUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
addInManager.TopLevelExceptionHandler((Exception)e.ExceptionObject);
}
// Any exceptions returned to Excel will cause the Addin to be disabled
// So we must swallow them here.
internal void TopLevelExceptionHandler(Exception ex)
{
var e = new NotificationEventArgs(NotificationEventArgs.NotificationEnum.TopLevelException);
if (NotifyEventTopLevelException != null)
{
if (NotifyEventTopLevelException(ex,e))
{
System.Diagnostics.Process.Start("mailto:Support#XYZ.com%3e?subject=XYZ%202%20PROD%20Environment%20Problem&body=Hi,%0A%0AIssue:%0A%0ASteps%20to%20Reproduce:");
}
}
LogExceptions(ex);
}
I would also suggest that you run the WebService request on a different thread, eg:
BackgroundWorker1.WorkerReportsProgress = true;
BackgroundWorker1.WorkerSupportsCancellation = true;
BackgroundWorker1.DoWork += DoWorkExecuteQuery;
BackgroundWorker1.RunWorkerCompleted += RunWorkerCompletedExecuteQuery;
private bool QueryData()
{
var thinkProgBar = new ThinkingProgressBar();
thinkProgBar.ShowCancelLink(true);
thinkProgBar.SetThinkingBar(true);
BackgroundWorker1.RunWorkerAsync(thinkProgBar);
thinkProgBar.ShowDialog();
if (thinkProgBar.Tag != null && thinkProgBar.Tag.ToString() == "Cancelled")
{
CancelGetDataByFilters();
thinkProgBar.SetThinkingBar(false);
return false;
}
thinkProgBar.SetThinkingBar(false);
return true;
}
private void DoWorkExecuteQuery(object sender, DoWorkEventArgs e)
{
dtQueryData = null;
e.Result = e.Argument;
((ThinkingProgressBar)e.Result).SetThinkingBar(true);
dtQueryData = WEBSERVICE.GetData(); //CALL YOUR WEBSERVICE HERE
}
private void RunWorkerCompletedExecuteQuery(object sender, RunWorkerCompletedEventArgs e)
{
var dlg = e.Result as ThinkingProgressBar;
if (dlg != null) {
((ThinkingProgressBar)e.Result).SetThinkingBar(false);
dlg.Close();
}
}
Here is the ThinkingProgress bar:
public partial class ThinkingProgressBar : Form
{
private System.DateTime startTime = DateTime.Now;
public ThinkingProgressBar()
{
InitializeComponent();
}
private void lblClose_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
this.Tag = "Cancelled";
this.Hide();
}
public void ShowCancelLink(bool show)
{
lblClose.Visible = show;
}
public void SetThinkingBar(bool on)
{
if (on)
{
lblTime.Text = "0:00:00";
startTime = DateTime.Now;
timer1.Enabled = true;
timer1.Start();
}
else
{
timer1.Enabled = false;
timer1.Stop();
}
}
private void timer1_Tick(object sender, EventArgs e)
{
var diff = new TimeSpan();
diff = DateTime.Now.Subtract(startTime);
lblTime.Text = diff.Hours + ":" + diff.Minutes.ToString("00") + ":" + diff.Seconds.ToString("00");
lblTime.Invalidate();
}
}
Based on an Code Project article on Windows Forms User Settings by David Veeneman, I have been playing around with saving the start location and start size of an application.
It works perfectly in the single instance, but when I expand it to multiple instance I run into problems.
I've wrapped the section dealing with loading the setting and saving the settings in a mutex to protect writing to and from the settings file.
I would like the windows to stack from the last known location. This seems to work fine most of the time, but if I open up four or five windows in rapid sucession the first three will open perfectly, then there will be a gap, and after that some of them start to open at the same location.
Render the Form/Application:
private Mutex saveSetting;
private const int START_LOCATION_OFFSET = 20;
private void MainForm_Load(object sender, EventArgs e)
{
// Get the mutex before the reading of the location
// so that you can't have a situation where a window drawn
// in the incorrect position.
this.saveSetting = new Mutex(false, "SaveSetting");
this.saveSetting.WaitOne();
this.LoadWindowStartSizeAndLocation();
.
.
.
.
.
this.saveSetting.ReleaseMutex();
}
Loading the settings:
private void LoadWindowStartSizeAndLocation()
{
// Set window location
if (Settings.Default.WindowLocation != null)
{
System.Drawing.Point startLocation =
new System.Drawing.Point
(Settings.Default.WindowLocation.X + START_LOCATION_OFFSET,
Settings.Default.WindowLocation.Y + START_LOCATION_OFFSET);
this.Location = startLocation;
Settings.Default.WindowLocation = startLocation;
Settings.Default.Save();
}
// Set window size
if (Settings.Default.WindowSize != null)
{
this.Size = Settings.Default.WindowSize;
}
}
Saving the settings:
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
this.SaveWindowSizeAndLocationForNextStart();
}
catch (Exception ex)
{
System.Diagnostics.Debug.Assert(false, ex.Message);
}
}
/// <summary>
/// Save the Window Size And Location For the next Application Start up.
/// </summary>
private void SaveWindowSizeAndLocationForNextStart()
{
if (this.WindowState != FormWindowState.Minimized)
{
// Copy window location to app settings
Settings.Default.WindowLocation = this.Location;
Settings.Default.WindowSize = this.Size;
}
try
{
this.saveSetting = new Mutex(false, "SaveSetting");
this.saveSetting.WaitOne();
Settings.Default.Save();
}
catch
{
// Do nothing. It won't permanently disable the system if we
// can't save the settings.
}
finally
{
this.saveSetting.ReleaseMutex();
}
}
Can anyone tell me what I'm doing worng? Or how based on the code above could I get two instances rendered to the same start location??
Thanks
A
The problem is that settings are loaded before the mutex is acquired. Call Settings.Default.Reload() after acquiring the mutex.
Hi I have a problem using Filesystemwatcher & BackgroundWorker process.
I have a windows forms application that checks for new text files on a folder, it process them and creates xml files from them.
I´m using FSW to monitor for new txt files on a folder, the app works fine but when the folder receives a large amount of files (let's say 1000), the app freezes because it's processing all of them.
it occurred to me to add a backgroundworker, so the FSW calls it everytime a new file is created, this way we can process the file on the background without freezing the UI.
This idea did not work because for every file that is created, I try to call the RunWorkerAsync() method, so if it's busy processing a file and I try to process a new one it will throw the following error:
"This BackgroundWorker is currently busy and cannot run multiple tasks concurrently."
So I tried to loop the method with a while til it gets available but, infinite exception is thrown.
this is the simplified version of my code:
private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
{
readFile();
}
private void readFile()
{
while (backgroundWorker1.IsBusy)
{
readFile();
}
backgroundWorker1.RunWorkerAsync(idx);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
int i = (int)e.Argument;
i += 1;
e.Result = i;
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = "Processing...";
this.Refresh();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
label1.Text = "Completed...";
this.Refresh();
idx = (int)e.Result;
}
The exception thrown says “An unhandled exception of type 'System.StackOverflowException' occurred in WindowsFormsApplication2.exe, make sure you do not have an infinite loop or recursion”
Of course I could remove the FSW, but I'd like to know if there's a way to make them work together, any ideas?
What you have is a classic Producer/Consumer problem.
Solve it with a System.Collections.Concurrent.ConcurrentQueue<string>.
On the FSW event, add the filename to the Queue.
Start 1 or 2 BackgroundWorkers to process the queue.
And this is the code that overflows your stack in a hurry:
private void readFile()
{
while (backgroundWorker1.IsBusy)
{
readFile(); // the recursive call, will fail quickly
}
backgroundWorker1.RunWorkerAsync(idx);
}
Not only does this cause an SO exception, it also blocks your main thread.
You need a better way to wait, and the ConcurrentQueue gives you that.
Instantiating new BackgroundWorkers would do the trick, as would Henk's solution above.
Or, you can do it without changing your code too much just using the ThreadPool.
private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
{
ThreadPool.QueueUserWorkItem(o => readFile(e));
}
public void readFile(System.IO.FileSystemEventArgs e)
{
this.BeginInvoke(new MethodInvoker(() =>
{
label1.Text = "Processing...";
this.Refresh(); //you shouldn't need this
}));
//your long running read/processing... doing something event args
this.BeginInvoke(new MethodInvoker(() =>
{
label1.Text = "Completed...";
this.Refresh();
idx = (int) e.Result;
}));
}
Why not instantiate a new BackgroundWorker in readFile instead of reusing?