Re: Terminating Accept
 
On Mar 22, 9:33 pm, Joseph M. Newcomer <newco...@flounder.com> wrote:
See below...
On Mon, 22 Mar 2010 07:28:21 -0700 (PDT), dushkin <talt...@gmail.com> wro=
te:
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
****
If you got an OnAccept() notification without error, then the Accept() sh=
ould be
immediate, becuase the connection has actually been established at the lo=
wer level of the
protocol statck.  You should not be calling Accept() except in the OnAc=
cept() handler.
****>probably blocked some messaging or something. Therfore the applicati=
on
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.
Listen() is never part of the loop; Listen() merely makes the socket bind=
ing publicly
accessible, so the loop is
Bind()
Listen();
while(true)
   {
    Accept(...);
   }
I have no idea what the nonsensical word "crash" means, since you failed =
to explain the
phenomenon you observed.  Note that for CAsyncSocket, you would NEVER w=
rite the above
loop, it makes no sens whatsoever!  Instead, you would handle the Accep=
t() in your
OnAccept() handler., so the fact that you have written a loop means you d=
on't understand
how CAsyncSocket actually works, and therefore your code is erroneous. =
 Fix your code
first.
****
I read somewhere that you wouldn't like to put this loop in a thread.
****
No, it is erroneous code.
****
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.
****
Did you call Shutdown() to shut down the socket?
*****
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);
****
There is NOTHING CORRECT or even POSSIBLY CORRECT about this code!  The=
 WFSO in a
constructor means that this will hang until the event is set, which means=
 you get no UI at
all.  NEVER write code like this, ever, under any imginable circumstanc=
es
If you want to close the log file when the thread terminates, have the th=
read PostMessage
a user-defined message, which you handle in your dialog, and close the lo=
g file there!
This is absolutely HORRIBLE code!
*****
   m_autoLog.Close();
}
void CPAADlg::DoDataExchange(CDataExchange* pDX)
{
   CDialog::DoDataExchange(pDX);
}
***
Nothing happens.  You never get here.  The constructor hangs
****
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()
****
YOu will get no notifications of any sort until that event gets set.  T=
herefore, this code
won't handle anything.  It can never be invoked, because the thread has=
 blocked during the
constructor!
*****
// CPAADlg message handlers
BOOL CPAADlg::OnInitDialog()
{
***
You will never get here because the code hangs in the constructor
****
   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_ABOUT=
BOX);
           ASSERT(bNameValid);
           if (!strAboutMenu.IsEmpty())
           {
                   pSysMenu->AppendMenu(MF_SEPARATO=
R);
                   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 b=
ig icon
   SetIcon(m_hIcon, FALSE);                // Set s=
mall 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();
****
The use of events scares me.  You don't need any, and if you have them,=
 your code is
probably wrong.  Unless you made the deep mistake of believing the horr=
ible KB article on
multithreaded sockets, in which case, your code will be complete trash an=
d can only be
rewritten completely to salvage it (see my essay on my MVP TIps site on m=
ultithreaded
asynschronous sockets.  which shows why the Microsoft article is comple=
te rubbish, having
been written by someone who did not understand sockets, or threading, or =
synchronization).
****
   CWinThread* pThread = AfxBeginThread(RunListener ,this);
   if(!pThread)
           AfxMessageBox("Thread Error!");
****
YOu might want to look at my ToString function, which takes a formatting =
string and
arguments and returns a CString, which allows you to say something meanin=
gful here, such
as WHY there is a failure to create the thread!
*****
   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.
****
YOu might want to move this function so it doesn't have the wrong comment=
 above it!
****
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);
****
Why is this not in a try...catch block?  It can throw an exception.  =
And why do you
presume time formatting is %H.%M.%S, which is cultural and should change =
based on locale?
****
}
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, p=
os.y, this, NULL);
           PostMessage(WM_NULL, 0, 0);
****
And the purpose of posting WM_NULL is what?
****
           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)
