How to open an application on active display while using Process.Start()? - c#

I am using
System.Diagnostics.Process.Start(ProcessInfo);
to open a TEXT file in notepad from within my windows form application.
Detailed code snippet is
ProcessStartInfo PSI = new ProcessStartInfo("notepad.exe", LogFile);
PSI.WindowStyle = ProcessWindowStyle.Normal;
System.Diagnostics.Process p = System.Diagnostics.Process.Start(PSI);
However, it opens notepad on the default desktop but not on the extended desktop on which the main application is running.
Now, the question is, how to open notepad on the active desktop i.e. Window on which the current application is running?

Other that specifying the initial window state (normal, hidden, etc), you have basically no control over how the newly launched application starts up and where it shows itself.
The best bet here is to launch the application, then use its window handle to tell it to move. This all requires using P/Invoke, to call MoveWindow. The C# signatures for all of those functions are on pinvoke.net.
Here's a very simple (VB.NET) example that shows the basic idea. In this case, as #Lloyd points out, the window handle you need is the Process.MainWindowHandle you get back from Process.Start. Note that Process.MainWindowHandle isn't filled in immediately; you typically need to call WaitForInputIdle to make sure the window actually gets created. If MainWindowHandle is 0 then you'll know it's too soon.

Related

Call a console application without waiting for it

I'm developing a Delphi application which calls a .net console application in hide mode, but the problem is: when I close my delphi application then the console application also closes, even using ShellExecute without specifying to wait for a SingleObject.
I tried that same Shell call for Windows Calc, so now even when I close my app the Calc remains opened and that is the behavior that I'm looking for.
Does someone know if it's possible to call a console application and leave it independent from parent process and how to do that, so it does not close when main application closes?
The issue is that the child process attaches to the console of the parent process. When the parent closes, it's console closes, taking the child with it.
Resolve this by giving the child process its own console. Use CreateProcess passing the CREATE_NEW_CONSOLE process creation flag. You will also want to pass CREATE_NO_WINDOW to avoid showing the new console window.

How does Windows force "minimized" state from a desktop shortcut?

I have an application that is designed to minimize to the system tray. No issues there.
The problem I am having is that I cannot determine what Windows is doing to force the minimized state when I set up a desktop shortcut to that executable and launch it, such as:
I put some debug outputs in the form's constructor and launched via the shortcut. I get no command line arguments and a check of WindowState yields Normal. Yet the app starts minimized to the taskbar.
However, that's the rub: I want it to start minimized to the system tray, just as it would if the form were on-screen and the user minimized it. Not all the time, just when a "minimize" shortcut is used, or when the user clicks Minimize on the form, of course.
EDIT: for the curious...my initial testing was flawed because I checked in the constructor. Placing the test in the Load method produced a Minimized state, to which I could then react and call my code to perform the "minimize-to-tray".
Windows is starting the process with parameters to minimize the main window.
In C#, you can do the same by setting WindowStyle (MSDN) at ProcessStartInfo for use in Process.Start().
In the native world, you would use the CreateProcess (MSDN) API and pass a STARTUPINFO, setting wShowWindow to SW_MINIMIZE.
To query the window state, use GetWindowInfo (MSDN), look at dwStyle and check if WS_MINIMIZEis set. In C#, this should be in Form.WindowState.

How to open two separate (default) browser windows instead of new tabs

I'm trying to use C# to open two separate browser windows side by side. I've tried using Process.Start(url) but that causes Chrome to open new tabs instead of new windows. This seems to work on IE, however I'd like to have code that can work with different types of browsers, namely: IE, Chrome, Firefox, and Safari. How do I detect the default browser and then open two separate windows side-by-side? Additionally, I want to be able to position the two windows next to each other, is that possible?
If you want to open new window in chrome instead of new tab, this code worked for me
Process process = new System.Diagnostics.Process();
process.StartInfo.FileName = "chrome";
process.StartInfo.Arguments = <yoururl> + " --new-window";
process.Start();
This is more about the way that the browser is configured than how the process is called from C#. In both cases, the system simply calls the default program assigned to handle the URL. There may or may not be arguments to that command, but typically it will simply invoke chrome.exe <url> and from there, the chrome.exe process decides how to handle the parameter.
The only method I am aware of would be to examine the registry (under HKEY_CLASSES_ROOT\http\shell\open\command) and parse the string value. Once you know the specific browser, you may be able to control the presentation using command-line arguments. Of course, this is specific to Windows and may be a pain to manage.
If the browser does not support setting a geometry from the command line, you will need to use FindWindow and SetWindowPos (using P/Invoke) to manipulate the window locations.
I am not sure about your application, but would embedding a WebBrowser Control meet your needs? Then you would have total control of the presentation.

