Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent Windows Forms application from closing when the Console is closed [duplicate]

Tags:

vb.net

console

I have a standard Windows Forms application and I needed a solution to open the console within the Windows Forms application setting. I came up with this solution:

Public Class Win32

    <DllImport("kernel32.dll")>
    Public Shared Function AllocConsole() As Boolean
    End Function

    <DllImport("kernel32.dll")>
    Public Shared Function FreeConsole() As Boolean
    End Function

' ...

Win32.AllocConsole()
Console.WriteLine("Test")

Using the P/Invoke functions above, I can open a console without my application being a "Console Application".

The problem I am now having is that when I close the console window it exits my program and closes all Forms and Windows. Is there a way to prevent the user from closing the Console window, or to prevent the program from exiting when the console window is closed? (I can close the console programmatically using Win32.FreeConsole().)

like image 287
Tom Avatar asked Feb 01 '14 22:02

Tom


1 Answers

I think you might find this interesting, give it a try; works great for me! Another note: the user can't hit the close button because it's disabled and the only way to get out is how you set it...

 Imports System.Collections.Generic
 Imports System.Windows.Forms
 Imports System.Runtime.InteropServices
 Imports System.Diagnostics
 Imports Microsoft.Win32

 Public Class Form1

 <DllImport("kernel32.dll", SetLastError:=True)> _
Private Shared Function AllocConsole() As Boolean
End Function

<DllImport("kernel32.dll", SetLastError:=True)> _
Private Shared Function FreeConsole() As Boolean
End Function

Private Declare Function DeleteMenu Lib "user32" (ByVal hMenu As Integer, _
 ByVal uPosition As Integer, ByVal uFlags As Integer) As Boolean
Private Declare Function GetForegroundWindow Lib "user32" () As Integer
Private Declare Function GetSystemMenu Lib "user32" (ByVal hWnd As Integer, _
   ByVal bRevert As Boolean) As Integer
Private Declare Function GetWindow Lib "user32" (ByVal hWnd As Integer, _
   ByVal uCmd As Integer) As Integer
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
   (ByVal hWnd As Integer, ByVal lpString As String, ByVal nMaxCount As Integer) As Integer


Private Sub btnStartConsole_Click(sender As Object, e As EventArgs) Handles btnStartConsole.Click
    StartConsole()
End Sub

Private Sub StartConsole()
    AllocConsole()
    Console.Title = "TEST"
    ' Obtain a handle to the console application window by passing the title of your application.
    Dim hWnd As Integer = ObtainWindowHandle("TEST") 'Can change this, but must match the name you give it!'

    ' Obtain a handle to the console application system menu.
    Dim hMenu As Integer = GetSystemMenu(hWnd, False)

    ' Delete the Close menu item from the console application system menu.
    ' This will automatically disable the Close button on the console application title bar.
    DeleteMenu(hMenu, 6, 1024)

    Console.WriteLine("We have a console! Enter something!")
    ' Read value.
    Dim s As String = Console.ReadLine()
    ' Write the value.
    Console.WriteLine("You typed " + s)
    Console.WriteLine("Press any key! ...")
    Console.ReadLine()

    FreeConsole()
End Sub

Private Function ObtainWindowHandle(ByVal lpstrCaption As String) As Integer

    ' To store the handle to a window.
    Dim hWnd As Integer
    ' Maximum number of characters in the GetWindowText method.
    Dim nMaxCount As Integer
    ' Actual number of characters copied in the GetWindowText method.
    Dim nCopiedLength As Integer
    ' To store the text of the title bar of the window.
    Dim lpString As String

    nMaxCount = 255
    ' Obtain a handle to the first window.
    hWnd = GetForegroundWindow

    ' Loop through the various windows until you encounter the console application window, _
    ' or there are no more windows.
    While hWnd <> 0

        ' Fill lpString with spaces.
        lpString = Space(nMaxCount)
        ' Get the text of the title bar of the window in lpString.
        nCopiedLength = GetWindowText(hWnd, lpString, nMaxCount)

        ' Verify that lpString is neither empty, nor NULL.
        If Len(Trim(lpString)) <> 0 And Asc(Trim(lpString)) <> 0 Then
            ' Verify that the title of the retrieved window is the same as the title of the console application window.
            If CType(InStr(Microsoft.VisualBasic.Left(lpString, nCopiedLength), lpstrCaption), Boolean) Then
                ' Return hWnd to the Main method.
                Return hWnd
            End If
        End If

        ' Get the next window.
        hWnd = GetWindow(hWnd, 2)

    End While

    ' If no corresponding windows are found, return 0.
    Return 0

End Function
End Class
like image 151
Trevor Avatar answered Sep 21 '22 03:09

Trevor