I'm trying to include in my Windows Form App a way that when user tries to shutdown windows it opens a dialog box with CANCEL option....that office classic one.
In other topics, people describes how to prevent windows shutdown. They use a dialog box for this. It helps but if the user immediately clicks in any option in this box, windows closes the application.
You can understand what I'm meaning, doing the following test:
In windows Vista or 7 Open Paint, Word or any office soft and begin writing something. Do not save it.
Try to shutdown windows and when the classic save dialog box appears IMMEDIATELY click in "cancel".
You will see that the application continues to work and windows is asking you what you want to do.
I tried to follow this Microsoft Link but if I click "ok" in Message Box, the App closes.
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason.Equals(CloseReason.WindowsShutDown))
{
if (MessageBox.Show("You are closing this app.\n\nAre you sure you wish to exit ?", "Warning: Not Submitted", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Stop) == DialogResult.Yes)
return;
else
e.Cancel = true;
}
}
Although delay windows shutdown is not recommended it is possible using shutdown scripts. You can configure your own script file using gpedit.msc configuration file.
I have read that these scripts can delay the windows shutdown up to 10 minutes.
I hope it helps
Related
When creating a .NET Core Web app C# and debugging you can opt to Launch the browser when Running the app. The console launches and then the url launches in your preferred browser. Once you close the browser tab opened by the debug session, the app process it stop and is no longer running on the machine.
When I published the app, the page does not launch automatically so I am starting a new Process to do so. I've added an event handler to the process before starting it but the since the app didn't launch the process it doesn't receive any notification when the tab has been closed.
What is the proper way to go about launching your .NET Core web app and/or handle communicating between the two?
I even tried adding a Close button but JS won't allow me to close the window as I haven't opened it.
I'm creating my Process as follows:
var p = Process.Start("cmd", "/C start http://localhost:5000");
I've tried
p.WaitForExit();
p.EventHandler += newHandler;
and I also tried using ProcessStartInfo but the only thing that is working right now is if I set a Timer and then kill the process when the timer is activated but this doesn't seem too clean.
Any advice is appreciated!
I wanted to follow-up with the process I feel is the most graceful way that I am happy with.
A few pieces of info that may be helpful in creating your own process. It was a goal of mine to use .net core to self host a client side web app which communicates with a server hosted web api.
I am using Razor views and .net core 3.1
I am using Startup and utilizing applicationLifeTime to handle OnStartup where I start the process as I described in my original post.
At this point the web app opens and if the user decides to close the browser the process doesn't know and continues to run in the background.
In order to prevent it from continuing to run and allow the user to initiate it closing, I made a few the following additions.
First, I added a timer that uses a configurable length of time via appsettings. When starting the process that opens the browser I call and set the timer that will perform an "AutoShutdown" if the process is still running after the configurable length of time that I defaulted to 1hr. I am using Enviroment.Exit(0) in the event that handles closing the running process.
My View is using a Model that contains a property who's value will be set from the page via a hidden field.
I added a Close button to the View that is displayed to the user at startup. When the user clicks close, I use jquery to set a hidden field in the view and then I use jquery to submit the form.
When the Model is received, the value set by the client's request to close is true and you can handle the close without display errors if you use a Timer and Start it almost immediately after redirecting the View to a view with a message to the client. Whether they leave it open or close it, the process will have closed. Example of how I did it below.
Finally, in Main.cs I put a check in to check if there is an existing process running and close it before starting a new one. I added this because the client may not always close the browser and/or they may attempt to start it before the "AutoShutdown" timer has kicked in.
This is more "hacky" then I would like but I couldn't find anything else that didn't throw and show Bad Request when trying to use Envirnoment.Exit(0) when the client is still has the view open and I was unsuccessful at being able to allow console input so that I could send close to the console.
This is how I am handling the close request from the client in my Controller
if (ui.HandleCloseApp)
{
var app = Process.GetProcessesByName("NameOfYourWebApp");
if (app.Length >= 1)
{
foreach (var p in app)
{
if (p.ProcessName == "NameOfYourWebApp")
{
p.Close();
p.Dispose();
}
}
}
var t = new System.Timers.Timer(10);
t.Elapsed += OnClose;
t.Start();
return View("Close");
}
I hope this helps someone else in creating their own "graceful" process that shouldn't be :)
I'm still open if anyone has input to share. Thx!
I have a WinForms WebView2 project that is a simple bot running some JavaScript on a webpage. I am using JS to click an element on the webpage and download a file. The website prompts me with "Are you sure you want to leave the page?" dialog, So I want to send the RETURN keyboard press to confirm that I want to leave the webpage and download the file.
I want to run this automatically using windows Task Scheduler. This method works, as long as I am remote connected to my server and the window is not minimized. However, when I am not remote connected to my server, my enter keypress returns and error.
I have tried this code with SendKeys
//Get Webview proccess
Process p = Process.GetProcessesByName("msedgewebview2").FirstOrDefault();
if (p != null)
{
IntPtr h = p.MainWindowHandle;
SetForegroundWindow(h);
printToTextbox("pressed ENTER key");
SendKeys.SendWait("{ENTER}");
await checkDownloadFinished();
}
I start my Bot and then exit my remote session. When I return, this error is given when the program reaches SendKeys.SendWait("{ENTER}");
System.ComponentModel.Win32Exception: 'Access is denied'
I also tried the Nuget package InputSimulator
Process p = Process.GetProcessesByName("msedgewebview2").FirstOrDefault();
if (p != null)
{
IntPtr h = p.MainWindowHandle;
SetForegroundWindow(h);
printToTextbox("pressed ENTER key");
InputSimulator s = new InputSimulator();
s.Keyboard.KeyPress(WindowsInput.Native.VirtualKeyCode.RETURN);
await checkDownloadFinished();
}
Following the same proccess, I start my bot and exit my remote session. When I return, I am met with this error:
System.Exception: 'Some simulated input commands were not sent successfully. The most common reason
for this happening are the security features of Windows including User Interface Privacy Isolation
(UIPI). Your application can only send commands to applications of the same or lower elevation.
Similarly certain commands are restricted to Accessibility/UIAutomation applications. Refer to the
project home page and the code samples for more information.'
Is there another c# compatible way to send keystrokes? Or is there a way to prevent the dialog from ever popping up? Thank you!
You're doing it wrong :-)
You should try to look at: CoreWebView2.ScriptDialogOpening Event.
The scriptdialogopening has its eventargs with an Accept() method to click Ok on the dialog.
Here's the eventargs link: CoreWebView2ScriptDialogOpeningEventArgs
Now you don't have to mess with SendKeys.
I would like to manage the behavior of my application when it closes (and not when it is suspended), but I couldn't find any method to override.
In this application, a user can log in with his profile: when he is in the main page of the application and presses back button, the app goes suspended and it's ok then that if it's resumed the user is still logged; what I want to do is that if the application is closed, the user won't be logged anymore, and if he opens the app again he has to log in again.
When the login is successful, I set local settings this way:
var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
localSettings.Values["Logged"] = true;
So I would like to set to "false" the value of logged whenever the application is closed (not suspended), but like I said I couldn't find any kind of "on close" method to override.
The only way I've found to achieve what I want is to set
var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
localSettings.Values["Logged"] = false;
in the "OnLaunched" method in App.xml.cs, but it's not working fine.
Define a handler vor the Application.Suspending event (https://msdn.microsoft.com/en-us/library/windows.ui.xaml.application.suspending).
The system suspends your app whenever the user switches to another app or to the desktop, and resumes your app whenever the user switches back to it. However, the system can also terminate your app while it is suspended in order to free up resources.
So there is no special event for closing the app.
I have a C# application, in which I access outlook through the Office PIAs in order to parse appointments. In my application, when I create my outlook object, a new outlook process is created in the task manager. When I close my application, I also quit the outlook object. This shuts down the outlook process in my task manager.
My problem is, when the user is also interacting with outlook. Specifically, if the user has outlook opened, when my program closes, my program also closes that user's outlook program. Experimenting with opening outlook both manually and with my program, while watching the task manager, it seems that only one instance of outlook can ever be running at the same time, and both the user and my program then accesses that same instance, so when I close outlook from my program, I also shut down the user's program.
Strangely enough, the reverse is not the case. If the user shuts down outlook, while my program runs, his window will disappear, but the outlook process will not shut down, and my program can still continue. It is as if the window is only a client of the outlook process, although there is no separate process for the window. Is there a way for me to see, if my program is the only one using the outlook process, or if there are any "user window clients" open, so I can avoid shutting down outlook, when it is still in use?
I found a solution myself. I turns out that outlook keeps track of how many explorers are open on it. Reaching zero explorers does not cause a shutdown of the process, but it indicates that no user has any normal outlook window open, so the process can be safely shut down. In my project I have a single class which accesses outlook. My solution is to test for zero explorers in the destructor of that class (the following code assumes "using Outlook = Microsoft.Office.Interop.Outlook;"):
~OutlookAccessor()
{
try
{
Outlook.Application app = new Outlook.Application();
if (app.Explorers.Count == 0)
{
((Outlook._Application)app).Quit();
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
}
catch (System.Runtime.InteropServices.COMException)
{
; // nevermind, we're only trying to free the Outlook COM object, and the most probable cause for this exception is that office is not installed.
}
}
Of course, you have to be careful to close all explorers you use in your code, or the solution will not work, e.g.:
private void AccessOutlook(Outlook.MAPIFolder topfolder)
{
Outlook.Explorer explorer = null;
try
{
explorer = topFolder.GetExplorer();
... // do stuff with the explorer
}
finally
{
if (explorer != null)
{
((Outlook._Explorer)explorer).Close();
}
}
}
I am developing a simple application where in we have predefined quotas on usage for each user on the system..
and if the quota is up..the system should logoff of the user account..
this will happen if the application is allowed to run..
but if the user is closing the application on his own ..the app should automaticaly logoff the account..
i did exactly that in writing forced logoff code in form-closing event..
but if we are closing the app/process using the taskmanager..
the form closing event is not being called.
and so the user is able to continue even if his quota of time is up..
can anybody helpme out with this..
This is nice question.
Maybe you can make an applicaton to watch task manager and user status. I am not sure about that could help you but I gonna write
for ex
Process[] myApp = Process.GetProcesses("My Application");
if (myApp.Length == 0)
{
// App closed, and check the user status
// If user is still up, make it logoff,
// Also you can track processes with ProcessId too GetProcessesById(5415)
}
else
{
// App is running, there is no problem
}