Link to home
Start Free TrialLog in
Avatar of naga1979
naga1979

asked on

Write In Console

Dear Experts

I developed a application which will run continuously. Each and every status of the application will be logged in a log file. I developed my application in such a way that it hides in the task bar when it is minimized. What i want to do is to write each and every status of the application in the dos console. So that the status can be viewed in the console. I am able to write the status in the dos console with the following APIs

Private Declare Function AllocConsole Lib "kernel32" () As Long
Private Declare Function FreeConsole Lib "kernel32" () As Long
Private Declare Function GetStdHandle Lib "kernel32" (ByVal nStdHandle As Long) As Long
Private Declare Function WriteConsole Lib "kernel32" Alias "WriteConsoleA" (ByVal hConsoleOutput As Long, ByVal lpBuffer As Any, ByVal nNumberOfCharsToWrite As Long, lpNumberOfCharsWritten As Long, lpReserved As Any) As Long


The problem here is when the user closes the console using the window close button it is throwing some memory error and terminates the actual application itself. Its not throwing any error if we use FreeConsole API to close the console. How to avoid this error. Can we avoid the user closing the console. How to avoid the memory error.

Cheers!
Avatar of abel
abel
Flag of Netherlands image

I don't know why you get the memory error, I need to see more of the code to understand why that happens. But instead of trying to solve the memory error, it's probably much easier to make it impossible to close the window.

You can do that by using SetClassLong, but the window must be in your process space, and I don't know if that is the case. If it is, use it before you create the window, because if you change classes, windows created with that class do not change, only newly created windows do. (note that "class" here has nothing to do with the notion of class most vb-users have).
If you can use it, you should call it with
GCL_STYLE constant and modify the CS_NOCLOSE bit. In pseudocode:

lStyle = GetClassLong(hwnd, GCL_STYLE)
lStyle = lStyle And (Not GCL_STYLE)
SetClassLong(hwnd, GCL_STYLE, lStyle)
CreateWindow(withNewClass)

Hope this helps a bit,
Abel
Avatar of naga1979
naga1979

ASKER

Dera abel

Here is my code

Private Declare Function AllocConsole Lib "kernel32" () As Long
Private Declare Function FreeConsole Lib "kernel32" () As Long
Private Declare Function GetStdHandle Lib "kernel32" (ByVal nStdHandle As Long) As Long
Private Const STD_INPUT_HANDLE = -10&
Private Const STD_OUTPUT_HANDLE = -11&
Private Const STD_ERROR_HANDLE = -12&

Private Declare Function WriteConsole Lib "kernel32" Alias "WriteConsoleA" (ByVal hConsoleOutput As Long, ByVal lpBuffer As Any, ByVal nNumberOfCharsToWrite As Long, lpNumberOfCharsWritten As Long, lpReserved As Any) As Long

Private Declare Function SetConsoleTitle Lib "kernel32" Alias "SetConsoleTitleA" (ByVal lpConsoleTitle As String) As Long

Private Declare Function SetConsoleActiveScreenBuffer Lib "kernel32" (ByVal hConsoleOutput As Long) As Long



Private Sub Command1_Click()
FreeConsole
End Sub

Private Sub Form_Load()
Dim z As String

AllocConsole
x = GetStdHandle(STD_OUTPUT_HANDLE)
z = "Hai how are you " + vbCrLf
SetConsoleTitle ("Hello World")

For i = 0 To 50
    WriteConsole x, z, Len(z), vbNull, vbNull
Next
End Sub

In this i get error if try to close the console directly.

Cheers!
Hi naga,

The method I suggested is not usable in this situation. I'm sorry for that, but that's how it is. My search for any other solution appeared to be fruitless and I was about to give up (enough melodrama?) when I finally saw the light!

Here's what the problem is: a console window is not subclassable, end of story. You cannot change its properties, you cannot change its class or the properties of its class. What you CAN do is sending messages to it, like a WM_CLOSE, but that's not going to help us here. In addition, Microsoft does not issue any message when it creates or destroys the window. It does not have a parent window and it does not belong to your application. It runs in its own thread and that's yet another reason why you can do so little with it. As it turns out, consoles have a special place when it comes to windows, and that's all probably due to the fact that it can run full-screen and act as if it were not a window at all. After all, you can run console applications in it, and they differ significantly in design from GUI applications.

But that's not all. In times of Windows 95/98 there were still some possibilities to peek and poke around the memory areas of other processes, including console processes. In Win2k this is not possible at all, unless you design your own device driver to do the tricks.

Just this morning I thought of two possible solutions for you. One is about creating an out of process COM object (EXE) using VB and encapsulate the whole console-story in that object. If the console quits, the object quits, but nobody really cares, right? And that only raises trappable errors, and that's what we were after.

