Link to home
Start Free TrialLog in
Avatar of HStrix
HStrix

asked on

C: Is computer reachable

Hello experts,
I'm looking for a solution in pure C (Windows APIs are needed?) to verify if a computer is reachable or not.
I'm using Visual Studio 6.

If anyone knows how to do this
please supply an appropriate snippet.

Thank you for any help.

   HStrix

Avatar of Jaime Olivares
Jaime Olivares
Flag of Peru image

You can use Winsock functions: gethostbyname and gethostbyaddr:
http://msdn.microsoft.com/library/en-us/winsock/winsock/gethostbyname_2.asp
http://msdn.microsoft.com/library/en-us/winsock/winsock/gethostbyaddr_2.asp

also you can make a ping to know if computer is available in real-time.
Also, take a look to this article about pinging in Windows:
http://www.codeproject.com/internet/winping.asp
Avatar of HStrix
HStrix

ASKER

Thank you jaime_olivares,
I found the following code (at http://msdn.microsoft.com/library/en-us/winsock/winsock/gethostbyname_2.asp):
---
      // Declare and initialize variables
      hostent* remoteHost;
      char* host_name;
      unsigned int addr;
      //----------------------
      // User inputs name of host
      //printf("Input name of host: ");                                
      host_name = (char*) malloc(sizeof(char*)*16);
      //fgets(host_name, 16, stdin);                              /7  <= original code
      host_name = "mycomputername";                       // <== this doesn't work ??
---
Can you help me to replace that statement?
Just need this:

     hostent* remoteHost;
     char* host_name;
     unsigned int addr;
     host_name = "mycomputername";
     // now you can call your function      
Avatar of HStrix

ASKER

OK, after this my code is:
---
      // If the user input is an alpha name for the host, use gethostbyname()
      // If not, get host by addr (assume IPv4)
      //if (isalpha(host_name[0])) {   /* host address is a name */
      //host_name[strlen(host_name)-1] = '\0'; /* NULL TERMINATED */
      remoteHost = gethostbyname(host_name);
      //}
      //else  {
      //addr = inet_addr(host_name);
      //remoteHost = gethostbyaddr((char *)&addr, 4, AF_INET);
      //}

                int intLastErr = WSAGetLastError(); // gives 10093

      if (WSAGetLastError() != 0) {
      if (WSAGetLastError() == 11001)
      //printf("Host not found...\nExiting.\n");
            strcpy(strComputerVerify,"Host not found");
      }
      else
      //printf("error#:%ld\n", WSAGetLastError());
            strcpy(strComputerVerify,"unknown error");
---
I get in remotehost as address all zeros.
WSAGetLastError = 10093
Can you help me again?
You have commented the most important line:
addr = inet_addr(host_name);
Avatar of HStrix

ASKER

Now my code looks as follows:
---
      // If the user input is an alpha name for the host, use gethostbyname()
      // If not, get host by addr (assume IPv4)
      //if (isalpha(host_name[0])) {   /* host address is a name */
      //host_name[strlen(host_name)-1] = '\0'; /* NULL TERMINATED */
      //remoteHost = gethostbyname(host_name);
      //}
      //else  {
      addr = inet_addr(host_name);
      remoteHost = gethostbyaddr((char *)&addr, 4, AF_INET);  // remoteHost is again zero
      //}
      int intLastErr = WSAGetLastError(); // 10093 appears again
      //if (WSAGetLastError() != 0) {
      if (intLastErr != 0)
      {
            //if (WSAGetLastError() == 11001)
            if (intLastErr == 11001)
            {
                  //printf("Host not found...\nExiting.\n");
                  strcpy(strComputerVerify,"Host not found");
            } else
            {
                  strcpy(strComputerVerify,"???");
            }
      }
      else
            //printf("error#:%ld\n", WSAGetLastError());
            strcpy(strComputerVerify,"unknown error")
---
Something is not working...
Avatar of jkr
'gethostbyname()' will not help you in determining if a machine is reachable. It just tells whether there's a DNS record available or not. You could just use

WKSTA_INFO_100 w100;

NetWkstaGetInfo ( L"\\\\themachine", 100, &w100);

If that call fails, the machine is not reachable.
Avatar of HStrix

ASKER

Thank you jkr,
what .h file and which .lib file do I need?
I added netapi32.lib, but I miss something.
The header file is 'lmwksta.h' - BTW, NOTE that this might also fail if theat machine is not running windows or the Workstation service is not running (the latter meaning "unreachable" anyway). However, a machine can also be cofigured to not answer to "pings".
Avatar of HStrix

ASKER

OK,
now I get the error
---
error C2664: 'NetWkstaGetInfo': cannot convert parameter 1 from 'const unsigned short[11]' to 'LPSTR'
---
My code is:
---
void verifyComputer(void)
{
   WKSTA_INFO_100 w100;
   NetWkstaGetInfo ( L"\\\\mycomputername", 100, &w100);
}
---
>NOTE that this might also fail if theat machine is not running windows or the >Workstation service is not running (the latter meaning "unreachable" anyway).
That's why ping is a better solution

> However, a machine can also be cofigured to not answer to "pings".
In case machines are yours, then there is no such problem
Avatar of HStrix

ASKER

Concerning the machine:
I know that the machine I'm trying to verify does exist.
But I'm not sure that it is running.
In addition the caller might have made a typo (the access in made via a .bat file).
>>error C2664: 'NetWkstaGetInfo': cannot convert parameter 1 from 'const unsigned short[11]' to
>>'LPSTR'

Are you on Win9x? Then use

void verifyComputer(void)
{
  WKSTA_INFO_100 w100;
  NetWkstaGetInfo ( _T("\\\\mycomputername"), 100, &w100);
}

>>In case machines are yours, then there is no such problem

And no problem about the WkStaSvc.
Notices there are many considerations when using NetWkstaGetInfo, depending on Operating System and security rights. Read more at:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/netwkstagetinfo.asp
Avatar of HStrix

ASKER

I'm in Win2000 Workstation.
Avatar of HStrix

ASKER

But it is not an MFC application,
it is a console application, it starts with
---
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR        lpCmdLine,
                     int             nCmdShow )
{

    ......

}
>> Notices there are many considerations when using NetWkstaGetInfo, depending on Operating
>>System

