|
Hi,
For some reason I have been seeing this question alot... and the adequate responses. Although it is correct that console applications initially do not have a message queue... the first time a win32k.sys/GDI syscall greater or equal to 0x1000 is invoked... the windows kernel increases the thread stack-size and invokes KiConvertToGuiThread which will convert the console thread into a GUI thread with a message queue.
How do you 'invoke a system call above 0x1000' ?
WIN32K.SYS System Call Table[^]
As you can see in that table... the first GDI system call NtGdiAbortDoc is at index 0x1000. Because we know that the GetMessage function[^] results in a call to NtUserGetMessage and the DispatchMessage function[^] results in a call to NtUserDispatchMessage. We can infer that by simply creating a message loop... we will have in-fact promoted the thread into a GUI thread.
In other words... by simply attempting to pump the message queue... the thread is given one.
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
So what do you have now? Now you have a console process with a thread containing a message queue that has no window HANDLE so cannot recieve window messages. Is this the end of the road?
No, window messages are not the only type of message. You can still use the PostThreadMessage function[^] to post thread messages to the console.
Step 1: Create two console applications... Sender and Reciever.
Step 2: In the reciever begin an infinite message pump (console thread will be promoted to gui thread by the subsystem)
Step 3: In the sender call CreateProcess with the CREATE_NEW_CONSOLE flag that creates the reciever process. (otherwise messages will appear in senders console!)
Step 4: Using the PROCESS_INFORMATION.dwThreadId begin posting messages with PostThreadMessage to reciever from sender.
Best Wishes,
-David Delaune
|
|
|
|
|
Nice.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
How do you create/register the message handler func?
==============================
Nothing to say.
|
|
|
|
|
Hi,
What message handler function are you referring to? The GetMessage function[^] is exported from the user32 library.
Best Wishes,
-David Delaune
|
|
|
|
|
#include <windows.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "user32")
int main(int argc, char *argv[], char *envp[])
{
DWORD idThread;
MSG Msg;
if (argc == 2)
{
idThread = atoi(argv[1]);
if (!PostThreadMessage(idThread, WM_COMMAND, (WPARAM)0, (LPARAM)0))
cout << GetLastError() << " PostThreadMessage error\n";
return 0;
}
cout << GetCurrentThreadId() << " thread id\n";
while (GetMessage(&Msg, NULL, 0, WM_USER))
{
if (Msg.message == WM_COMMAND)
cout << "WM_COMMAND\n";
else
cout << "Message: " << Msg.message << endl;
}
return 0;
}
|
|
|
|
|
|
If you have access to the console app source code, and you go to the trouble of adding the message pump, you may as well add code to create a message-only window, no?
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Hi Richard,
Richard Andrew x64 wrote: you may as well add code to create a message-only window, no?
It doesn't really matter to me how you decide to implement IPC between console applications. As Rajesh suggested you could use sockets, pipes or as Carlo Pallini suggested you could use STDIN/STDOUT/STDERR or as you suggested a hidden window or the option I have suggested; PostThreadMessage. It is great to have so many options put on the table.
Best Wishes,
-David Delaune
|
|
|
|
|
Yep, definitely not impossible (people get too used to the framework doing magic)... I think it's just a bit of a hassle more than anything else. Good job pointing this out!
|
|
|
|
|
It is not possible but you can cheat. Reverse engineer it.
Create a Windows app (win32 or MFC) and redirect messages to a console window.
But once you add a window, your app will no longer be a console app.
So it is still not possible.
See [this].
More reversed console apps [here] and [here].
|
|
|
|
|
Here is another example, to go along with Carlos'.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
|
|
|
|
|
Hi,
I have gotten arount Most of the security challenges around the New Windows Model.
One issue remains a challenge. I created a derrived MFC Control: 'CMultiColumListBox', derived from MFC-'CListBox'. It in turn, is used as a Baseclass for various data tabulations. it all works to perfection under Win 95/98. Win NT, and Windows XP. With Vista and Windows 7, the Header Button listtakes up about 80% of the width of the CListbox Window, the Text Colums take up even Less.
One part of the creation process sets up the display Geometry parameters. I must have missed a Translation Somewhere.
The Salient part of the control that does this is as follows:-
BOOL CMultiColumListBox::RegisterControl(CDialog * pDialog)
{
if(!m_bDrawButtons)return TRUE;
ASSERT(pDialog->IsKindOf( RUNTIME_CLASS(CWnd) ) );
ASSERT(::IsWindow(pDialog->m_hWnd));
CDC* pDC=pDialog->GetDC();
ASSERT(pDC);
m_pParentDialog=pDialog;
CRect CtrlRect,DlgWndRect,DlgClientRect,BnRect;
GetWindowRect(&CtrlRect); pDialog->GetWindowRect(&DlgWndRect);
pDialog->GetClientRect(&DlgClientRect);
int BorderWidth=DlgWndRect.Width() - DlgClientRect.Width();
int TitleBarHeight=DlgWndRect.Height() -
DlgClientRect.Height()-BorderWidth;
BorderWidth/=2;
int Base_x,Base_y,BaseWidth;
Base_x=CtrlRect.left-1;
Base_y=CtrlRect.top;
BaseWidth=CtrlRect.Width();
for(int i=0;i<m_nNrOfColumns;i++){
CWnd* pWnd=pDialog->GetDlgItem(m_nColumList[i].n_ID);
ASSERT(pWnd);
pWnd->ShowWindow(SW_NORMAL);
int Width=m_nColumList[i].width;
if(i==m_nNrOfColumns-1)Width=BaseWidth;
if(Width>BaseWidth)Width=BaseWidth;
BnRect.left=Base_x-DlgWndRect.left-BorderWidth;
BnRect.right=Base_x+Width-DlgWndRect.left-BorderWidth;
BnRect.top=Base_y-m_nItemHeight*2-TitleBarHeight-DlgWndRect.top-1;
BnRect.bottom=Base_y-TitleBarHeight-DlgWndRect.top-1;
pWnd->MoveWindow(&BnRect); Base_x+=Width;
BaseWidth-=Width;
char* p=m_nColumList[i].lpcstrColumHeader;
if(p)pWnd->SetWindowText(p);
}
return TRUE;
}
This function would Typicaly be called from OnInitDialog()from the Dlg that contains it. It sets the Parameters for subsequent Drawing and Painting.
Any Idea about DlgToScreen() ScreenToDlg(),etc tha should have been used here
Bram van Kampen
|
|
|
|
|
i have a character arry in C
hello hi soidjosdc
kcopsdkcpok cjsdp
dskcoksdpc ocsdkcpd
i want to read it line by line and store it in another array....please help
|
|
|
|
|
please give any suggestions
|
|
|
|
|
Okay, I'll byte..
In essence, you have a string that you have to cut up into smaller pieces.
The cut-points are clearly defined - the string is to be cut at the end of each line of text.
So, we need
1) knowledge of the number of lines
2) memory to hold each of the lines
3) to copy each of the lines to the memory allocated in step 2.
Sooo, you'll need to know what your line-ending character(or sequence) is. You'll need to count the number of instances of the of line terminators, and for ease and simplicity, add 1 to this number - this is the number of lines you have - mLineCount.
You can then create an array of mLineCount elements of char*
You can then copy each line, storing the address of the new text into the appropriate array element.
Two functions you'll likely make use of are strdup and strtok. I advise you read the documentation for these two functions carefully, there are a few gotchas or things to watch for with strtok - Particularly, the fact that it modifies the input string. This precludes the use of the function on const char* strings.
For example, while the intention below is to split "some text" into two separate strings, it will fail since strtok can't modify myString.
char *myString = "some text", *delims = ",. ";
char *curToken;
curToken = strtok(myString, delims);
|
|
|
|
|
I and others already answered a similar query below. If you still don't understand string parsing then you need to spend a lot of time reading the MSDN documentation and sample code on the functions I recommended to you.
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
You may hand-craft it, for instance:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main()
{
int n, count;
int item, lastindex;
char ** b;
const char a[] = "hello hi soidjosdc\nkcopsdkcpok cjsdp\ndskcoksdpc ocsdkcpd";
const int LEN = sizeof(a);
for (n=0, count = 0; n<LEN; n++)
{
if (a[n] =='\n' || a[n] == '\0')
count++;
}
b = (char **) malloc( count * sizeof(char *));
assert(b);
for (n=0, item=0, lastindex = 0; n<LEN; n++)
{
if (a[n] =='\n' || a[n]=='\0')
{
int k, len;
len = n-lastindex;
b[item] = (char *) malloc(len+1);
assert(b[item]);
for (k=0; k<len;k++)
{
b[item][k] = a[lastindex+k];
}
b[item][k] = '\0';
lastindex = n+1;
item++;
}
}
for (item=0; item<count; item++)
{
printf("%s\n", b[item]);
}
for (item=0; item<count; item++)
{
free(b[item]);
}
free(b);
return 0;
}
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
That's what I'm talkin' about.
I love your cruel avoidance of the simplifying (though functionality hiding) strdup and strtok.
|
|
|
|
|
enhzflep wrote: That's what I'm talkin' about.
In fact I just spoon-fed the OP with your method.
enhzflep wrote: I love your cruel avoidance of the simplifying (though functionality hiding) strdup and strtok.
Yes, that's my own departure: why should we use a function when we've the 'metal'?
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
I want to run a do loop, for cosmetic purposes while WaitForSingleObjectEx is monitoring the ShellExecuteEx Thread.
I'm looking for something to grab onto, for the while statement to monitor, and then release to close the handle.
The hProcess !- NULL, is not working well, or I'm calling the code in the wrong order or something.
exit_Code = ShellExecuteEx(&lpExecInfo);
if (lpExecInfo.hProcess != NULL) {
DWORD iWait = WaitForSingleObjectEx(lpExecInfo.hProcess, INFINITE, TRUE);
int ndx = 0;
do {
ndx++;
} while ( lpExecInfo.hProcess !=NULL );*/
CloseHandle(lpExecInfo.hProcess);
|
|
|
|
|
Your loop is unnecessary. The call to WaitForSingleObjectEx() is going to block unitl the process you are monitoring is complete.
Chris Meech
I am Canadian. [heard in a local bar]
In theory there is no difference between theory and practice. In practice there is. [Yogi Berra]
posting about Crystal Reports here is like discussing gay marriage on a catholic church’s website.[Nishant Sivakumar]
|
|
|
|
|
Your right about that. It's one or the other.
|
|
|
|
|
Hi,
As Chris pointed out... by the time your do-while loop has started the processes will have ended. I would also recommend that you use CreateProcess rather than ShellExecute.
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi));
si.cb = sizeof(si);
if(CreateProcess(lpApplicationpath,lpCommandline, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE|NORMAL_PRIORITY_CLASS, 0, lpCurrentdirectory, &si, &pi))
{
int index = 0;
do
{
++index;
} while (WAIT_OBJECT_0 = WaitForSingleObject(pi.hProcess,10););
}
Best Wishes,
-David Delaune
|
|
|
|
|
The program takes 30 minutes to run, I'll give create process a whirl
|
|
|
|
|
Here's what I use
int CWelcomeWizardDlg::RunAppAndWait(char *cmd)
{
PROCESS_INFORMATION ProcInfo;
STARTUPINFO StartInfo;
int exit_status = 0;
memset(&StartInfo, 0, sizeof(StartInfo));
StartInfo.cb = sizeof(StartInfo);
if (CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &StartInfo, &ProcInfo))
{
WaitForSingleObject(ProcInfo.hProcess, INFINITE);
GetExitCodeProcess(ProcInfo.hProcess, (unsigned long *)&exit_status);
CloseHandle(ProcInfo.hProcess);
CloseHandle(ProcInfo.hThread);
return exit_status;
}
return 1;
}
|
|
|
|
|