***
This code makes me nervous.  Where is m_defaultMenuItemID set?  I can=
not find where the
subroutine below is called.  At this point, I'd search for the default =
menu item as set in
the menu and not trust any global variable to tell me what it was.
****
           {
                   if (!menu.LoadMenu(m_tnd.uID))
                           return 0;
                   pSubMenu = menu.GetSubMenu(0);
                   if (!pSubMenu)
                           return 0;
                   uItem = pSubMenu->GetMenuItemI=
D(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_DefaultMenuItemByPo=
s ==
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)
****
WHy is this a global function?  If you don't want to make it a static c=
lass member, it
should at least be a static name within this compilation unit.  But it =
is sloppy to use a
global function for a thread function; you should always use a static met=
hod of your class
e.g.,
        class CPAADlg : public CDIalog {
...
read more =BB
Joseph,
 Your answers are the best and I learn much of them. I just wish your
attitude were a little more tolerant...
Anyhow, I started to implement the OnAccept, OnSend, etc.
I tried to follow the example on chapter 24 in "MFC Programming with
Visual C++ 6 Unleashed" as much as possible. I built a client app and
a server app.
The server seems to get up and wait for a request on accept.
But for some reason the client fails to connect. It returns error
10035. Now, I read in some places what you and other wrote about it -
that it is a natural behavior of an asynchronous socket. But I didn't
understand how to deal with it and why does it happen? How can we
avoid it - if at all?
Also I can tell that the OnSend is called and the Onconnect not. I
understand the latter (because connect failed) but don;t understand
the first one.
Another issue I need to know how to implement is - after the
agent(server) gets the request and does what he do with it - it needs
to send an ack back to the client.
can you explain me how?
I will post here the code, but I will appreciate if you will remember
that I am relatively a newbie and I hope your answers will be tolerant
but professional as always.
I still haven't implemented all the recommendations you gave me
before. Their time will sure come.
(also sorry for my not perfect English - it is not my mother tongue)
---------------------------------------------------------------------------=
-----------------------------------
Socket - h
---------------------------------------------------------------------------=
-----------------------------------
class CPaaSock : public CAsyncSocket
{
public:
    CPaaSock();
    virtual ~CPaaSock();
    void SetParent(CDialog *pWnd)
    {
        // Set the member pointer
        m_pWnd = pWnd;
    }
private:
    CDialog* m_pWnd;
public:
    virtual void OnAccept(int nErrorCode);
    virtual void OnClose(int nErrorCode);
    virtual void OnConnect(int nErrorCode);
    virtual void OnReceive(int nErrorCode);
    virtual void OnSend(int nErrorCode);
};
---------------------------------------------------------------------------=
-----------------------------------
Socket - cpp
---------------------------------------------------------------------------=
-----------------------------------
// CPaaSock member functions
void CPaaSock::OnConnect(int nErrorCode)
{
    // Were there any errors?
    if (nErrorCode == 0)
        // No, call the dialog's OnAccept function
        ((CPAMDlg*)m_pWnd)->OnAccept();
}
void CPaaSock::OnAccept(int nErrorCode)
{
    // Were there any errors?
    if (nErrorCode == 0)
        // No, call the dialog's OnAccept function
        ((CPAMDlg*)m_pWnd)->OnAccept();
}
void CPaaSock::OnReceive(int nErrorCode)
{
    // Were there any errors?
    if (nErrorCode == 0)
        // No, call the dialog's OnAccept function
        ((CPAMDlg*)m_pWnd)->OnReceive();
}
void CPaaSock::OnSend(int nErrorCode)
{
    // Were there any errors?
    if (nErrorCode == 0)
        // No, call the dialog's OnAccept function
        ((CPAMDlg*)m_pWnd)->OnSend();
}
void CPaaSock::OnClose(int nErrorCode)
{
    // Were there any errors?
    if (nErrorCode == 0)
        // No, call the dialog's OnAccept function
        ((CPAMDlg*)m_pWnd)->OnClose();
}
---------------------------------------------------------------------------=
-----------------------------------
Server - h
---------------------------------------------------------------------------=
-----------------------------------
// PAADlg.h : header file
//
#pragma once
#include "SystemTray.h"
#include "PaaSock.h"
#define WM_ICON_NOTIFY  WM_APP+10
// CPAADlg dialog
class CPAADlg : public CDialog
{
// Construction
public:
    CPAADlg(CWnd* pParent = NULL);	// standard constructor
    virtual ~CPAADlg();
    // Change menu default item
    void GetMenuDefaultItem(UINT& uItem, BOOL& bByPos);
    BOOL SetMenuDefaultItem(UINT uItem, BOOL bByPos);
    CString PeerAddress() const { return m_sPeerAddress; }
    void SetPeerAddress(CString val) { m_sPeerAddress = val; }
    UINT& PeerPort() { return m_uPeerPort; }
    void SetPeerPort(UINT val) { m_uPeerPort = val; }
    void SendCompletionAck(void);
    bool RunScript(char a_sScriptName[]);
    void WriteToFile(CString line);
    CPaaSock m_sListenSocket; //used for listening for connection
requests
    CPaaSock m_sConnectSocket; //used for sending messages back and forth
    void OnAccept();
    void OnConnect();
    void OnReceive();
    void OnSend();
    void OnClose();
    // Default handler for tray notification message
    virtual LRESULT OnTrayNotification(WPARAM uID, LPARAM lEvent);
// Dialog Data
    enum { IDD = IDD_PAA_DIALOG };
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support
// Implementation
protected:
    HICON m_hIcon;
    // Generated message map functions
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()
private:
    CString m_sPeerAddress;
    UINT m_uPeerPort;
    BOOL CreateLogFile();
    CStdioFile m_autoLog;
    CWnd* m_pParentWnd;
    CSystemTray m_TrayIcon;
    NOTIFYICONDATA  m_tnd;
    UINT         m_DefaultMenuItemID;
    BOOL         m_DefaultMenuItemByPos;
    BOOL m_bVisible;
    void StartListen();
public:
    afx_msg void OnWindowPosChanging(WINDOWPOS* lpwndpos);
};
---------------------------------------------------------------------------=
-----------------------------------
Server - cpp
---------------------------------------------------------------------------=
-----------------------------------
// PAADlg.cpp : implementation file
//
#include "stdafx.h"
#include "PAA.h"
#include "PaaSock.h"
#include "PAADlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
const CString sLibrary("c:\\Automation Scripts\\");
static const UINT iListenPort = 4000;
// CPAADlg dialog
CPAADlg::CPAADlg(CWnd* pParent /*=NULL*/)
    : CDialog(CPAADlg::IDD, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_DefaultMenuItemByPos = TRUE;
    m_pParentWnd = pParent;
    m_bVisible = FALSE;
}
CPAADlg::~CPAADlg(){
    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)
    ON_WM_WINDOWPOSCHANGING()
END_MESSAGE_MAP()
// CPAADlg message handlers
BOOL CPAADlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    // 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, "PA Automation Agent",
hIcon, IDR_POPUP_MENU))
        return -1;
    if(! CreateLogFile())
        return FALSE;
    m_sListenSocket.SetParent(this);
    m_sConnectSocket.SetParent(this);
    StartListen();
    return TRUE;  // return TRUE  unless you set the focus to a control
}
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;
}
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
}
void CPAADlg::StartListen(){
    // Create a socket bound to the port specified
    m_sListenSocket.Create(iListenPort);
    WriteToFile("Agent - Socket Created\n");
    // Listen for connection requests
    m_sListenSocket.Listen();
    WriteToFile("Agent - Ready for next message\n");
}
void CPAADlg::OnAccept()
{
    // Accept the connection request
    m_sListenSocket.Accept(m_sConnectSocket);
    WriteToFile("Agent - Message Accepted\n");
}
void CPAADlg::OnConnect()
{
}
void CPAADlg::OnReceive()
{
    char *pBuf = new char[1025];
    int iBufSize = 1024;
    int iRcvd;
    CString strRecvd;
    // Receive the message
    iRcvd = m_sConnectSocket.Receive(pBuf, iBufSize);
    WriteToFile("Agent - Message Received\n");
    if (iRcvd == SOCKET_ERROR)
    {
        CString s;
        s.Format("Agent - Receive Error: %d\n", GetLastError());
        WriteToFile(s);
    }
    else
    {
        m_sConnectSocket.GetPeerName(PeerAddress(), PeerPort());
        pBuf[iRcvd] = NULL;
        WriteToFile("Agent - Handle Message\n");
        RegDeleteKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\AutoIt3Att\\Scripts\
\Flags");
        if(RunScript(pBuf))
            SendCompletionAck();
    }
}
void CPAADlg::OnSend()
{
}
void CPAADlg::OnClose()
{
    // Close the connected socket
    m_sConnectSocket.Close();
}
//Keep dialog hidden!
void CPAADlg::OnWindowPosChanging(WINDOWPOS* lpwndpos)
{
    if(!m_bVisible)
        lpwndpos->flags &= ~SWP_SHOWWINDOW;
    CDialog::OnWindowPosChanging(lpwndpos);
}
---------------------------------------------------------------------------=
-----------------------------------
Client - h
---------------------------------------------------------------------------=
-----------------------------------
// PAMDlg.h : header file
//
#pragma once
#include "PaaSock.h"
// CPAMDlg dialog
class CPAMDlg : public CDialog
{
// Construction
public:
    CPAMDlg(CWnd* pParent = NULL);	// standard constructor
    CPaaSock m_sConnectSocket; //used for sending messages back and forth
    void OnAccept();
    void OnConnect();
    void OnReceive();
    void OnSend();
    void OnClose();
// Dialog Data
    enum { IDD = IDD_PAM_DIALOG };
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support
// Implementation
protected:
    HICON m_hIcon;
    // Generated message map functions
    virtual BOOL OnInitDialog();
    BOOL CreateLogFile();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()
public:
    void Run();
    void SendScriptRequest(const CString& a_sAddress, char
a_sScriptName[], bool a_bWaitForCompleteAck = true);
private:
    void WaitForCompletionAck(void);
    CStdioFile m_autoLog;
    char m_sScriptName[255];
    void WriteToLog(const CString& line);
public:
    virtual BOOL DestroyWindow();
};
---------------------------------------------------------------------------=
-----------------------------------
Client - cpp
---------------------------------------------------------------------------=
-----------------------------------
// PAMDlg.cpp : implementation file
//
#include "stdafx.h"
#include "PAM.h"
#include "PaaSock.h"
#include "PAMDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
static const UINT iServerPort = 4000;
// CPAMDlg dialog
CPAMDlg::CPAMDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CPAMDlg::IDD, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CPAMDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CPAMDlg, CDialog)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    //}}AFX_MSG_MAP
//	ON_WM_CLOSE()
END_MESSAGE_MAP()
// CPAMDlg message handlers
BOOL CPAMDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    // 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
    if(! CreateLogFile())
        return FALSE;
    m_sConnectSocket.SetParent(this);
    Run();
    return TRUE;  // return TRUE  unless you set the focus to a control
}
void CPAMDlg::Run()
{
    WriteToLog("Manager - Button Clicked\n");
    SendScriptRequest(_T("localhost"), "LoginToACC");
}
void CPAMDlg::SendScriptRequest(const CString& a_sAddress, char
a_sScriptName[], bool a_bWaitForCompleteAck)
{
    Sleep(1000);
    strcpy_s(m_sScriptName, a_sScriptName);
    m_sConnectSocket.Create();//on any port
    WriteToLog("\n");
    WriteToLog("Manager - Socket Created\n");
    m_sConnectSocket.Connect(a_sAddress, iServerPort);
}
BOOL CPAMDlg::DestroyWindow()
{
    m_autoLog.Close();
    return CDialog::DestroyWindow();
}
BOOL CPAMDlg::CreateLogFile()
{
    CFileException e;
    if(!m_autoLog.Open("c:\\AutoPaMan.log", CFile::modeCreate|
CFile::modeNoTruncate|CFile::modeWrite, &e)){
        CString s;
        s.Format("%d", e.m_cause);
        AfxMessageBox(s);
        return FALSE;
    }
    return TRUE;
}
void CPAMDlg::WriteToLog(const CString& line)
{
    CTime tm = CTime::GetCurrentTime();
    m_autoLog.WriteString(tm.Format("%H.%M.%S : ") + line);
}
void CPAMDlg::OnConnect()
{
    WriteToLog("Manager - Socket Connected\n");
    int iAmtSent;
    CString s("Manager - Going to send ");
    WriteToLog(s + m_sScriptName + " Request\n");
    iAmtSent = m_sConnectSocket.Send(m_sScriptName,
strlen(m_sScriptName));
}
void CPAMDlg::OnClose()
{
    // Close the connected socket
    m_sConnectSocket.Close();
}
void CPAMDlg::OnAccept()
{
}
void CPAMDlg::OnSend()
{
    WriteToLog("Manager - Message Sent !\n");
}
void CPAMDlg::OnReceive()
{
}