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.
Related
I have the following code in C#:
while (wechsel)
{
ProfDpDrv.MDPReadSlaveData(SlaveAddress, resetdiag, out dpData);
newStatus = dpData.m_InputData[i];
if (newStatus == 1)
{
int debug = e.RowIndex;
Dgv_Data_List.Rows[e.RowIndex].Cells["Adresse"].Style.BackColor = Color.Green; //
Dgv_Data_List.Refresh();
wechsel = false;
}
}
Here I want to EXIT the loop with the ESC if wechsel still at true. I have no console by the way.
Due to the fact, that we don't know where this code is running (WinForms, WPF, ASP, etc) except it is not a console it is hard to give you a concrete help.
A general advice to solve this issue, would be to create a CancellationTokenSource and give the source.Token to the long running method. This method can within the loop regulary check, if a cancellation was requested by checking token.IsCancellationRequested and then simply do whatever needed to leave a consistent state and exit the method.
And back to the beginning of my answer, it depends on the used interface you have to hook onto something to register a keypress and then calling source.Cancel().
I assumed that you are using WPF or WinForms.
Just subscribe to KetDown method on host window to capture all keys being pressed and then check if it's ESC and handle that appropriately, see code below:
public partial class MainWindow : Window
{
private bool wechsel = true;
public MainWindow()
{
InitializeComponent();
this.KeyDown += MainWindow_KeyDown;
}
private void MainWindow_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key != Key.Escape) return;
wechsel = false;
txtInfo.Text = "interrupted by ESC";
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
int i = 0;
while (wechsel)
{
txtInfo.Text = i++.ToString();
await Task.Delay(500);
}
}
}
I'm really confused so I'm hoping someone can help me out here. I'm working on a programming assignment for uni but there's one part that's really been bugging me and I can't move on until it is fixed. I have created two classes. The problems in each are shown here:
class Login : Form1
{
Form1 f = new Form1();
public void LoginCorrect()
{
Form1.attempts = 3;
MessageBox.Show("Correct Credentials Entered!");
f.loginScreenVar = false;
f.mainScreenVar = true;
f.ChangeScreen();
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void ChangeScreen()
{
//Login Screen
txtUsername.Visible = loginScreenVar;
txtPassword.Visible = loginScreenVar;
btnLogin.Visible = loginScreenVar;
lblLoginCaption.Visible = loginScreenVar;
lblUsername.Visible = loginScreenVar;
lblPassword.Visible = loginScreenVar;
//Main Screen
lblWelcomeUser.Visible = mainScreenVar;
btnViewDetails.Visible = mainScreenVar;
btnViewAccounts.Visible = mainScreenVar;
btnLogout.Visible = mainScreenVar;
MessageBox.Show(loginScreenVar.ToString());
}
}
I have some controls on screen in my design which consist of text boxes, labels, and buttons, and these are meant to show and hide at diffferent times. I have created some booleans which can be set to true and false which will also set the visibility of these controls to true and false.
My problem is when accessing ChangeScreen() from my Login class, for some reason the controls don't hide when they're meant to. I've literally got a message box in the ChangeScreen() method which outputs the result of 'loginScreenVar' and this is false. Please can someone tell me why my 'Login Screen' controls are NOT hiding even though 'loginScreenVar' = false.
Another thing to note is when calling this code from a button in the Form1 class, it does work. However, due to the brief of my assignment I need to use multiple classes.
I really hope this isn't a bug and someone can help me here because I literally can't move on until this is fixed, thanks!
The issue is that, as noted in the comments, you create a new instance of Form1.
A whole new object, with own states.
Why can't I see this new instance? - well, if you did f.show() THEN you'd see it.
As it stands, you're still looking at the old instance.
So, what you need is a publicly accessible instance of Form1 which your two classes access, without creating a new instance.
OR
you could also work with two different windows. For example:
Form1_loaded(object sender, EventArgs e)
{
LoginWindow lw = new LoginWindow();
var result = lw.ShowDialog();
if(result == DialogResult.Cancel)
{
Application.Quit();
}
}
Let's assume you have a button for login. When clicked, it checks whether password and user name are correct. If not, the incorrect count gets increased by one. If the incorrect count is >= 3, then you just close the LoginWindow. (Default DialogResult is DialogResult.Cancel). The code might look like this:
LoginBtn_Click(object sender, EventArgs e)
{
if(UserNameInput.Text == userName && PasswordInput.Text == password)
{
failedAttempts = 0;
this.DialogResult = DialogResult.OK;
this.Close();
}
else
{
failedAttempts++;
if(failedAttempts >= 3)
{
MessageBox.Show("Wrong password. Shutting down the application...");
this.Close();
}
else
{
MessageBox.Show("Wrong password. " + (3-failedAttempts) + " tries left.");
}
}
}
This way, if login isn't successful, app quits. Otherwise the main screen appears.
Note: This is a basic solution. In a more complex app, you'd want more sophisticated output (not hard-coded strings) and comparisions using VariableName.Equals();
Let's keep it simple (and in the style you've started) for now:
public partial class Form1 : Form //Change the default "form1" "Button1" etc names as soon as possible
{
private bool loginScreenVar = true; //when naming booleans, use "truth test" sounding names like isLoginScreenMode
private bool mainScreenVar = true;
public Form1() //this is a constructor, a method that is always called when a new instance of this object is created
{
InitializeComponent();
//use the constructor to set things up
loginScreenVar = true;
mainScreenVar = false;
ChangeScreen();//make sure loginscreen is showing
}
public void ChangeScreen()
{
//Login Screen
txtUsername.Visible = loginScreenVar;
txtPassword.Visible = loginScreenVar;
btnLogin.Visible = loginScreenVar;
lblLoginCaption.Visible = loginScreenVar;
lblUsername.Visible = loginScreenVar;
lblPassword.Visible = loginScreenVar;
//Main Screen
lblWelcomeUser.Visible = mainScreenVar;
btnViewDetails.Visible = mainScreenVar;
btnViewAccounts.Visible = mainScreenVar;
btnLogout.Visible = mainScreenVar;
MessageBox.Show(loginScreenVar.ToString());
}
//call this method when the login is correct
public void LoginCorrect()
{
loginScreenVar = false;
mainScreenVar = true;
ChangeScreen();
}
//double click your login button in the forms designer to add this click event handler
public void LoginButton_Clicked(object sender, ClickEventArgs e){
if(txtUsername.Text == "user" && txtPassword.Text == "pass"){
LoginCorrect();
} else {
MessageBox.Show("Login incorrect");
}
}
}
Forget the class Login:Form stuff unless you're really trying to explore object instantiation and making your own classes for things. Your Form1 will be on show when your app starts, do all the logic inside it
A better way to change screens in winforms is by creating two separate panels each one contains the desired controls to be shown and hide so that you can switch between them
Code example:
Form1_loaded(object sender, EventArgs e)
{
LogInPanel.Visible=true;
}
private void ConnectBtn_Click(object sender, EventArgs e)
{
// Do your checking here
// IF conditions met
MainPanel.Visible=true;
}
private void DisconnectBtn_Click(object sender, EventArgs e)
{
// Do your checking here
// IF conditions met
LogInPanel.Visible=true;
}
If you want to keep you methadologie make sure your program.cs runs Login class instead of Form1 class
I have some code that I found here. It traps the output from cmd.exe and also sends input to it. I am using it (heavily modified) on a form in our application. It works well so we can hide cmd.exe from the users but allow this form to administrators. Other benefits include a favorites list, ect.
Here is some code. Note: I deleted 70% of the code to simplify it so there may be issues. If anyone wishes to run this code and they are having problems let me know and I will edit it and make sure it works. All it needs is a form with two textboxes, txtConsoleIn and txtConsoleOut plus a timer; tmrSelectedCommand.
public partial class frmCommandPrompt : Form
{
private bool CancelOutput;
private bool FirstTime = true;
private bool InternalCommand;
private string InternalCommandResponse;
private ProcessStartInfo psi;
private Process p;
private string SelectedCommand;
private bool SelectedCommandExecuteNow;
private delegate void InvokeWithString(string text);
public frmCommandPrompt()
{
InitializeComponent();
}
private void frmCommandPrompt_Shown(object sender, EventArgs e)
{
this.txtConsoleIn.Select();
}
private void tmrSelectedCommand_Tick(object sender, EventArgs e)
{
tmrSelectedCommand.Enabled = false;
if (SelectedCommand != string.Empty)
{
if (SelectedCommandExecuteNow)
{
ExecuteCommand(SelectedCommand);
}
else
{
txtConsoleIn.Text = SelectedCommand;
txtConsoleIn.SelectionStart = txtConsoleIn.Text.Length;
txtConsoleIn.Select();
}
SelectedCommand = string.Empty;
SelectedCommandExecuteNow = false;
}
}
// Sending console commands
private void txtConsoleIn_KeyUp(object sender, KeyEventArgs e)
{
string Command;
if ((int)e.KeyCode == (int)Keys.Return)
{
InternalCommand = false;
Command = txtConsoleIn.Text;
ExecuteCommand(Command);
txtConsoleIn.Clear();
}
}
private void Async_Data_Received(Object sender, DataReceivedEventArgs e)
{
if (this.IsHandleCreated)
{
this.Invoke(new InvokeWithString(Sync_Output), e.Data);
}
}
private void Sync_Output(string text)
{
if (!InternalCommand)
{
if (!CancelOutput)
{
OutputText(text);
}
}
else
{
if (text != String.Empty)
{
InternalCommandResponse = text;
InternalCommand = false;
}
}
}
private void ExecuteRecentCommand(string Command, bool ExecuteNow)
{
SelectedCommand = Command;
SelectedCommandExecuteNow = ExecuteNow;
tmrSelectedCommand.Enabled = true;
}
private void ExecuteCommand(string Command)
{
CancelOutput = false;
p.StandardInput.WriteLine(Command);
}
private void OutputText(string text)
{
txtConsoleOut.AppendText(text + Environment.NewLine);
txtConsoleOut.ScrollToCaret();
}
}
I would like to display the path, like prompt=$P$G. I can issue the command echo %cd% and trap the output while suppressing both that command and output. I
can then output this and add a ">." So far so good. Now the problem.
Sometimes commands can change the path. So I need to check the path again, but when? What if someone enters a long running command? How do I know when it is done? I would prefer to make this work as closely to the original cmd.exe as possible for ease of use.
is cd the only command that changes the path (besides a poorly written batch file)? If so I can check the path after that command. But I will have to use a label since a command like dir *.txt /s issued from the root can take some time and it will not only look stupid to throw the path in the middle of that output but will make the form less useable than not even displaying the path at all.
Or maybe have a timer starting another instance of cmd.exe running every 20 seconds or so just to get the path and display it in a label. Sounds like a lot of wasted cycles for little gain.
At this point the best bet seems to force the users to check the path themselves. I can add a button to get the path to make it easier but I would prefer a nicer solution.
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.