Embedding a Dos Console in a Windows Form

Embedding a DOS console in a windows form

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.

Embedding a DOS console in a windows form with Visual Basic

Using bring a console window to front in c# as a basis, you can modify your code:

<DllImport("user32.dll", EntryPoint:="FindWindow", SetLastError:=True)> _
Private Shared Function FindWindowByCaption(ByVal zeroOnly As IntPtr, ByVal lpWindowName As String) As IntPtr
End Function

''in frmLoad:
hwnd = FindWindowByCaption(IntPtr.Zero, "c:\WINDOWS\system32\cmd.exe")

As Jon Skeet said:

It's hacky, it's horrible, but it works for me (thanks, pinvoke.net!):

And Cody Gray is also correct with this:

You probably can't manage to find it because it won't always have this title: C:\\WINDOWS\\system32\\cmd.exe. Mine doesn't, for example.

So it works, but is flaky.

How to embed a Console in a Windows Form application?

You could use not one but two Textboxes for your purpose. tbOutput and tbInput. tbOutput would be Multiline and ReadOnly whereas tbInput would be single line, not readonly and placed beneath tbOutput. Then to process inputs you could do something like:

Private Sub Output(s As String)
If s <> "" Then
tbOutput.AppendText(vbCrLf & ">> " & s)
End If
End Sub
Private Sub tbInput_KeyDown(sender As Object, e As KeyEventArgs) Handles tbInput.KeyDown
If e.KeyCode = Keys.Enter Then
If tbInput.Text <> "" Then
Output(tbInput.Text)
' Handle input value
tbInput.Text = ""
End If
End If
End Sub

At the 'Handle input value you would check the user input and handle it according to your needs. Use Lucida Console font in bold in gray and black background for style :-)

How to embed a external CLI window into a Panel in Windows Forms?

I just wrote a simple helper class in VB.NET that will serve me to set and release a parent window with ease.

It seems to work as expected at least as far as I have tested it in my required scenarios.

Thanks to @Jimi, @RbMm and @Remy Lebeau for their help and their tips that I need to know in order to figure how to do this.

However, what I share here is not functional due to missing types, but you could get the idea. Sorry but it would require to exceed the maximum character limit of this post, and maybe it's too much effort of copy & paste and adapt things to show them here if I'm the only one interested to accomplish this task...

But if you want to figure how to make this class functional then simply add the missing P/Invoke members of which I use in the missing NativeMethods class definition, and replace the missing WindowInfo type for a call to GetWindowInfo (and the WINDOWINFO struct) or else GetClientRect + GetWindowLongPtr functions, and replace missing SafeWindowHandle type for IntPtr or for a custom class derived from SafeHandleZeroOrMinusOneIsInvalid.

Usage Example:

Dim process As Process = Process.GetProcessesByName("name").Single()
Dim windowParenting As New WindowParenting(process.MainWindowHandle)

windowParenting.SetParent(Me.Panel1,
fitToParentBounds:=True,
removeBorder:=True,
removeCaption:=True,
resizable:=False)

Thread.Sleep(5000)
windowParenting.ReleaseParent(throwOnInvalidSourceWindowHandle:=True)

' Or...
' windowParenting.Dispose() ' It calls ReleaseParent.

WindowParenting Class:

''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Implements a mechanism to set and release the parent window for a specific source window.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
Public Class WindowParenting : Implements IDisposable

#Region " Properties"

''' <summary>
''' A safe handle to the source window.
''' </summary>
Public ReadOnly Property WindowHandle As SafeWindowHandle

''' <summary>
''' Gets a <see cref="DevCase.Core.IPC.WindowInfo"/> object for the source window.
''' </summary>
Public ReadOnly Property WindowInfo As WindowInfo
Get
Return Me.GetWindowInfo()
End Get
End Property

''' <summary>
''' Gets a value that determine whether the source window has a parent window.
''' </summary>
Public ReadOnly Property HasParent As Boolean
Get
Try
Return Me.WindowInfo.ParentWindow IsNot Nothing
Catch ex As Exception
Return False
End Try
End Get
End Property

#End Region

#Region " Private Fields"

''' <summary>
''' Keeps track of the current source window bounds when making a call to <see cref="WindowParenting.SetParent"/> method.
''' </summary>
Private lastBounds As Rectangle = Rectangle.Empty

