From: dushkin on
Hi All.

Recently I posted a question (http://groups.google.com/group/
microsoft.public.vc.mfc/browse_thread/thread/6ec9bd3dc80c408e#) about
a problem regarding closing an app using a system tray icon menu.

What I didn't know till now is that the problem was a
CAsyncSocket::Accept() function that was waiting for a connection and
probably blocked some messaging or something. Therfore the application
never exited. When I removed the accept function part - the closing of
the app via the system tray menu succeeded.

So I tried to move the listen/accept while loop into a separate
thread. I thought that this way the accept won't interfere in closing
the app. But then, when I tried to stop the "accept" with some closing
functions as you will see in the code, in order to allow the "Exit"
app in the menu to work, the CAsyncSocket::Close() crashed and the
accept didn't stop working anyway.

I read somewhere that you wouldn't like to put this loop in a thread.

My question is how to deal with this problem.

Actually, I think I need to somehow stop the "Accept" operation and
thus allow the system tray messages to work.

How do I do it?

Following is the class code. I removed some of the AboutBox code and
some other irrelevant code. I use a class for the system tray
functionality.

Thanks.

--------------------------------------------------------------------------

// PAADlg.cpp : implementation file
//

#include "stdafx.h"
#include "PAA.h"
#include "PAADlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

bool g_stop = false;
CEvent gEvent;

UINT RunListener(LPVOID lpParam);


// CPAADlg dialog

CPAADlg::CPAADlg(CWnd* pParent /*=NULL*/)
: CDialog(CPAADlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_DefaultMenuItemByPos = TRUE;
m_pParentWnd = pParent;
}

CPAADlg::~CPAADlg(){

g_stop = true;

//Trying to close Accept operation when exiting app
m_ListeningSocket.CancelBlockingCall();
m_ListeningSocket.ShutDown();
m_ListeningSocket.Close();
m_ConnectedSocket.Close();

WaitForSingleObject(gEvent.m_hObject, INFINITE);

m_autoLog.Close();

}

void CPAADlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CPAADlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_ICON_NOTIFY, OnTrayNotification)
END_MESSAGE_MAP()


// CPAADlg message handlers

BOOL CPAADlg::OnInitDialog()
{
CDialog::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}

// Set the icon for this dialog. The framework does this
automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon

//HICON hIcon = ::LoadIcon(NULL, IDI_ASTERISK);
HICON hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
if (!m_TrayIcon.Create(NULL, WM_ICON_NOTIFY, "Hello", hIcon,
IDR_POPUP_MENU))
return -1;

if(! CreateLogFile())
return FALSE;

gEvent.ResetEvent();

CWinThread* pThread = AfxBeginThread(RunListener ,this);
if(!pThread)
AfxMessageBox("Thread Error!");

return TRUE; // return TRUE unless you set the focus to a control
}

void CPAADlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}

// If you add a minimize button to your dialog, you will need the code
below
// to draw the icon. For MFC applications using the document/view
model,
// this is automatically done for you by the framework.
BOOL CPAADlg::CreateLogFile()
{
CFileException e;
if(!m_autoLog.Open("c:\\AutoPaAgn.log", CFile::modeCreate|
CFile::modeNoTruncate|CFile::modeWrite, &e)){
CString s;
s.Format("%d", e.m_cause);
AfxMessageBox(s);
return FALSE;
}
return TRUE;
}

void CPAADlg::WriteToFile(CString a_sLine)
{
CTime tm = CTime::GetCurrentTime();
m_autoLog.WriteString(tm.Format("%H.%M.%S : ") + a_sLine);
}