The idea is that
a) All users can use infolevel 100
b) If the call is successful, the machine is available.

>> I'm in Win2000 Workstation.

The following compiles just fine:

#include <windows.h>
#include <lm.h>
#include <lmwksta.h>
#include <tchar.h>

#pragma comment ( lib, "netapi32.lib")

void verifyComputer(void)
{
 WKSTA_INFO_100* pw100;
 NetWkstaGetInfo ( _T("\\\\mycomputername"), 100, (LPBYTE*) &pw100);

 NetApiBufferFree ( pw100);
}

int APIENTRY WinMain(HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR        lpCmdLine,
                    int             nCmdShow )
{

   return 0;

}

You need to clarify a few details:

What do you mean by "reachable"?

Some possibilities:

(1)  The DNS name exists

(2)  That IP address responds to "ping".

(3) Some port accepts connections:  Which one? Could be Telnet, www, FTP, Gopher, IRC, DNS, SMB.

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

Note that a lot of computers are behind firewalls, or have ping turned off, specifically to avoid other computers figuring out they are there.

Perhaps if you'd explain exactly what you're trying to do we could suggest something appropriate.

Avatar of HStrix

ASKER

Thanks, now I modified the code to
---
void verifyComputer(void)
{
      DWORD netret;
      LPTSTR pszServerName = NULL;
      pszServerName = (char *)L"\\\\mycomputername"; // result is "\" only
      pszServerName = _T("\\\\mycomputername");        // result is "\\mycomputername"
      WKSTA_INFO_100* pw100;
      //netret = NetWkstaGetInfo ( pszServerName, 100, (LPBYTE *)&pw100);
                netret = NetWkstaGetInfo ( _T("\\\\mhpab5gc"), 100, (LPBYTE *)&pw100);  // it leads to the same result
      if( netret == NERR_Success )  // netret = 53
      {
            strcpy(strComputerVerify,"Host is available");
      } else
      {
            strcpy(strComputerVerify,"Host not found");
      }
      NetApiBufferFree ( pw100);
}
---
It compiles error free, but the execution gives code 53.