''' <summary>
''' Keeps track of the current source <see cref="WindowStyles"/> when making a call to <see cref="WindowParenting.SetParent"/> method.
''' </summary>
Private lastWindowStyle As WindowStyles = WindowStyles.None

#End Region

#Region " Constructors "

''' <summary>
''' Initializes a new instance of the <see cref="WindowParenting"/> class.
''' </summary>
''' <param name="hwnd">
''' A handle to the source window.
''' </param>
<DebuggerStepThrough>
Public Sub New(hwnd As IntPtr)
Me.New(New SafeWindowHandle(hwnd))
End Sub

''' <summary>
''' Initializes a new instance of the <see cref="WindowParenting"/> class.
''' </summary>
''' <param name="hwnd">
''' A handle to the source window.
''' </param>
<DebuggerStepThrough>
Public Sub New(hwnd As SafeHandle)
Me.WindowHandle = hwnd

If Me.WindowHandle.IsInvalid Then
Throw New Exception("Invalid window handle.")
End If
End Sub

''' <summary>
''' Initializes a new instance of the <see cref="WindowParenting"/> class.
''' </summary>
''' <param name="window">
''' AThe source window.
''' </param>
<DebuggerStepThrough>
Public Sub New(window As NativeWindow)
Me.New(New SafeWindowHandle(window.Handle))
End Sub

''' <summary>
''' Initializes a new instance of the <see cref="WindowParenting"/> class.
''' </summary>
''' <param name="window">
''' The source window.
''' </param>
<DebuggerStepThrough>
Public Sub New(window As IWin32Window)
Me.New(New SafeWindowHandle(window.Handle))
End Sub

#End Region

#Region " Public Methods "

''' <summary>
''' Sets a new parent window for the source window.
''' </summary>
''' <param name="parentWindow">
''' The parent window.
''' </param>
'''
''' <param name="fitToParentBounds">
''' If set to <see langword="True"/>, fits to size of the source window to the parent window bounds.
''' </param>
'''
''' <param name="removeBorder">
''' If set to <see langword="True"/>, removes the border from the source window.
''' </param>
'''
''' <param name="removeCaption">
''' If set to <see langword="True"/>, removes the caption from the source window.
''' </param>
'''
''' <param name="resizable">
''' If set to <see langword="False"/>, remove sthe size frame from the source window.
''' </param>
''' <exception cref="InvalidOperationException">
''' Source window already has a parent window.
''' </exception>
<DebuggerStepThrough>
Public Overridable Sub SetParent(parentWindow As IWin32Window, fitToParentBounds As Boolean,
removeBorder As Boolean, removeCaption As Boolean,
resizable As Boolean)

Dim curentWindowInfo As WindowInfo = Me.GetWindowInfo()
If Me.lastBounds = Rectangle.Empty Then
Me.lastBounds = curentWindowInfo.Bounds
End If
If Me.lastWindowStyle = WindowStyles.None Then
Me.lastWindowStyle = curentWindowInfo.WindowStyle
End If

Dim newStyle As WindowStyles = (Me.lastWindowStyle And Not WindowStyles.SysMenu)
If removeBorder Then
newStyle = (newStyle And Not WindowStyles.Border)
End If
If removeCaption Then
newStyle = (newStyle And Not WindowStyles.Caption)
End If
If Not resizable Then
newStyle = (newStyle And Not WindowStyles.SizeFrame)
End If

Dim parentWindowHandle As New SafeWindowHandle(parentWindow.Handle)

NativeMethods.SetParent(Me.WindowHandle, parentWindowHandle)
Me.SetSourceWindowStyle(newStyle)

Dim parentClientRect As Rectangle
If fitToParentBounds Then
NativeMethods.GetClientRect(parentWindowHandle, parentClientRect)
End If
NativeMethods.SetWindowPos(Me.WindowHandle, IntPtr.Zero, 0, 0,
If(fitToParentBounds, parentClientRect.Width, 0),
If(fitToParentBounds, parentClientRect.Height, 0),
SetWindowPosFlags.AsyncWindowPos Or
SetWindowPosFlags.ShowWindow Or
If(fitToParentBounds, SetWindowPosFlags.None, SetWindowPosFlags.IgnoreResize))

End Sub

Public Overridable Sub SetParent(parentWindow As NativeWindow, fitToParentBounds As Boolean,
removeBorder As Boolean, removeCaption As Boolean,
resizable As Boolean)

Me.SetParent(DirectCast(parentWindow, IWin32Window), fitToParentBounds, removeBorder, removeCaption, resizable)

End Sub

Public Overridable Sub SetParent(parentWindow As Control, fitToParentBounds As Boolean,
removeBorder As Boolean, removeCaption As Boolean,
resizable As Boolean)

