Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 827
  • Last Modified:

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

0
HStrix
Asked:
HStrix
  • 19
  • 12
  • 6
  • +1
1 Solution
 
Jaime OlivaresSoftware ArchitectCommented:
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.
0
 
Jaime OlivaresSoftware ArchitectCommented:
Also, take a look to this article about pinging in Windows:
http://www.codeproject.com/internet/winping.asp
0
 
HStrixAuthor Commented:
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?
0
A proven path to a career in data science

At Springboard, we know how to get you a job in data science. With Springboard’s Data Science Career Track, you’ll master data science  with a curriculum built by industry experts. You’ll work on real projects, and get 1-on-1 mentorship from a data scientist.

 
Jaime OlivaresSoftware ArchitectCommented:
Just need this:

     hostent* remoteHost;
     char* host_name;
     unsigned int addr;
     host_name = "mycomputername";
     // now you can call your function      
0
 
HStrixAuthor Commented:
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?
0
 
Jaime OlivaresSoftware ArchitectCommented:
You have commented the most important line:
addr = inet_addr(host_name);
0
 
HStrixAuthor Commented:
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...
0
 
jkrCommented:
'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.
0
 
HStrixAuthor Commented:
Thank you jkr,
what .h file and which .lib file do I need?
I added netapi32.lib, but I miss something.
0
 
jkrCommented:
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".
0
 
HStrixAuthor Commented:
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);
}
---
0
 
Jaime OlivaresSoftware ArchitectCommented:
>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
0
 
HStrixAuthor Commented:
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).
0
 
jkrCommented:
>>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);
}

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

And no problem about the WkStaSvc.
0
 
Jaime OlivaresSoftware ArchitectCommented:
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
0
 
HStrixAuthor Commented:
I'm in Win2000 Workstation.
0
 
HStrixAuthor Commented:
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 )
{

    ......

}
0
 
jkrCommented:
>> 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;

}

0
 
grg99Commented:
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.

0
 
HStrixAuthor Commented:
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.

0
 
jkrCommented:
>>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);
}
0
 
HStrixAuthor Commented:
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.
0
 
jkrCommented:
>>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()'.

0
 
HStrixAuthor Commented:
Yes, I wanted to ask appropriate questions in that order.
0
 
HStrixAuthor Commented:
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 =>http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_21137583.html
verifyComputer(computername);
---
0
 
jkrCommented:
>> // 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);
}
0
 
HStrixAuthor Commented:
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);
---
0
 
HStrixAuthor Commented:
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
 
jkrCommented:
'0' is

#define NERR_Success            0       /* Success */

But something is fishy here - could you look up the declaration of 'NetWkstaGetInfo()' in your header file?
0
 
HStrixAuthor Commented:
OK, I'll check that tomorrow.
On my computer is the environment of .Net 2003 and of the Platform SDK.
0
 
HStrixAuthor Commented:
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
    );
---
0
 
jkrCommented:
Hmm, the part of interest now would be the typedef for 'LMSTR'...
0
 
HStrixAuthor Commented:
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
---
0
 
jkrCommented:
Ah, here we have it :o)

Then, that should be

Try

#include <windows.h>
#define FORCE_UNICODE
#include <lm.h>
#include <lmwksta.h>

#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);
}

Actually, _WIN32_WINNT or WINNT  should be defined somewhere, though...
0
 
HStrixAuthor Commented:
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;
---
0
 
HStrixAuthor Commented:
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
0
 
jkrCommented:
>>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.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Easily Design & Build Your Next Website

Squarespace’s all-in-one platform gives you everything you need to express yourself creatively online, whether it is with a domain, website, or online store. Get started with your free trial today, and when ready, take 10% off your first purchase with offer code 'EXPERTS'.

  • 19
  • 12
  • 6
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now