How to make process stop running with keystroke - c#

When I run my selenium framework it runs as a process. There is no user interface. It runs until it completes or until it encounters an exception that stops the test. Currently, the only way to manually stop the test is to kill the process in Task Manager.
I would like the user to be able to press a key, like escape, to stop the process.
I've only so far been able to find such functions related to a project running in a console

You could create a batchfile with the following contents:
taskkill /F /FI "IMAGENAME eq notepad.exe"
(replace 'notepad.exe' with the correct program name)
When you create a link to that batch-file, you can also specify a 'Shortcut key' to start this batchfile.

Thank you Luuk. To work around I created a batch file that is now included in the build.

Related

Run an External Program or Batch File From a C# Xamarin Program

I want to have my C# (Xamarin) program run an EXE or batch (BAT) file. The user will be running my program, and will click on one of several buttons, some of which open Web pages and others of which run external programs. These files will be on the same computer as the one running the main program and don't need greater permissions. The overall program will be in Windows, UWP.
I already have code to pull info from the database saying "the button the user clicked references a program and it's (eg) C:\Tools\MyTool.exe". (Real path more like (C:\Users\Me\source\repos\ProductNameV2\ProductName\ProductName.UWP\Assets\EXE\whatever.exe".) I used a "demo.bat" file containing nothing but echo and pause statements, or references to a built-in Windows program like Notepad or Calc that an ordinary command prompt can recognize without an explicit path (ie. that's part of the recognized system Path). Yes, the real path to the dummy file does exist; I checked. I've also explicitly added files demo.bat and dummy.txt to my C# project.
Here's roughly what I've tried so far to actually run a batch file, or an EXE, or just to try opening a text file. Nothing works.
1)
bool check = await Launcher.CanOpenAsync(#"file:///C:\Tools\demo.bat"); // Returns false.
bool check = await Launcher.CanOpenAsync(#"file:///C:\Tools\dummy.txt"); // Returns true.
await Launcher.OpenAsync(#"file:///C:\Tools\demo.bat") // Seems to do nothing; silently fails.
await Launcher.OpenAsync(#"file:///C:\Tools\dummy.txt") // Same.
2)
Process batchProcess = new Process();
batchProcess.StartInfo.FileName = #"file:///C:\Tools\demo.bat"; // Same result with notepad.exe
batchProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
batchProcess.Start();
batchProcess.WaitForExit();
// Result: "Access is denied" error during Start().
3)
var otherProcessInfo = new ProcessStartInfo(#"file:///C:\Tools\demo.bat")
var otherProcess = Process.Start(otherProcessInfo);
otherProcess.WaitForExit();
otherProcess.Close();
// Result: "The system cannot find the file specified" despite it being the same path as in previous examples.
// Also tried literally using the path C:\Tools\demo.bat, without adding that to the C# project.
// One thing that slightly works is to use:
var otherProcessInfo = new ProcessStartInfo("cmd.exe", "/c echo Hello world!");
// This version opens a window and instantly closes it again. With "/c pause" instead, it opens, saying "press any key to continue".
// Chaining multiple commands with newline or semicolon characters doesn't work as a form of batch file.
So: the only tiny success I've had here is to run cmd.exe, to run a one-line command. I suppose that depending on what the batch file must do, there's some possibility of receiving a string, breaking it into lines, then running cmd.exe using method 3 to call them one at a time. Which is ugly at best.
Is there some better way to do this -- to run a batch file or an EXE from within my program?
EDIT: Yes, I did in fact look at documentation before asking. Why did I use URIs? Because of multiple errors telling me that the simple path strings ("C:\this\that") I was using were in an "Invalid URI format". Using Process.Start("notepad.exe") silently fails, doing nothing. Using a method involving System.Diagnostics.Process (found at How to run external program via a C# program? and yes I saw that before) fails with an error of "Access denied" when using my batch file reference, or silently failing (no window opens) using plain old notepad.exe. I avoided setting Process options that say hide the window.
So to rephrase: Is there a way to make my program run some EXE somewhere on the computer, or to run a batch file that has more than one command in it? What is that way?
Using the data you collected, I was able to run a batch file by doing the following:
var strPathToExeOrBat = System.IO.Path.Combine("C:\\Tools", "demo.bat");
var otherProcessInfo = new ProcessStartInfo("cmd.exe", $"/c call \"{strPathToExeOrBat\"");
var otherProcess = Process.Start(otherProcessInfo);
otherProcess.WaitForExit();
otherProcess.Close();
I also think it would be helpful to review the capabilities of the cmd.exe application.
I found this post to be helpful:
https://stackoverflow.com/questions/515309/what-does-cmd-c-mean#:~:text=%2FC%20Carries%20out%20the%20command%20specified%20by%20the%20string%20and,switches%20by%20typing%20cmd%20%2F%3F%20.
In particular the /k option will leave the window open, if you don't want it to close after running a script.
Thank you very much for your question! It really helped me find the answer to this! (at least for my situation of a .NET MAUI windows app, but MAUI is built off of Xamarin.Forms, so you shouldn't have a problem doing the same thing)
EDIT: Updated to use file path from question and string interpolation with System.IO.Path.Combine for slightly greater cross platform capability

VSIntr no data is collected

I am trying to instrument our application looking for performance optimizations, but I cannot manage to get any data out of it. I am mainly interested in function running times and how many times where they were called.
Can you point to the flaw in my process please?
Here is what I do:
1. VSInstr MyAssembly.dll
This creates the instumented dll (like twice the size) and backs up the original.
I get a warning about strong-named things so step 2
2. sn -Ra MyAssembly.dll TheKeyFile.snk
Says resigning is successfull
3. VsPerfCLREnv /traceon
Setting up environment variables
4. Running the program. I go right before the step I want to investigate.
5. VsPerfCmd /start:trace /output:../Reports/Report.vsp
Starting the trace
6. Clicking the button to do the process (app creation) and waiting to finish
7. VSPerfCmd /shutdown
Stop tracing.
8. VSPerfCLREnv /off
Reset environment to normal
At the end of all this I check the Report.vsp file. It is a 148KB file which when opened in VS2017 throws these two error popups and fails to open anything:
File contains no data buffers
Failed to analyse report
The solution was to
Use /globaltraceon instead of /traceon
First run VsPerfCmd /start:trace and only start the service afterwards
Call VSPerfCmd /processon:[PID] to attach to process
Stop the service when finished ( /shutdown won't complete otherwise)
So the steps looked like this:
VSInstr MyAssembly.dll
sn -Ra MyAssembly.dll TheKeyFile.snk
VsPerfCLREnv /globaltraceon
Set service on Manual startup
Restart computer
VsPerfCmd /start:trace /output:Reports/Report.vsp
Start service manually
VsPerfCmd /processon: (look up in Task Manager)
Do whatever you want to measure
Stop service
VsPerfCmd /shutdown

Detect if the application started made another process

The uninstallers from an application normally launch new process and I am trying to make my application know about it so if after the uninstallation, it will execute some tasks.
NSIS for example.
string uninstallstring = "C:\\Program Files (x86)\\Pidgin\uninstall.exe"; // reg.GetValue("UninstallString").ToString();
Process p = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = uninstallstring
},
EnableRaisingEvents = true
};
p.Start();
p.WaitForExit();
Debug.WriteLine(p.HasExited);
Debug.WriteLine(p.ExitCode);
// clean up TASKS after uninstall here
// clean clean clean
code above will try uninstall Pidgin. It will Start() and it should wait for the uninstaller to finish its job and show in Debug panel True/False (HasExited) as well as its ExitCode.
The problem there is, after Start() is executed, the "uninstall.exe" launched a new application "Au_.exe" in "C:\Users\Jayson\AppData\Local\Temp\~nsu.tmp" and "uninstall.exe" closed, WaitForExit() has done its job and Debug panel shows
True
0
those are "HasExited" and "ExitCode" but the Pidgin Uninstall is still running which tells me that "uninstall.exe" launched the "Au_.exe" as not his child process.
My question is, how do I make sure that the uninstaller finish its job?
If you know name of application, started by unnistaller, you can try to check existence of his procces use Process.GetProcessesByName("Au_.exe") by timer. When procees appeared and then disappeared you can raise callback.
Also you can read about GetExitCodeProcess
I think there is no general solution here. You rely on external component that doesn't work as expected (normally we expect that uninstall.exe will exit only after complete uninstall and will return corresponding error code, but it doesn't).
There are several workarounds:
When uninstall.exe complete, look for Au_.exe process and wait for its completion.
After uninstall.exe (and may be Au_.exe) check is it really uninstall Pidgin. You can check filesystem or some special registry keys. Probably you expect something before your custom cleanup tasks. If it was not uninstalled properly - repeat or don't clean up (may be show some error or write log message - it depends on your application).
Made your custom uninstaller for Pidgin that will cleanup all necessary resources. Pidgin is open-source, so you can look how its installer works. May be it will be enough to simply modify existing installer.
Don't worry about Au_.exe and just cleanup your resources - may be it's really not a problem for your application.
(if possible) Ask user of your application to uninstall Pidgin. When user did it - make some simple checks (e.g. C:/Program Files/Pidgin is deleted) and do your cleanup.

How to run exe in mono in the background

Okay, so I have a .net exe, and it runs when I type mono myexe.exe. However, if I want to use another command or close the terminal window the app stops executing.
I have tried using mono myexe.exe & and it runs and showing [8] 20078 etc., but once I type something else it shows [8]+ Stopped, and then executes the command I typed in.
Any ideas?
how about nohup mono myexe.exe &
If you want to use & then look into outputting the result to a file.
nohup mono program.exe > program.out &
The right way of doing this would be to create a daemon with your linux distro.
You can also run it as an service using this line of code:
mono-service -l:/tmp/myservice.lock ./ServiceDaemon.exe
where -l:LOCKFILE specifies the file to use for locking. When you look into your lock file, you will see the process id. The process id you can use to kill the service, whenever you need to terminate it.
Source: blog.chudinov.net

c# program works from cmd prompt but not run separately?

I would post a snippet, but I honestly have no idea what part of my code could possibly be doing this. The program is sizable, I don't want to make you all wade through it. What kinds of things could possibly be the cause of this? Everything works perfectly when called from the command prompt: "readoo.exe". But when I click the exe in its file. . . "readoo.exe has encountered a problem and needs to close. . ."
this is intended to eventually be a scheduled task -> i'm worried, will it work?
i've never debugged, all i've ever used is notepad. I am learning, and feel that this strengthens my understanding of a project.
it crashes nearly immediately. there are no shortcuts, though the file paths are relative.
trying this method: shortcut -> properties -> shortcut -> Start In. I don't have a "shortcut" option
my program reads log files, parses, and creates 4 new files based on the found content
Microsoft Error Report says file not found. But how can this be? the files are there, albeit relative.
Take a copy of your project, and then start hacking bits out of it. When it no longer crashes, you've removed the bit causing the problem.
At what point does it fail when you double-click on it? Immediately, or only when you take a certain action?
You could also add a lot of logging to it, which could indicate where the problem is too.
This is probably looking for a dll that it can't find or is finding a different version from what it wants.
You could try Process Monitor or Process Explorer from sysinternals to see what dlls it loads when it does work and where it finds them.
Try putting a System.Diagnostics.Debugger.Break()call as the first thing in Main() and you'll be asked to attach a debugger - this should definitely show you what is different betweent the 2 invocations.
I would start with identifying what is different in the two methods of execution. Is there a shortcut modifying anything?
The starting directory?
The execution account?
command line arguments?
There are 2 things that it could be:
The current directory could be different when you click on the program or run from the command prompt.
The settings and path could be different when you click on the programe you are using the standard command prompt, are you opening the visual studio command prompt when you run the program from the prompt.
If your application relies on some file that should be on the same path of that exe, that can occurr.
You will have to change the properties of the exe (or shortcut to the exe) to "Start In" the directory where your exe is. For a shortcut, right click on the shortcut -> properties -> shortcut -> Start In.
I guess that is what I think could be the cause.
EDIT: Add a Console.ReadLine towards the end of your code to make it pause for you to see any exception thrown. That should help when you run it using windows explorer.
Put a try/catch around your code and output the exception message to the console in the catch block. That should give you some clues.

Categories