Me.SetParent(DirectCast(parentWindow, IWin32Window), fitToParentBounds, removeBorder, removeCaption, resizable)

End Sub

''' <summary>
''' Release the source window from its current parent window.
''' </summary>
''' <param name="throwOnInvalidSourceWindowHandle">
''' If set to <see langword="True"/>, throws an <see cref="NullReferenceException"/>
''' if the source window handle specified in <see cref="WindowParenting.WindowHandle"/> is invalid.
''' <para></para>
''' This can be useful if you need to detect whether the source window has been destroyed.
''' </param>
<DebuggerStepThrough>
Public Overridable Sub ReleaseParent(Optional throwOnInvalidSourceWindowHandle As Boolean = False)

Dim isInvalid As Boolean = Me.WindowHandle.IsInvalid OrElse
Me.WindowHandle.IsClosed OrElse
Not NativeMethods.IsWindow(Me.WindowHandle)

If isInvalid AndAlso throwOnInvalidSourceWindowHandle Then
Throw New NullReferenceException("Invalid source window handle.")

ElseIf Not isInvalid Then
If Not Me.HasParent Then
Throw New InvalidOperationException("Source window has not a parent window.")
End If

NativeMethods.SetParent(Me.WindowHandle, IntPtr.Zero)

If Me.lastWindowStyle <> WindowStyles.None Then
Me.SetSourceWindowStyle(Me.lastWindowStyle)
Me.lastWindowStyle = WindowStyles.None
End If

If Me.lastBounds <> Rectangle.Empty Then
NativeMethods.SetWindowPos(Me.WindowHandle, IntPtr.Zero,
Me.lastBounds.X, Me.lastBounds.Y,
Me.lastBounds.Width, Me.lastBounds.Height,
SetWindowPosFlags.AsyncWindowPos)
Me.lastBounds = Rectangle.Empty
End If

End If

End Sub

#End Region

#Region " Private Methods "

''' <summary>
''' Returns a <see cref="DevCase.Core.IPC.WindowInfo"/> object for the source window.
''' </summary>
<DebuggerStepThrough>
Private Function GetWindowInfo() As WindowInfo
Return New WindowInfo(Me.WindowHandle)
End Function

''' <summary>
''' Sets the <see cref="WindowStyles"/> for the source window.
''' </summary>
<DebuggerStepThrough>
Private Sub SetSourceWindowStyle(style As WindowStyles)

If Environment.Is64BitProcess Then
NativeMethods.SetWindowLongPtr(Me.WindowHandle, WindowLongValues.WindowStyle, style)
Else
NativeMethods.SetWindowLong(Me.WindowHandle, WindowLongValues.WindowStyle, style)
End If

End Sub

#End Region

#Region " IDisposable Implementation "

''' <summary>
''' Flag to detect redundant calls.
''' </summary>
Private disposedValue As Boolean

''' <summary>
''' Releases all the resources used by this instance.
''' </summary>
''' <param name="disposing">
''' <see langword="True"/> to release both managed and unmanaged resources;
''' <see langword="False"/> to release only unmanaged resources.
''' </param>
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue AndAlso disposing Then
Try
Me.ReleaseParent()
Catch ex As Exception
End Try
Me.WindowHandle?.Close()
End If
Me.disposedValue = True
End Sub

''' <summary>
''' Releases all the resources used by this instance.
''' </summary>
Public Sub Dispose() Implements IDisposable.Dispose
Me.Dispose(True)
End Sub

#End Region

End Class

It lacks a bit of win32 error-handling for P/invokes. And maybe other things could be improved.

How to use Console.WriteLine() in windows Forms Application

Console.WriteLine command is working only in console application type. so using windows app doesn't display required output,seems your application is windows form application.

if you want show output on Console window using Console.WriteLine withing the windows form application need to add this property and call it from the main form constructor.then it will open with console as well.

     public InsertNames()
{
AllocConsole();
InitializeComponent();
}

[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AllocConsole();

OR

In project settings you can set application type as Console. Then you will get console and form as well.

Embed a Console Window inside a WPF Window

You should be able to use the same technique as the Windows Forms application you showed by reparenting into an HwndHost. You could even just adapt the Windows Forms code, and put this directly into WindowsFormsHost control.

How do I show a console output/window in a forms application?

this one should work.

using System.Runtime.InteropServices;

private void Form1_Load(object sender, EventArgs e)
{
AllocConsole();
}

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AllocConsole();


Related Topics



Leave a reply



Submit