LRESULT CPAADlg::OnTrayNotification(WPARAM wParam, LPARAM lParam)
{
//Return quickly if its not for this tray icon
if (wParam != m_tnd.uID)
return 0L;

CMenu menu, *pSubMenu;

// Clicking with right button brings up a context menu
if (LOWORD(lParam) == WM_RBUTTONUP)
{
if (!menu.LoadMenu(m_tnd.uID))
return 0;

pSubMenu = menu.GetSubMenu(0);
if (!pSubMenu)
return 0;

// Display and track the popup menu
CPoint pos;
GetCursorPos(&pos);

SetForegroundWindow();

pSubMenu->TrackPopupMenu(TPM_LEFTALIGN, pos.x, pos.y, this, NULL);

PostMessage(WM_NULL, 0, 0);

menu.DestroyMenu();
}
else if (LOWORD(lParam) == WM_LBUTTONDBLCLK)
{
// double click received, the default action is to execute default
menu item
SetForegroundWindow();

UINT uItem;
if (m_DefaultMenuItemByPos)
{
if (!menu.LoadMenu(m_tnd.uID))
return 0;

pSubMenu = menu.GetSubMenu(0);
if (!pSubMenu)
return 0;

uItem = pSubMenu->GetMenuItemID(m_DefaultMenuItemID);

menu.DestroyMenu();
}
else
uItem = m_DefaultMenuItemID;

PostMessage(WM_COMMAND, uItem, 0);
}

return 1;
}

BOOL CPAADlg::SetMenuDefaultItem(UINT uItem, BOOL bByPos)
{
if ((m_DefaultMenuItemID == uItem) && (m_DefaultMenuItemByPos ==
bByPos))
return TRUE;

m_DefaultMenuItemID = uItem;
m_DefaultMenuItemByPos = bByPos;

CMenu menu, *pSubMenu;

if (!menu.LoadMenu(m_tnd.uID))
return FALSE;

pSubMenu = menu.GetSubMenu(0);
if (!pSubMenu)
return FALSE;

::SetMenuDefaultItem(pSubMenu->m_hMenu, m_DefaultMenuItemID,
m_DefaultMenuItemByPos);

return TRUE;
}

void CPAADlg::GetMenuDefaultItem(UINT& uItem, BOOL& bByPos)
{
uItem = m_DefaultMenuItemID;
bByPos = m_DefaultMenuItemByPos;
}

UINT RunListener(LPVOID lpParam)
{
CPAADlg * pDlg = (CPAADlg *)lpParam;

if (pDlg->m_ListeningSocket.Create(5555))
{
while(true)
{
pDlg->WriteToFile("Agent - Socket Created\n");
if (pDlg->m_ListeningSocket.Listen())
{
pDlg->WriteToFile("Agent - Wait for next message\n");

if (pDlg->m_ListeningSocket.Accept(pDlg->m_ConnectedSocket))
{
if(g_stop)
break;

pDlg->WriteToFile("Agent - Message Accepted\n");
char *pBuf = new char[1025];
int iBufSize = 1024;
int iRcvd;

iRcvd = pDlg->m_ConnectedSocket.Receive(pBuf, iBufSize, 0);

pDlg->WriteToFile("Agent - Message Received\n");

if (iRcvd == SOCKET_ERROR)
{
CString s;
s.Format("Agent - Receive Error: %d\n", GetLastError());
pDlg->WriteToFile(s);
}
else
{
pDlg->m_ConnectedSocket.GetPeerName(pDlg->PeerAddress(), pDlg-
>PeerPort());

pBuf[iRcvd] = NULL;

pDlg->WriteToFile("Agent - Handle Message\n");

RegDeleteKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\AutoIt3Att\\Scripts\
\Flags");

if(pDlg->RunScript(pBuf))
pDlg->SendCompletionAck();
}
pDlg->m_ConnectedSocket.Detach();
}
else{
CString s;
s.Format("Agent - Accept Error: %d\n", GetLastError());
pDlg->WriteToFile(s);
}
}
else{
CString s;
s.Format("Agent - Listen Error: %d\n", GetLastError());
pDlg->WriteToFile(s);
}
}
}

gEvent.SetEvent();
//pDlg->m_ListeningSocket.Close();
return 0;
}

bool CPAADlg::RunScript(char a_sScriptName[])
{
CString s("Agent - RunScript ");
WriteToFile( s + a_sScriptName + "\n");

CString sScriptFullPath = sLibrary + a_sScriptName + ".au3";
CString cmdLine;

cmdLine.Format("\"c:\\Program Files\\AutoIt3\\AutoIt3.exe\" \"%s\"",
sScriptFullPath);

STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof STARTUPINFO;

PROCESS_INFORMATION pi;
BOOL res = CreateProcess(NULL,
cmdLine.GetBuffer(),
NULL,
NULL,
NULL,
NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW,
NULL,
NULL,
&si,
&pi);

if (TRUE == res)
{
WriteToFile("Agent - RunScript - Process created\n");
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return true;
}

return false;
}