If I use
--
pszServerName = (char *)L"\\\\mycomputername"; // result is "\" only
//netret = NetWkstaGetInfo ( pszServerName, 100, (LPBYTE *)&pw100);
---
then I get netret=0, but is this OK for the contents of pszServerName?

For testing I use the computername I'm running on,
so I'm sure that it is OK.

If I use
--
pszServerName = (char *)L"\\\\mycomputernameX"; // result is "\" only but "mycomputernameX" is unknown
//netret = NetWkstaGetInfo ( pszServerName, 100, (LPBYTE *)&pw100);
---
then I get netret=53.

>>pszServerName = (char *)L"\\\\mycomputernameX"; // result is "\" only but "mycomputernameX" i

That cannot work (thus the ERROR_BAD_NETPATH). It needs to be UNICODE:

void verifyComputer(char* pszName)
{
WKSTA_INFO_100* pw100;
wchar_t awcName [ MAX_COMPUTERNAME_LENGTH + 1];

wsprintf ( awcName, "%S", pszNme);

NetWkstaGetInfo ( awcName, 100, (LPBYTE*) &pw100);

NetApiBufferFree ( pw100);
}
Avatar of HStrix

ASKER

Here is some more explanation:

The C[++] I'm writing is designed to invoke another program (using ShellExecute)
and then stops working.

The another program is located on a share.
Now I want to check step-by-step
 - of the computer is reachable,
 - then if the share is still available
 - and at last if the program I want to activate is on that share.
And in each case I want to inform the user about the cause of an occured problem.

Everything is already working, if the three checks above are not required.
But I thought, there might be some circumstances, that problems occur.
>>Now I want to check step-by-step
>>- of the computer is reachable,
>>- then if the share is still available

Then, the next step is using 'NetShareGetInfo()'...

>> - and at last if the program I want to activate is on that share.

... followed by 'NetShareAdd()'.

Avatar of HStrix

ASKER

Yes, I wanted to ask appropriate questions in that order.
Avatar of HStrix

ASKER

For the code
---
void verifyComputer(char* pszName)
{
      DWORD netret;
      WKSTA_INFO_100* pw100;
      wchar_t awcName [ MAX_COMPUTERNAME_LENGTH + 1];
 // error C2664: 'wsprintfA': cannot convert parameter 1 from 'const unsigned short[11]' to 'LPSTR'                    occurs for next line:
      wsprintf ( awcName, "%S", pszName);
// error C2664: 'NetWkstaGetInfo': cannot convert parameter 1 from 'const unsigned short[11]' to 'LPSTR'           occurs for next line:            
      NetWkstaGetInfo ( awcName, 100, (LPBYTE*) &pw100);
---
I get above's errors.

I call the routine as follows
---
char *computername = "";
computername= token; // as it is in =>https://www.experts-exchange.com/questions/21137583/VC-read-cmdline-arguments.html
verifyComputer(computername);
---
>> // error C2664: 'wsprintfA':

Ouch :o) - that should be 'wsprintfW()'

Try

#include <windows.h>
#ifndef UNICODE
#define UNICODE
#include <lm.h>
#include <lmwksta.h>
#undef UNICODE
#endif

#pragma comment ( lib, "netapi32.lib")

void verifyComputer(char* pszName)
{
WKSTA_INFO_100* pw100;
wchar_t awcName [ MAX_COMPUTERNAME_LENGTH + 1];

wsprintfW ( awcName, L"%S", pszName);

NetWkstaGetInfo ( awcName, 100, (LPBYTE*) &pw100);

NetApiBufferFree ( pw100);
}
Avatar of HStrix

