Is it possible to embed a DOS console in a Windows Form or User Control in C# 2.0?
We have a legacy DOS product that my Windows app has to interact with, and it's been requested that an instance of the legacy product should run within the Windows application.
At the moment, I'm using the user32.dll to locate the window that the DOS product is running in, minimising then maximising the window, and typing characters into the window. This isn't a very good solution to the problem, as it means my application has to store the window name in application settings, and requires that the user returns to the correct page of the DOS app before using the interaction function.
EDIT: Some more information
The legacy app needs to be visible to the user, but not in a separate window.
I've tried TimothyP's answer and it works very well, but is it possible to achieve the same functionality, but with the DOS window visually embedded in a windows form or user control instead of popping up in it's own window? Preferably in a ShowDialog() way so that the user cannot interact with the app wile they are in 'Legacy Mode', so to speak.
It's possible to redirect the standard input/output of console/dos applications using the Process class. It might look something like this:
var processStartInfo = new ProcessStartInfo("someoldapp.exe", "-p someparameters");
processStartInfo.UseShellExecute = false;
processStartInfo.ErrorDialog = false;
processStartInfo.RedirectStandardError = true;
processStartInfo.RedirectStandardInput = true;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.CreateNoWindow = true;
Process process = new Process();
process.StartInfo = processStartInfo;
bool processStarted = process.Start();
StreamWriter inputWriter = process.StandardInput;
StreamReader outputReader = process.StandardOutput;
StreamReader errorReader = process.StandardError;
process.WaitForExit();
You can now use the streams to interact with the application.
By setting processStartInfo.CreateNoWindow to true the original application will be hidden.
I hope this helps.
Concerning your question on how to display the DOS app inside the Windows app.
There are a few solutions.
The first one is to simply not display the DOS app (with CreateNoWindow)
and "simulate" the UI of the DOS app in your Windows application by reading and writing to the streams.
The other solution would be to use the Win32API, get the Windows Handle (Whnd) of the Console/DOS application window and set its parent to your form. I'm currently not at home
and since it has been ages since I've done this, I can't remember by heart how it is done. If I'm not mistaken you'll need to use the following Win32 API calls:
FindWindow
GetWindow
SetParent
If I have some time left later today, I'll see if I can find better samples.
You can use the CreateProcess function and the hStdInput, Output, and Error members of the STARTUPINFO argument, this will allow you to intercept standard input and output of the application.
Related
I have a custom application running as a the shell (Windows 10 Enterprise) for a particular user - i.e. the user boots straight into this application.
However, I want to be able to provide access to the WiFi settings form. I have read that the way to do this is something like
Process.Start("ms-settings:network-wifi");
or
Process.Start("ms-availablenetworks:");
However, as far as I can tell, that relies on explorer running as the shell.
I've tried...
Process proc = new Process();
proc.StartInfo.FileName = #"c:\windows\explorer.exe";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.Arguments = "ms-availablenetworks:";
proc.Start();
All of the above work fine if I run in a normal environment, i.e. with explorer as the shell.
But for this user (with my custom shell application), I get an instance of explorer.exe running and displaying an error, Class not registered
I have also come across using LaunchUriAsync() but I don't think that would help me here, besides it's only available for Windows Store applications for what I've read, which this is not.
Well I managed to get this working
First start explorer on its own, then a second Process.Start() to run the settings page.
Unfortunately, when explorer.exe runs, it displays the taskbar which I don't want. (I had previously assumed I'd be able to hide it with a group policy setting or something but this doesn't appear to be the case).
But I suppose that's another question...
I need to launch or run an windows exe file from a OEM in Win store App.
can below be used? I try but have error but why since diagnostic is in the framework
using System.Diagnostics;
Process myProcess = new Process();
try
{
myProcess.StartInfo.UseShellExecute = false;
// here I point to the OEM windows exe file
myProcess.StartInfo.FileName = "C:\\HelloWorld.exe";
myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
-- Update
# Michal :
Thank you. This method works using URI.
One problem :
the WinRT app goes into background after launching. How to make the winRT app not going background?
Is there any other way? I need to integrate the Exe from the OEM into Win Store App.
Note:
I want to know is this can be done or I am doing something which is not allowed?
If I didnot make my case clearer, please tell me what I miss.
I tried it but it did not work. So my solution should be using similar approach like Diagnostic but what it can be?
Recycling bits from https://social.msdn.microsoft.com/Forums/windowsapps/en-US/0a822355-909f-44b4-9c79-cb986087fe27/after-launching-or-activate-an-app-the-main-app-goes-into-background?forum=winappswithcsharp
This is expected behavior and there's no good way around it. Launching a file or protocol switches to the default handler with no expectation of return.
Launching an app via protocol like this a hack in the first place. Since you are a side-loaded app look into writing a Brokered Windows Runtime Component to allow proper use of desktop API and communication with a desktop back-end.
See the Brokered Windows Runtime Component docs at http://msdn.microsoft.com/en-us/library/windows/apps/dn630195.aspx
I am trying to input console commands on a desktop app (through a text box) click a button, execute the command and get the returned values back for display.
The point is, I want to make my work faster and less stressful when trying to input repetitive commands on the console over and over again everyday.
I know some console application programming on C# and web applications(.NET, ADO.NET) on C# as well, but nothing about desktop applications. Any ideas?
The Process class can be used to start an application, and read it's output (from the standard output or standard error streams).
For example, to start a process, and read it's "output", you could use:
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "Foo.exe";
p.Start();
// Read the output
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
If you make a basic windows forms applications, you could store repetitive commands in a local file and have a mechanism to choose a command from this file in your application and run it. Windows forms shouldn't be too hard for you. it is just drag and drop.
I am attempting to verify the security of an application. The scenario is this:
A C# WinForms application is run by a limited user via Terminal Services (no desktop, just the app). One of the things this C# app can do is execute a batch file that runs a lengthy process with elevated privileges. I am afraid that the limited user may be able to interrupt the batch script (vua Ctrl+C or some other method) and gain access to the underlying elevated shell.
I have tried to do this myself with various combos of Ctrl+C and Ctrl+Break, etc. All I can get is the "Teminate batch job? (Y/N)" prompt, and if you choose terminate, then control is immediately returned to the C# app (which is good). I have not found a way to break this but it seems dangerous to me.
Does anyone know of a way to break out of a C# instantiated batch script and access the underlying shell without returning to the C# app?
No, don't think there is one. But if you're really worried, why not set the CreateNoWindow property on the ProcessStartInfo object you are presumably using to true to prevent user interaction at all?
Not quite an answer to your described scenario but a different way to look at it.
If possible, I would have a "jobs server" who sole responsibility is to run the jobs your Terminal Services-run apps create. Then you would communicate the job (or just it parameters) via WCF to the server. The users would have no access to the server and very little control of the jobs (possibly just a cancel option and success/failure status reports).
You could do something like this (with a Textbox on your app)
ProcessStartInfo info = new ProcessStartInfo();
info.Arguments = "/C ping 127.0.0.1";
info.WindowStyle = ProcessWindowStyle.Hidden;
info.CreateNoWindow = true;
info.FileName = "cmd.exe";
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
using (Process process = Process.Start(info))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
textBox1.Text += result;
}
}
Then you can see the results of the batch without the users being able to actually see the window at all, that way it's only visible as a process so they can't interupt it.
I have a console application which does a set of operations and gives out messages after completion of each operation. When I run my console app, the messages in my console window may look like this:
Checking prerequisites...
Completing prerequisites..
Performing installation...
Completing installation...
Done..!
Now I'm executing this console application from one of my C# windows applications by using Process.StartInfo().
I need to get all the messages thrown by my console application to be displayed in the windows form of my application.
Can this be done?
Thanks.
Look here Capturing console output from a .NET application (C#)
This can be quite easily achieved using the ProcessStartInfo.RedirectStandardOutput Property. A full sample is contained in the linked MSDN documentation.
Process compiler = new Process();
compiler.StartInfo.FileName = "csc.exe";
compiler.StartInfo.Arguments = "/r:System.dll /out:sample.exe stdstr.cs";
compiler.StartInfo.UseShellExecute = false;
compiler.StartInfo.RedirectStandardOutput = true;
compiler.Start();
Console.WriteLine(compiler.StandardOutput.ReadToEnd());
compiler.WaitForExit();