Posted 21 years ago on 8/5/2004 and updated 1/10/2009
Take Away: Description of technique and sample code for using VFP to access the Win-32 API and return the MAC address of the Network Interface Card (NIC.
Windows Win-32 API contains many methods to glean information about the computer currently running the Windows operating system. Although Microsoft’s Visual FoxPro (VFP) has the capability of using these methods to access system information, most of the published routines to accomplish these tasks are for other languages (such as C++) and require conversion by someone literate in both languages to be useful to the VFP programmer.
In this series of articles, we will examine specific techniques and provide code samples for the VFP programmer to use to access the Windows API for some important tasks.
A sample need for system information is a requirement to uniquely identify a specific computer, for example to create a license “key†that will only work on a specific known system to allow use of a software product. This can be accomplished by reading the ID information on the system’s network interface card (NIC). Since every NIC in the world has a different unique ID number, this ID can be used to uniquely identify a specific machine. The NIC ID is also referred to as the “physical address†or the Media Access Control (MAC) address of the network card.
While the number can change for a specific machine by swapping out the NIC, this is not a common event, and for most purposes the NIC ID uniquely identifies a specific machine. Obviously, this technique will not work for machines not equipped with a NIC, but these are not common, especially in the business world.
Windows API (specifically IPHLPAPI.DLL) provides a method for accessing the NIC ID number, along with quite a bit of other related information if needed. This is the GetAdaptorsInfo method which works for all current versions of Windows (95/98/Me/NT/2000/XP) [update: WinNT has been shown to be incompatible with this API call. See http://www.pcausa.com/Utilities/macaddr2.htm for other techniques for obtaining this info in an NT system.].
The NIC MAC or ID is expressed as a sequence of 6 byte values, i.e. numbers between 0-255 (in decimal notation). Byte values are often expressed in hexadecimal notation since only 2 hex digits are required to express the value range 0-255. Hexadecimal notation is used to describe the NIC ID by the Windows IPCONFIG utility: try typing IPCONFIG /ALL at the command line to see the 6-byte NIC “physical address†number on your own machine expressed as hexadecimal notation.
Whether expressed as binary, hexadecimal or decimal, it is important to recognize that ultimately, the NIC ID is composed of 6 numbers each in the range of 0-255. When the GetAdaptorsInfo method returns the ID it will return 6 separate numbers (as individual characters). Of course, there is another system of encoding, very commonly used in computer systems, that represents a number in the same range as byte values as a single character. This is the ASCII (American Standard Code for Information Interchange) code that defines alphanumeric characters, such as the letters and numerals in this document, among others. Since the GetAdaptorsInfo method returns the NIC ID as a character string, each individual returned character’s ASCII value is equal to the numeric value of each of the NIC ID’s byte values.
The following sample code will display the NIC ID for the machine on which it is run in both decimal and hexadecimal notation.
* GetNicID - uses Win-32 API call to get NIC ID (physical address)
* this is the DLL declaration to access the API method
DECLARE INTEGER GetAdaptersInfo IN iphlpapi ;
STRING @pAdapterInfo, LONG @pOutBufLen
LOCAL lcBuffer, lnBufsize
lnBufsize = 0
lcBuffer = ""
* first call to GetAdaptorsInfo() method
* this call usually returns: ERROR_BUFFER_OVERFLOW (111)
* with lnBufsize set to the required amount of memory
= GetAdaptersInfo(@lcBuffer, @lnBufsize)
* build buffer string from nulls
lcBuffer = Repli(Chr(0), lnBufsize)
* call method again
IF GetAdaptersInfo(@lcBuffer, @lnBufsize) <> 0 && ERROR_SUCCESS
* no joy
=MESSAGEBOX('WinAPI problem - GetAdaptorsInfo')
RETURN
ENDIF
LOCAL lnAddrlen, lcAddress, ii
* 401st byte of lcBuffer is size of NIC address string
lnAddrlen = Asc(SUBSTR(lcBuffer, 401, 1))
* actual NIC address starts at byte 405 of lcBuffer
lcAddress = SUBSTR(lcBuffer, 405, lnAddrlen)
* build decimal and hex strings from ASCII values of returned characters
lcThisID = ''
lcThisHex = ''
FOR ii = 1 TO lnAddrLen
lcThisID = lcThisID + ;
IIF(ii>1,',','') + ;
ALLTRIM(STR(ASC(SUBSTR(lcAddress,ii,1))))
lcThisHex = lcThisHex + ;
IIF(ii>1,'-','') + ;
RIGHT(TRANSFORM(ASC(SUBSTR(lcAddress,ii,1)),'@0'),2)
NEXT
* display decimal and hex versions of NIC ID
?
? 'NIC ID (decimal): '+lcThisID
? 'NIC ID (hex): '+ lcThisHex
For information on the other information returned by the GetAdaptorsInfo API call (Name, Desc, IP, Index, Type, Gateway, DHCPON, DHCPServer), see Rob444 on tek-tips.com Jan 16, 2003: