6

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().)

JDB
  • 25,172
  • 5
  • 72
  • 123
Tom
  • 640
  • 1
  • 7
  • 25
  • I've tried to clarify your question. If I've gotten it wrong, you can open up the [revision history](http://stackoverflow.com/posts/21504253/revisions) and rollback to the previous version. – JDB Feb 01 '14 at 22:33
  • 2
    I have tried that answer however it is not working for me! – Tom Feb 01 '14 at 22:54
  • the problem and possible answers are covered pretty much in depth in that question/answers. Look at the other answers for possible solutions. – Mark Hall Feb 01 '14 at 23:10
  • 3
    There's nothing to "try" in those answers. They all say the same thing: you cannot stop this. Don't create a console if you can't afford this to happen. – Hans Passant Feb 01 '14 at 23:24
  • @HansPassant I would like to say WRONG, you can stop this, I did and works great! – Trevor Feb 02 '14 at 01:50

1 Answers1

1

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
Trevor
  • 7,777
  • 6
  • 31
  • 50
  • This is also tried and TESTED! Let me know how it works out for you! – Trevor Feb 02 '14 at 01:19
  • His main concern is if someone closes the console by clicking the close button, it **will** kill the application. – Mark Hall Feb 02 '14 at 01:28
  • @MarkHall There, no problem now, I've done this before had to go through and find it. It disables the menu close, but maximize and minimize functions are still available... Give it a try and see... – Trevor Feb 02 '14 at 01:49
  • @Mr CoDeXeR Yes your code is a solution to the problem however it is technically not a true answer to the question because your stopping the close button from showing but not stating how to stop the form closing when the close button is pressed but your answer does not allow a close button to be pressed – Tom Feb 03 '14 at 21:36
  • Ok, let me remind you what you have asked.... "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?" This is what you asked and I delivered you a solution. If you don't stop the dang close button then they can exit! – Trevor Feb 03 '14 at 22:33
  • @Çöđěxěŕ It work for me!!! Nice solution, I have voted UP. – GGSoft Jan 11 '19 at 11:21
  • @Çöđěxěŕ It will be interesting, how to enable close button again? Please provide code, if possible!!! – GGSoft Jan 11 '19 at 12:27
  • @GGSoft well, what have you tried to do? – Trevor Jan 11 '19 at 13:23
  • @Çöđěxěŕ I want to re-enable close button again. How I can achieve this? What flags I must specify? Thanks!!! – GGSoft Jan 11 '19 at 14:12