ASKER

Still I get the following:
---
     WKSTA_INFO_100* pw100;
     wchar_t awcName [ MAX_COMPUTERNAME_LENGTH + 1];
     wsprintfW ( awcName, L"%S", pszName);
// error C2664: 'NetWkstaGetInfo': cannot convert parameter 1 from 'const unsigned short[11]' to 'LPSTR'           occurs for next line:            
     NetWkstaGetInfo ( awcName, 100, (LPBYTE*) &pw100);
---
Avatar of HStrix

ASKER

I changed
   NetWkstaGetInfo ( awcName, 100, (LPBYTE*) &pw100);
to
  netret = NetWkstaGetInfo ( (LPSTR) &awcName, 100, (LPBYTE*) &pw100);
then I get netret=0.
But I'm confused is this OK or not?
'0' is

#define NERR_Success            0       /* Success */

But something is fishy here - could you look up the declaration of 'NetWkstaGetInfo()' in your header file?
Avatar of HStrix

ASKER

OK, I'll check that tomorrow.
On my computer is the environment of .Net 2003 and of the Platform SDK.
Avatar of HStrix

ASKER

Here it is:
---
excerpt from lmwksta.h
---
//
// Function Prototypes
//

NET_API_STATUS NET_API_FUNCTION
NetWkstaGetInfo (
    IN  LMSTR   servername OPTIONAL,
    IN  DWORD   level,
    OUT LPBYTE  *bufptr
    );

NET_API_STATUS NET_API_FUNCTION
NetWkstaSetInfo (
    IN  LMSTR   servername OPTIONAL,
    IN  DWORD   level,
    IN  LPBYTE  buffer,
    OUT LPDWORD parm_err OPTIONAL
    );

NET_API_STATUS NET_API_FUNCTION
NetWkstaUserGetInfo (
    IN  LMSTR  reserved,
    IN  DWORD   level,
    OUT LPBYTE  *bufptr
    );

NET_API_STATUS NET_API_FUNCTION
NetWkstaUserSetInfo (
    IN  LMSTR  reserved,
    IN  DWORD   level,
    OUT LPBYTE  buf,
    OUT LPDWORD parm_err OPTIONAL
    );

NET_API_STATUS NET_API_FUNCTION
NetWkstaUserEnum (
    IN  LMSTR       servername OPTIONAL,
    IN  DWORD       level,
    OUT LPBYTE      *bufptr,
    IN  DWORD       prefmaxlen,
    OUT LPDWORD     entriesread,
    OUT LPDWORD     totalentries,
    IN  OUT LPDWORD resumehandle OPTIONAL
    );
---
Hmm, the part of interest now would be the typedef for 'LMSTR'...
Avatar of HStrix

ASKER

Here it is:
---
excerpt from lmcons.h
---
//
// Only the UNICODE version of the LM APIs are available on NT.
// Non-UNICODE version on other platforms
//
#if defined( _WIN32_WINNT ) || defined( WINNT ) || defined( __midl ) \
    || defined( FORCE_UNICODE )
#define LMSTR   LPWSTR
#define LMCSTR  LPCWSTR
#else
#define LMSTR   LPSTR
#define LMCSTR  LPCSTR
#endif
---
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany 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
Avatar of HStrix

ASKER

and follow up ...

excerpt from mapinls.h (appears first in the dropdownlist referring to definition)
---
typedef CHAR FAR *                                    LPSTR;
---

excerpt from winnt.h (appears secondly in the dropdownlist)
---
typedef CHAR *LPSTR, *PSTR;
---
Avatar of HStrix

ASKER

I tested it and it works as expected.
To get this solution some very special know-how seems to be required.
But as you know this was not your first help for me.

Thank you jkr very much for your great help!

    HStrix
>>To get this solution some very special know-how seems to be required.

Actually, some experience with MS' poorly doumented network APIs helps also :o)

Great that it finally worked.