The script doesn't send any pings, it just tries to open a connection to a server, (any type of server, just need an IP and port), if it can't make one within 100ms, (default value), then it fails and the script continues. So in theory, it's not actually waiting for anything to come back unless its connection is accepted in which case the script will continue to progress in under the 100ms wait time. I could make the 5 second delay between connection attempts shorter, (I didn't want it to get flagged by any security programs as excessive pings sometimes do), or configuable - if I took out the delay then it would attempt connections every 100ms or less.
Ah! (Port Connection) ...Therein lying the gotcha I mentioned at the beginning.Port Connection's do a 3-way handshake:
SYN (outbount request)
SYN-ACK (target response)
ACK (outbound acceptance)
Slamming the socket shut without the SYN-ACK requires a non-blocking raw socket connection that creates its own thread and uses select(...) to check for writability before timingout and slamming shut... (Which still isn't 100% reliable after XP SP2...) ...otherwise the default timeout (graceful closure) is in the 3-5 min range.
That's why I'd suggested using something strictly local for the initial (test) loop like a system call level iteration of the adapter statuses. While not directly related (it only pulls address info from the first adapter it finds - but you could loop it to get the others), here's an example of the type of function you would need:
//===========================================================================================
//============================================================================================
BOOL GetLocalIPAddressRange(SCAN_IP_STRUCT *lpsIP) {
char szLocalHost[MIN_BUFF] = {0};
char szNetMask[MIN_BUFF] = {0};
PIP_ADAPTER_INFO pAdapterInfo;
pAdapterInfo = (IP_ADAPTER_INFO *) malloc(sizeof(IP_ADAPTER_INFO));
ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO);
// Make an initial call to GetAdaptersInfo to get
// the necessary size into the ulOutBufLen variable
if(GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *) malloc (ulOutBufLen);
}
if(GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == NO_ERROR) {
if(pAdapterInfo) { // Grab the First Adapter we "See", and Run with it.
// MessageBox(lpsIP->hList, pAdapter->Description, "Adapter Description", MB_OK); // Dev Mgr Name
// MessageBox(lpsIP->hList, pAdapter->AdapterName, "Adapter Name", MB_OK); // Class ID
StringCbCopy(szLocalHost, MIN_BUFF, pAdapterInfo->IpAddressList.IpAddress.String);
StringCbCopy(szNetMask, MIN_BUFF, pAdapterInfo->IpAddressList.IpMask.String);
free(pAdapterInfo);
}else{
return FALSE;
}
}
//----------------------------------------------------------------------------->
u_long host_addr = inet_addr(szLocalHost); //-+-//-//> Local IP Address
u_long net_mask = inet_addr(szNetMask); //-+-//-//-> LAN (Sub)NetMask
u_long net_addr = host_addr & net_mask; //-+-//-//+-+-+-+-+-> 192.168.5.0
u_long bcast_addr = net_addr | (~net_mask); //-//-+-+-+-+-+-> 192.168.5.255
net_addr = ntohl(net_addr); //-+-// Convert Network Addy to Network Byte Order,
bcast_addr = ntohl(bcast_addr); // Convert Broadcast Addy to Network Byte Order
//-//-+-+-+-//-+-//-+-//-+-//-//-+-+-+-+-+->
net_addr +=1; //-//-+-> Add 1 to Get from Network Address to First IP in Subnet,
bcast_addr -=1; // Subtract 1 to Get from Broadcast Address to Last IP in Subnet
//-//-+-+-+-//-+-//-+-//-+-//-//-+-+-+-+-+->
net_addr = htonl(net_addr); //-+-// Convert Network Addy Back to Host Byte Order,
bcast_addr = htonl(bcast_addr); // Convert Broadcast Addy Back to Host Byte Order
//----------------------------------------------------------------------------->
strcpy_s(lpsIP->szStartIP, MIN_BUFF, inet_ntoa(*((struct in_addr *)&net_addr)));
strcpy_s(lpsIP->szEndIP, MIN_BUFF, inet_ntoa(*((struct in_addr *)&bcast_addr)));
strcpy_s(lpsIP->szNetMask, MIN_BUFF, szNetMask);
//----------------------------------------------------------------------------->
return TRUE;
}
Note: that is actually the code that Page Countster uses to get the default LM IP address range for the Scan for Printers dialog box.
Caveat: Currently it doesn't reinitialise itself to display on the logon screen if the current user logs off - that's about it. I'm still looking at fixing this by calling it again, (probably needs higher privileges so it can display on the logon screen again).
Running it on logoff isn't really the issue, because the WiFi card stays on. The trick is to get it to run on wakeup from sleep/hibernation when the connection has dropped because the WiFi card was napping.
Well, it kinda is at the moment because the instance running from the Startup script event terminates on detection of 'explorer.exe' process. And the instance running at Logon event is terminated when the 'explorer.exe' process terminates.
So when it drops back to the logon screen, there is no NetCheck program running - this is why I would like to run it as a service if I could get the damn thing to interact with the display 
Damn, that is a sticky one. Apparently "Allow service to interact with desktop" was depricated a while back due to the need for more complete Session 0 isolation - which quickly sinks out-of-my-depth (f0dder...?) - So the new more correct(er) way is to use two applications that pitch-N-catch. The service does the test & pitch, and the User GUI does the catch & display.
Maybe use WMI to look for (signs of life) a wake event?