How to open particular directory dialog box?

I'm developing a program in c# im stuck with this issue.
I want to show dialog box which refers to a particular directory.
I know that there is OpenDialogFolder and SaveDialog, but I don't want to save or open any files what I want is just to open a specific directory dialog box.
Like this screenshot:
It looks like you just want to open a copy of Windows Explorer. You can do that by simply calling Process.Start() and specifying just a folder path with no filename:
Process.Start(#"C:\Temp\");
The default behavior of the Windows shell, given a command like this on the command line (or a shortcut or a Run command) is to open Windows Explorer to show the contents of the specified path.
Now, Windows Explorer is an external process, which you are launching and then letting it do its thing. It therefore won't behave exactly like a modal dialog box, like preventing the dialog losing focus to another window. However, you can mimic the "can't do anything else with the application" behavior of a dialog by assigning the result of Process.Start (a Process) to a variable, then calling the WaitForExit() method on that Process with no parameters. This will block the application's main thread until the user closes the Explorer window you opened. It's not perfect; by blocking the thread, the application will not respond to any requests to draw itself or do any other basic things that even a dialog-interrupted window will still do, and you can still technically "activate" the window you used to launch Windows Explorer which will bring it in front of Windows Explorer. The Explorer window can also be minimized (something dialogs don't normally allow) and there isn't much you can do to prevent that.

Prevent a user from closing an application that is opened through a C# program

I have a old command line based program (its fortran if that matters) that is opened from a C# application when a user clicks a button. If the command line program is shut down while it is running data becomes corrupted. Is there any way to prevent people shutting it down while it is running? Like make the [x] not be available or somehow embed the program into mine?
System.Diagnostics.Process pname =
System.Diagnostics.Process.Start(Path.Combine(Application.StartUpPath,
"diag_main.exe"));
pname.Exited += new EventHandler(pname_Exited);
Note: I want to still be able to see the application running and it closes on its own when it is finished, I just can't have people killing it while it is in the process of running.
A solution that will take a decent amount of programming but can be done:
Write a separate program that intercepts the screen output of the program and sends it to your program somehow. Run this program in the hidden window, it turns around and runs the app and sends the output to your program.
At least parts of the interceptor are almost certainly going to have to be in assembly.
Edit: Redirecting stdout won't do it even if the program only writes to it--he wants the output displayed.
There are three things that might need to be intercepted:
Int 21h filesystem writes. These are the things that could be intercepted by redirecting stdout. Beware that some programs may write to a different handle number that actually represents the stdout file--look up the handle that's being written to in the program's handle table and compare it to the stdout entry (IIRC the second entry)--if they match it's actually screen output.
The second level is IIRC int 10h. There are several sub-calls that must be intercepted.
Finally, a program may do direct screen writes. Intercepting these would be a major pain, I wouldn't even consider trying it (you would have to basically rewrite the dos box.) Instead, frequently compare the screen memory with a saved copy looking for changes.
In all three cases at least parts of the routine are going to have to be written in assembly.
I have done the first, played a bit with the second but then I found that I could get by without doing it. I've never attempted the third.
Unfortunately, no. If the other program has a UI, then you can't hide it from the user. If it doesn't, then you can launch it without presenting a console window by using the ProcessStartInfo class. Even if you do that, though, they could still kill it using the task manager.
I don't know if this will apply to your app, but you can start the process with a hidden window - this would mean that the application is hidden and cannot be stopped via the UI.
When constructing your process object, use a constructor overload that takes a ProcessStartInfo object. Set the WindowStyle property of this to ProcessWindowStyle.Hidden and the CreateNoWindow property to true:
ProcessStartInfo startInfo = new ProcessStartInfo("fortranApp.exe");
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.CreateNoWindow = true;
Process.Start(startInfo);
Of course, it will still appear in the process list and can be killed that way, but at least this will prevent any unintentional shutdown.
You can try to use ProcessStartInfo and set the property CreateNoWindow to true and set WindowStyle to ProcessWindowStyle.Hidden. I haven't tried it myself but maybe you are lucky.
If the program is loading in a cmd window, then no, there's no way to prevent the user from just closing the window. A better approach would be to launch the program in the background, where it's hidden from casual users. A malicious user could still find the process and kill it, but that's likely to be less of a problem.
You can do this with the following:
var psi = new ProcessStartInfo();
psi.CreateNoWindow = true;
/// etc.

Categories