Here is what I am attempting to make. It's a C# ASP page.
User picks a date
User hits "Import"
An Exe stored in /AppData/ runs
A status message of "Running" shows on the page <-- Issue here
When the exe closes, the status message says "Done"
Here is my code for the import button:
Process[] pDTExport = Process.GetProcessesByName("DTImport");
if (pDTExport.Length != 0)
{
prgStatus.Visible = false;
txtStatus.Text = "Unable to import data: another import process is already running. Please wait for it to finish before trying again.";
txtStatus.ForeColor = Color.Red;
}
else
{
txtStatus.Text = "The import process is running..."; <-- Issue here
LaunchExe();
}
And how I am launching the exe:
private void LaunchExe()
{
string exePath = Server.MapPath("~/App_Data/DTImport.exe");
if (File.Exists(exePath))
{
Process pImport = new Process();
pImport.StartInfo.FileName = exePath;
pImport.StartInfo.Arguments = "-d " + txtDate.Text;
pImport.Start();
pImport.WaitForExit();
txtStatus.Text = "Done!";
txtStatus.ForeColor = Color.Green;
prgStatus.Visible = false;
}
else
{
txtStatus.Text = "DTImport.exe was not found in /AppData/"
txtStatus.ForeColor = Color.Red;
prgStatus.Visible = false;
}
}
The issue I am having is updating the front end before I launch the exe. I want it to do this: Click button -> Show running message -> Launch exe.
Currently, when I click on the button, the exe runs, but I never see the "Import process is running" message, just the "Done!" line after it finishes.
I know it's because the line
pImport.WaitForExit();
is blocking the main thread. I tried storing/reading a ViewState variable in the Page_Load event, to try and launch the exe on the postback causes by the button, but it didn't work. Any ideas how on how I can update the UI before the exe runs?
You can register an event Handler to the pImport.Exit event. This allows you to avoid waitForExit. In the registered method you can manage the update to import done.
Related
I'm building a windows form application that stores employee information records in a database, including SSN. Next to the textbox where the SSN is input is requested, I have a checkbox that when clicked, shows me the full SSN instead of the last four digits. To ensure that only an administrator is accessing this information, I created a prompt form connected to a MS SQL DB that stores an admin password and would like to ask the user for a password for security purposes. Also, i'd like to be able to call this form whenever needed. I successfully implemented it but would like to add a feature that allows for 3 tries. Is there a way to stop the program execution and keep prompting the user for input in a textBox?
output is a variable that stores the result of the 'SELECT' query that gets the password.
confirmation is the Accept Button.
The only option i could think of forcing input was calling a new form. Only problem is, this code is inside the form and my gut tells me that's not the answer to this problem. I must be missing something.
confirmation.Click += (sender, e) => {
//If Password is correct.
if (textBox.Text == output)
{
isCorrect = true;
Pprompt.Close();
}
else
{
isCorrect = false;
//While the password is incorrect.
while (isCorrect == false)
{
//textBox.Text = "";
if (textBox.Text == output)
{
isCorrect = true;
Pprompt.Close();
break;
}
tryCount++;
if (tryCount == 3)
{
MessageBox.Show("Access Denied.");
break;
}
}
}
}
What I'd like to happen is for the form to keep asking me for input until the try limit is exceeded.
You cannot have the loop inside the click handler, because the UI freezes while it is running and the user does not get the opportunity make any entries.
Process only one entry and process the next when the user clicks the button again.
confirmation.Click += (sender, e) => {
if (textBox.Text == output) // Password is correct.
{
isCorrect = true;
Pprompt.Close();
}
else
{
isCorrect = false;
textBox.Text = "";
tryCount++;
if (tryCount == 3)
{
MessageBox.Show("Access Denied.");
Pprompt.Close();
}
}
}
Unless you are using multi-threading or async/await, the following is true:
Winforms is event based. I.e., if no event handler is running, no code is running.
If code (i.e. an event handler) is running, the user interface (UI) is frozen and the user cannot make any input. He cannot enter text or click any buttons, cannot scroll lists and cannot resize or move the window.
While an event handler is running, no other event handler will ever be called. I.e., an event handler will never be interrupted by another one. This prevents you from having to deal with multi-threading issues unless you are using multi-threading explicitly.
If an event should be fired (e.g. a timer tick) while an event handler (e.g. a button click handler) is running, the execution of the event handler associated to this new event will be deferred until after the first event handler returns.
I am trying to open Active Directory using a button on my application. I don't want to get or set information from or in AD, just open it. The code below gives the error: Exception thrown: 'System.ComponentModel.Win32Exception' in System.dll, which isn't very helpful. Any ideas?
private void btnAD_Click(object sender, EventArgs e)
{
try
{
Process procAD = new Process();
procAD.StartInfo.FileName = "C:\\Windows\\System32\\dsa.msc";
procAD.Start();
}
catch
{
Console.WriteLine("Didn't open...");
}
}
There's a few ways. I would suggest that you actually start the mmc.exe executable and give it the msc file as an argument. For example:
Process procAD = new Process();
procAD.StartInfo.FileName = "C:\\Windows\\System32\\mmc.exe";
procAD.StartInfo.Arguments = "C:\\Windows\\System32\\dsa.msc";
procAD.Start();
You should also be able to do this, which is the same a double-clicking the file:
System.Diagnostics.Process.Start("C:\\Windows\\System32\\dsa.msc");
I have created setup of my application using Windows Installer.
Now I want to Start application at Windows Start-Up and move it system minimize tray as i don't want to display GUI(View) at Windows Start-Up.
I have searched in Google and i found to use Registry key But that is not enough for me as i also want to move to system minimize tray and application run.
My purpose to do it is, user do not feels annoying when application starts every time when he/she starts system.
Can anyone have answer?
Thanks..
In your application, add an event handler for the FrameworkElement.Loaded event. In that handler, add the following code:
WindowState = WindowState.Minimized;
This will minimise the application when it starts.
To start the application when the computer starts, you'll need to add your program into Windows Scheduler and set it to run at startup. You can find out more on the Schedule a task page at MSDN.
You also have to set this property to remove it from the taskbar
ShowInTaskbar= false;
Maybe this answer is late, but I still want to write it down to help those who haven't found solutions yet.
Firstly you need to add a function to minimize your app to tray when it autostarts as system startup.
In your App.xaml file, change the original StartupUri=... to Startup="App_Startup" as below. App_Startup is your function name and can be changed.
<Application x:Class="Yours.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="App_Startup">
In your App.xaml.cs file. Add the function below:
public partial class App : Application
{
private void App_Startup(object sender, StartupEventArgs e)
{
// Process command line args
var isAutoStart = false;
for (int i = 0; i != e.Args.Length; ++i)
{
if (e.Args[i] == "/AutoStart")
{
isAutoStart = true;
}
}
// Create main application window, starting minimized if specified
MainWindow mainWindow = new MainWindow();
if (isAutoStart)
{
mainWindow.WindowState = WindowState.Minimized;
}
mainWindow.OnAutoStart();
}
}
In your MainWindow.xaml.cs, add a function as below:
public void OnAutoStart()
{
if (WindowState == WindowState.Minimized)
{
//Must have this line to prevent the window start locatioon not being in center.
WindowState = WindowState.Normal;
Hide();
//Show your tray icon code below
}
else
{
Show();
}
}
Then you should set you app utostart as system start.
Now if you have a switch to decide whether you app to autostart as system start, you can just add the function below as your switch status changed event function.
private void SwitchAutoStart_OnToggled(object sender, RoutedEventArgs e)
{
const string path = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Run";
var key = Registry.CurrentUser.OpenSubKey(path, true);
if (key == null) return;
if (SwitchAutoStart.IsOn)
{
key.SetValue("Your app name", System.Reflection.Assembly.GetExecutingAssembly().Location + " /AutoStart");
}
else
{
key.DeleteValue("Your app name", false);
}
}
If you want to automatically start the application for all users on Windows startup, just replace the forth line with
RegistryKey key = Registry.LocalMachine.OpenSubKey(path, true);
^_^
I've searched through stackoverflow but cannot find the answer. I don't know if I could make this question clearly. I'm not an English-speaking person anyway =.=
I'm using c# and visual studio 2010 to develop.
I'm making a Form for user to login, I would like this form test sql server connection during load event.
It seems easy, the code is:
private void testDBconnection()
{
label3.Text = "Connecting to Database Server......";
SqlServerConnection ssc = new SqlServerConnection();
bool conOK = ssc.isConnectable(ssc.makeConnectionString(
SqlServerConnParamters.SqlServerIPAddress,
SqlServerConnParamters.AccountValidationDatabaseName,
SqlServerConnParamters.SqlServerUserName,
SqlServerConnParamters.SqlServerPassword,
5));
if (conOK)
{
label3.Text = "";
}
else
{
label3.Text = "Database connection failed";
button1.Enabled = false;
}
}
I put this method in Form_Load event.
But in runtime, this process start even before this form shows. And the validation could last for 15 seconds by default(I set it to 5 but it also takes time). If the connection has some problem, it will display like the programe failed to open, but it will shown after it failed to connect to database.
My intention is tell the user by Label3 displaying "Connecting to Database Server......", and tell user if connection failed.
I was trying to find Form Event like "Loaded_Complete", or "Loaded"(I found Form_Closed though), but I couldn't.
I guess it has something to do with thread, programe sleeping, or else. I hope someone could help me on this. Thanks a lot guys!
I would use a BackgroundWorker this way. That will defer the database check operation, and the form load will not be locked by it.
label3.Text = "Connecting...";
button1.Enabled = false;
var bkw = new BackgroundWorker();
bkw.DoWork += (s, ev) =>
{
SqlServerConnection ssc = new SqlServerConnection();
ev.Result = ssc.isConnectable(ssc.makeConnectionString(
SqlServerConnParamters.SqlServerIPAddress,
SqlServerConnParamters.AccountValidationDatabaseName,
SqlServerConnParamters.SqlServerUserName,
SqlServerConnParamters.SqlServerPassword, 5));
};
bkw.RunWorkerCompleted += (s, ev) =>
{
if ((bool)ev.Result == true)
{
label3.Text = "Connected";
button1.Enabled = true;
}
else
{
label3.Text = "Database connection failed";
}
bkw.Dispose();
};
bkw.RunWorkerAsync();
However, this would require some exception handling. If an exception occurs in the DoWork event, then you can check in the RunWorkerCompleted event wether ev.Error is null or not (it contains the exception) and react accordingly.
Use timer.
In form load event start the timer(set interval to 2 sec or what ever you want). As timer ticks call your connection method. At the starting of your testDBconnection() method, stop the timer and dispose it because you don't need it any more.
You should not be using the Form_Load event to fire events when a form loads, you should override the OnLoad() method instead, that way you control when the code gets fired (it's possible for multiple subscribers to be listening to Form_Load and you don't know what order they will run in).
The quickest and dirtiest way of getting the screen to refresh is to Add
Application.DoEvents();
After changing the label, this forces the screen to update. In general though this is bad practice and the background thread above would be a better solution long term.
I have the following code for a button click event. This event should open the command window and execute the application:
private void start_Click(object sender, EventArgs e)
{
if (textBox1.Text == " " || textBox2.Text == " ")
{
MessageBox.Show("Header File or Executable Missing");
}
else
{
Process.Start(textBox1.Text);
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = textBox1.Text;
string filename = textBox1.Text;
int found = filename.LastIndexOf("\\");
int end = filename.Length;
string temp = filename.Substring(found);
startInfo.Arguments = temp + textBox2.Text;
Process.Start(startInfo);
}
}
The problem that I'm facing out here is that when I click the button, the command window does not persist and I don't know whether the command window displays an error message or not because it opens & closes in a flash. Can anybody tell me what is going wrong here and give me a few hints how to go about solving the issue?
If you want to start a new console application from your Windows Forms application you need to either pass in the path to such an application or to cmd.exe + the run command for that application. Make sure the code in your console application halts by asking for a Console.ReadKey(true) or similar.