Second is a solution probably way beyond the current scope, but depending on your needs easy to implement: simulate your own console. If it's only about informing the user, you can create a window similar to a console window and use the OEM font to make it look original.

But these two options all faint when I start talking about the one and only solution that is really to your needs (am I overacting?). The cure to all your illnesses: SetConsoleCtrlhandler!

That function does exactly what we need: it creates a handler (some kind of callback function in this case, that you have to provide yourself) that processes close, ctrl-c and ctrl-break messages. And you probably knew that you could also close it not only with the close-button but with ctrl-c/break, and those we are going to catch as well.

This story ends up way beyond moderate level of programming, and not knowing what your level is, I just provide you with the sample code I used while investigating:


'--MODULE
Option Explicit
Public Const CTRL_BREAK_EVENT = 1
Public Const CTRL_C_EVENT = 0
Public Const CTRL_CLOSE_EVENT = 2
Public Const CTRL_LOGOFF_EVENT = 5
Public Const CTRL_SHUTDOWN_EVENT = 6

Public Function HandlerRoutine(ByVal dwCtrlType As Long) As Long        'ByVal is VERY IMPORTANT!!!
    Select Case dwCtrlType
        Case CTRL_C_EVENT, CTRL_BREAK_EVENT
            HandlerRoutine = 1
           
        Case CTRL_CLOSE_EVENT
            HandlerRoutine = 1
            Form1.tmrShutDownDlg.Enabled = True
           
        Case CTRL_LOGOFF_EVENT, CTRL_SHUTDOWN_EVENT
            HandlerRoutine = 0
           
        Case Else
            MsgBox "A control event unknown and undocumented: " & dwCtrlType
            HandlerRoutine = 0
           
    End Select

End Function



'--FORM or whereever
Private Sub Command4_Click()
    Dim z As String, x As Long, i As Long
    Dim retval As Long
   
    AllocConsole
    x = GetStdHandle(STD_OUTPUT_HANDLE)
    z = "Hai how are you " + vbCrLf
    SetConsoleTitle ("Hello World")
   
   
    For i = 0 To 50
       WriteConsole x, z, Len(z), vbNull, vbNull
    Next
   
    retval = SetConsoleCtrlHandler(AddressOf HandlerRoutine, True)        'Return val nonzero: succes!
    If retval = 0 Then
        MsgBox "Problem"
    End If
End Sub

Private Sub Command3_Click()
    FreeConsole
End Sub

Private Sub tmrShutDownDlg_Timer()
    Static count As Long
    Dim hwnd As Long, str As String
       
    str = "You tried to close it!" & vbCrLf
    count = count + 1
    If count > 100 Then         '5 seconds passed!
        tmrShutDownDlg.Enabled = False
        count = 0
    End If
   
    hwnd = FindWindow("#32770", "End Program - Hello World")
    If hwnd <> 0 Then
        SendMessage hwnd, WM_CLOSE, 0, 0
        WriteConsole GetStdHandle(STD_OUTPUT_HANDLE), str, Len(str), 0, 0
        If FindWindow("#32770", "End Program - Hello World") = 0 Then
            tmrShutDownDlg.Enabled = False
        End If
        count = 0           'There may have been more then one click on the close button, start again!
    End If
       
End Sub



I'll explain the code in the next post.
ASKER CERTIFIED SOLUTION
Avatar of abel
abel
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Btw, if you use your code on a system other then Win2k: the handler still works, but the reaction of the OS is probably a little different. Like the classname, I guess it won't be "#32770" on all systems. And the searchtext should be adjusted to the name of the caption of the console window you use in the final incarnation of your application.
Ping ;-)
Just curious: did it help?
Dear Abel

Give me some time, as i am busy with my office work.

Cheers!


Hi naga1979,

acctually this is not my comment about your question posted here,I just want to tell you there are maybe some
points for you from my question 20400164 posted at somewhere shown as below:

https://www.experts-exchange.com/questions/20400164/Philips-SpeechMania-hddl-question-about-transaction-dll-in-c.html

since I found that you mentioned about Philips SpeechMania before by searching.


anyway it will be very appreciated if you can click and view my question mentioned above.

or could you suggest me any experts or links where I can find somebody who can help me?

thanks in advance

xyan00


supplementary description:

I want to display a parameter  which is obtained by hddl from transaction dll,it would be better if the function  

calling for the window that showing the parameter is also invoked in the transaction dll.
Avatar of DanRollins
Hi naga1979,
It appears that you have forgotten this question. I will ask Community Support to close it unless you finalize it within 7 days. I will ask a Community Support Moderator to:

    Accept abel's comment(s) as an answer.

naga1979, if you think your question was not answered at all or if you need help, just post a new comment here; Community Support will help you.  DO NOT accept this comment as an answer.

EXPERTS: If you disagree with that recommendation, please post an explanatory comment.
==========
DanRollins -- EE database cleanup volunteer