void CPAADlg::SendCompletionAck(void)
{
while (1)
{
char Buf[10];
HKEY hKey;
DWORD type = REG_SZ;
long lRetCode;
DWORD size = 10;

lRetCode = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, "SOFTWARE\\AutoIt3Att\
\Scripts\\Flags", 0,KEY_READ,&hKey);

if (lRetCode == ERROR_SUCCESS){

WriteToFile("Agent - SendCompletionAck - Opened Complete Flag
registry Key\n");

lRetCode=::RegQueryValueEx(hKey,"Completed",NULL,NULL,(unsigned
char *)Buf,&size);

if(lRetCode == ERROR_SUCCESS){

Buf[1]=0;//the flag is 1 byte long: "1" or "0"

if (strcmp(Buf, "1") == 0)
{
WriteToFile("Agent - SendCompletionAck - Complete Flag registry
Key is 1\n");

CSocket sock;
if (sock.Create())//on any port
{
WriteToFile("Agent - SendCompletionAck Socket Created\n");
CString s;
s.Format("Agent - Peer IP is %s\n", m_sPeerAddress);
WriteToFile(s);
if (sock.Connect(m_sPeerAddress, 6666))
{
WriteToFile("Agent - SendCompletionAck Socket Connected\n");
int iAmtSent;
char buf[] ="1";

iAmtSent = sock.Send(buf, 1);

WriteToFile("Agent - Sent Completion Ack\n");
return;
}
else
{
CString s;
s.Format("Agent - SendCompletionAck Socket Connect Error: %d
\n", GetLastError());
WriteToFile(s);
}
}
else
{
CString s;
s.Format("Agent - SendCompletionAck Socket Create Error: %d\n",
GetLastError());
WriteToFile(s);
}
}else{
WriteToFile("Agent - SendCompletionAck - Complete Flag registry
Key is 0\n");
}
}
else
{
WriteToFile("Agent - SendCompletionAck - Failed to read Complete
Flag registry Key\n");
}

RegCloseKey(hKey);

}
else
{
WriteToFile("Agent - SendCompletionAck - Failed to open Complete
Flag registry Key\n");
}

Sleep(1000);

}//end while
}
From: Stephen Myers on
dushkin wrote:
> Hi All.
>
> Recently I posted a question (http://groups.google.com/group/
> microsoft.public.vc.mfc/browse_thread/thread/6ec9bd3dc80c408e#) about
> a problem regarding closing an app using a system tray icon menu.
>
> What I didn't know till now is that the problem was a
> CAsyncSocket::Accept() function that was waiting for a connection and
> probably blocked some messaging or something. Therfore the application
> never exited. When I removed the accept function part - the closing of
> the app via the system tray menu succeeded.
>
> So I tried to move the listen/accept while loop into a separate
> thread. I thought that this way the accept won't interfere in closing
> the app. But then, when I tried to stop the "accept" with some closing
> functions as you will see in the code, in order to allow the "Exit"
> app in the menu to work, the CAsyncSocket::Close() crashed and the
> accept didn't stop working anyway.
>
> I read somewhere that you wouldn't like to put this loop in a thread.
>
> My question is how to deal with this problem.
>
> Actually, I think I need to somehow stop the "Accept" operation and
> thus allow the system tray messages to work.
>
> How do I do it?
>
> Following is the class code. I removed some of the AboutBox code and
> some other irrelevant code. I use a class for the system tray
> functionality.
>
> Thanks.
>
> --------------------------------------------------------------------------
>
> // PAADlg.cpp : implementation file
> //
>
> #include "stdafx.h"
> #include "PAA.h"
> #include "PAADlg.h"
>
> #ifdef _DEBUG
> #define new DEBUG_NEW
> #endif
>
> bool g_stop = false;
> CEvent gEvent;
>
> UINT RunListener(LPVOID lpParam);
>
>
> // CPAADlg dialog
>
> CPAADlg::CPAADlg(CWnd* pParent /*=NULL*/)
> : CDialog(CPAADlg::IDD, pParent)
> {
> m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
> m_DefaultMenuItemByPos = TRUE;
> m_pParentWnd = pParent;
> }
>
> CPAADlg::~CPAADlg(){
>
> g_stop = true;
>
> //Trying to close Accept operation when exiting app
> m_ListeningSocket.CancelBlockingCall();
> m_ListeningSocket.ShutDown();
> m_ListeningSocket.Close();
> m_ConnectedSocket.Close();
>
> WaitForSingleObject(gEvent.m_hObject, INFINITE);
>
> m_autoLog.Close();
>
> }
>
> void CPAADlg::DoDataExchange(CDataExchange* pDX)
> {
> CDialog::DoDataExchange(pDX);
> }
>
> BEGIN_MESSAGE_MAP(CPAADlg, CDialog)
> ON_WM_SYSCOMMAND()
> ON_WM_PAINT()
> ON_WM_QUERYDRAGICON()
> //}}AFX_MSG_MAP
> ON_MESSAGE(WM_ICON_NOTIFY, OnTrayNotification)
> END_MESSAGE_MAP()
>
>
> // CPAADlg message handlers
>
> BOOL CPAADlg::OnInitDialog()
> {
> CDialog::OnInitDialog();
>
> // Add "About..." menu item to system menu.
>
> // IDM_ABOUTBOX must be in the system command range.
> ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
> ASSERT(IDM_ABOUTBOX < 0xF000);
>
> CMenu* pSysMenu = GetSystemMenu(FALSE);
> if (pSysMenu != NULL)
> {
> BOOL bNameValid;
> CString strAboutMenu;
> bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
> ASSERT(bNameValid);
> if (!strAboutMenu.IsEmpty())
> {
> pSysMenu->AppendMenu(MF_SEPARATOR);
> pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
> }
> }
>
> // Set the icon for this dialog. The framework does this
> automatically
> // when the application's main window is not a dialog
> SetIcon(m_hIcon, TRUE); // Set big icon
> SetIcon(m_hIcon, FALSE); // Set small icon
>
> //HICON hIcon = ::LoadIcon(NULL, IDI_ASTERISK);
> HICON hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
> if (!m_TrayIcon.Create(NULL, WM_ICON_NOTIFY, "Hello", hIcon,
> IDR_POPUP_MENU))
> return -1;
>
> if(! CreateLogFile())
> return FALSE;
>
> gEvent.ResetEvent();
>
> CWinThread* pThread = AfxBeginThread(RunListener ,this);
> if(!pThread)
> AfxMessageBox("Thread Error!");
>
> return TRUE; // return TRUE unless you set the focus to a control
> }
>
> void CPAADlg::OnSysCommand(UINT nID, LPARAM lParam)
> {
> if ((nID & 0xFFF0) == IDM_ABOUTBOX)
> {
> CAboutDlg dlgAbout;
> dlgAbout.DoModal();
> }
> else
> {
> CDialog::OnSysCommand(nID, lParam);
> }
> }
>
> // If you add a minimize button to your dialog, you will need the code
> below
> // to draw the icon. For MFC applications using the document/view
> model,
> // this is automatically done for you by the framework.
> BOOL CPAADlg::CreateLogFile()
> {
> CFileException e;
> if(!m_autoLog.Open("c:\\AutoPaAgn.log", CFile::modeCreate|
> CFile::modeNoTruncate|CFile::modeWrite, &e)){
> CString s;
> s.Format("%d", e.m_cause);
> AfxMessageBox(s);
> return FALSE;
> }
> return TRUE;
> }
>
> void CPAADlg::WriteToFile(CString a_sLine)
> {
> CTime tm = CTime::GetCurrentTime();
> m_autoLog.WriteString(tm.Format("%H.%M.%S : ") + a_sLine);
> }
>
> LRESULT CPAADlg::OnTrayNotification(WPARAM wParam, LPARAM lParam)
> {
> //Return quickly if its not for this tray icon
> if (wParam != m_tnd.uID)
> return 0L;
>
> CMenu menu, *pSubMenu;
>
> // Clicking with right button brings up a context menu
> if (LOWORD(lParam) == WM_RBUTTONUP)
> {
> if (!menu.LoadMenu(m_tnd.uID))
> return 0;
>
> pSubMenu = menu.GetSubMenu(0);
> if (!pSubMenu)
> return 0;
>
> // Display and track the popup menu
> CPoint pos;
> GetCursorPos(&pos);
>
> SetForegroundWindow();
>
> pSubMenu->TrackPopupMenu(TPM_LEFTALIGN, pos.x, pos.y, this, NULL);
>
> PostMessage(WM_NULL, 0, 0);
>
> menu.DestroyMenu();
> }
> else if (LOWORD(lParam) == WM_LBUTTONDBLCLK)
> {
> // double click received, the default action is to execute default
> menu item
> SetForegroundWindow();
>
> UINT uItem;
> if (m_DefaultMenuItemByPos)
> {
> if (!menu.LoadMenu(m_tnd.uID))
> return 0;
>
> pSubMenu = menu.GetSubMenu(0);
> if (!pSubMenu)
> return 0;
>
> uItem = pSubMenu->GetMenuItemID(m_DefaultMenuItemID);
>
> menu.DestroyMenu();
> }
> else
> uItem = m_DefaultMenuItemID;
>
> PostMessage(WM_COMMAND, uItem, 0);
> }
>
> return 1;
> }
>
> BOOL CPAADlg::SetMenuDefaultItem(UINT uItem, BOOL bByPos)
> {
> if ((m_DefaultMenuItemID == uItem) && (m_DefaultMenuItemByPos ==
> bByPos))
> return TRUE;
>
> m_DefaultMenuItemID = uItem;
> m_DefaultMenuItemByPos = bByPos;
>
> CMenu menu, *pSubMenu;
>
> if (!menu.LoadMenu(m_tnd.uID))
> return FALSE;
>
> pSubMenu = menu.GetSubMenu(0);
> if (!pSubMenu)
> return FALSE;
>
> ::SetMenuDefaultItem(pSubMenu->m_hMenu, m_DefaultMenuItemID,
> m_DefaultMenuItemByPos);
>
> return TRUE;
> }
>
> void CPAADlg::GetMenuDefaultItem(UINT& uItem, BOOL& bByPos)
> {
> uItem = m_DefaultMenuItemID;
> bByPos = m_DefaultMenuItemByPos;
> }
>
> UINT RunListener(LPVOID lpParam)
> {
> CPAADlg * pDlg = (CPAADlg *)lpParam;
>
> if (pDlg->m_ListeningSocket.Create(5555))
> {
> while(true)
> {
> pDlg->WriteToFile("Agent - Socket Created\n");
> if (pDlg->m_ListeningSocket.Listen())
> {
> pDlg->WriteToFile("Agent - Wait for next message\n");
>
> if (pDlg->m_ListeningSocket.Accept(pDlg->m_ConnectedSocket))
> {
> if(g_stop)
> break;
>
> pDlg->WriteToFile("Agent - Message Accepted\n");
> char *pBuf = new char[1025];
> int iBufSize = 1024;
> int iRcvd;
>
> iRcvd = pDlg->m_ConnectedSocket.Receive(pBuf, iBufSize, 0);
>
> pDlg->WriteToFile("Agent - Message Received\n");
>
> if (iRcvd == SOCKET_ERROR)
> {
> CString s;
> s.Format("Agent - Receive Error: %d\n", GetLastError());
> pDlg->WriteToFile(s);
> }
> else
> {
> pDlg->m_ConnectedSocket.GetPeerName(pDlg->PeerAddress(), pDlg-
>> PeerPort());
>
> pBuf[iRcvd] = NULL;
>
> pDlg->WriteToFile("Agent - Handle Message\n");
>
> RegDeleteKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\AutoIt3Att\\Scripts\
> \Flags");
>
> if(pDlg->RunScript(pBuf))
> pDlg->SendCompletionAck();
> }
> pDlg->m_ConnectedSocket.Detach();
> }
> else{
> CString s;
> s.Format("Agent - Accept Error: %d\n", GetLastError());
> pDlg->WriteToFile(s);
> }
> }
> else{
> CString s;
> s.Format("Agent - Listen Error: %d\n", GetLastError());
> pDlg->WriteToFile(s);
> }
> }
> }
>
> gEvent.SetEvent();
> //pDlg->m_ListeningSocket.Close();
> return 0;
> }
>
> bool CPAADlg::RunScript(char a_sScriptName[])
> {
> CString s("Agent - RunScript ");
> WriteToFile( s + a_sScriptName + "\n");
>
> CString sScriptFullPath = sLibrary + a_sScriptName + ".au3";
> CString cmdLine;
>
> cmdLine.Format("\"c:\\Program Files\\AutoIt3\\AutoIt3.exe\" \"%s\"",
> sScriptFullPath);
>
> STARTUPINFO si;
> ZeroMemory(&si, sizeof(si));
> si.cb = sizeof STARTUPINFO;
>
> PROCESS_INFORMATION pi;
> BOOL res = CreateProcess(NULL,
> cmdLine.GetBuffer(),
> NULL,
> NULL,
> NULL,
> NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW,
> NULL,
> NULL,
> &si,
> &pi);
>
> if (TRUE == res)
> {
> WriteToFile("Agent - RunScript - Process created\n");
> CloseHandle(pi.hProcess);
> CloseHandle(pi.hThread);
> return true;
> }
>
> return false;
> }
>
> void CPAADlg::SendCompletionAck(void)
> {
> while (1)
> {
> char Buf[10];
> HKEY hKey;
> DWORD type = REG_SZ;
> long lRetCode;
> DWORD size = 10;
>
> lRetCode = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, "SOFTWARE\\AutoIt3Att\
> \Scripts\\Flags", 0,KEY_READ,&hKey);
>
> if (lRetCode == ERROR_SUCCESS){
>
> WriteToFile("Agent - SendCompletionAck - Opened Complete Flag
> registry Key\n");
>
> lRetCode=::RegQueryValueEx(hKey,"Completed",NULL,NULL,(unsigned
> char *)Buf,&size);
>
> if(lRetCode == ERROR_SUCCESS){
>
> Buf[1]=0;//the flag is 1 byte long: "1" or "0"
>
> if (strcmp(Buf, "1") == 0)
> {
> WriteToFile("Agent - SendCompletionAck - Complete Flag registry
> Key is 1\n");
>
> CSocket sock;
> if (sock.Create())//on any port
> {
> WriteToFile("Agent - SendCompletionAck Socket Created\n");
> CString s;
> s.Format("Agent - Peer IP is %s\n", m_sPeerAddress);
> WriteToFile(s);
> if (sock.Connect(m_sPeerAddress, 6666))
> {
> WriteToFile("Agent - SendCompletionAck Socket Connected\n");
> int iAmtSent;
> char buf[] ="1";
>
> iAmtSent = sock.Send(buf, 1);
>
> WriteToFile("Agent - Sent Completion Ack\n");
> return;
> }
> else
> {
> CString s;
> s.Format("Agent - SendCompletionAck Socket Connect Error: %d
> \n", GetLastError());
> WriteToFile(s);
> }
> }
> else
> {
> CString s;
> s.Format("Agent - SendCompletionAck Socket Create Error: %d\n",
> GetLastError());
> WriteToFile(s);
> }
> }else{
> WriteToFile("Agent - SendCompletionAck - Complete Flag registry
> Key is 0\n");
> }
> }
> else
> {
> WriteToFile("Agent - SendCompletionAck - Failed to read Complete
> Flag registry Key\n");
> }
>
> RegCloseKey(hKey);
>
> }
> else
> {
> WriteToFile("Agent - SendCompletionAck - Failed to open Complete
> Flag registry Key\n");
> }
>
> Sleep(1000);
>
> }//end while
> }

I would replace RunListener with a class derived from CWinThread. You
can then communicate with the thread using PostThreadMessage().
Responses back to the main thread go via PostMessage() to the main window.

Your listener no longer needs Sleep() as it has it's own message pump.
You can then derive from CAsyncSocket and supply OnReceive() etc. This
gives you an event driven socket with very little glue needed.

To shutdown, you PostThreadMessage() to the RunListener thread which in
turn does a PostQuitMessage().

Be very careful in making calls to the main GUI thread from a worker
thread. Very bad things will happen.

Look for "user interface threads'. The name is somewhat misleading as
there is not necessarily something for the user to interface with. The
key is supporting a message pump.

Joe has some good stuff on his MVP site.

Hope this helps.
Steve