2006. január 4., szerda

Get MAC Address of Remote or Local Machine

Problem/Question/Abstract:

Function to return the MAC address of a remote or local machine in the format 'XX-XX-XX-XX-XX-XX'

The returned MAC address is a Unique ID that can be used in various ways. One way is as a parameter to my Wake On Lan function.(See article "Implementation of Wake On Lan procedure")

Example :

ShowMessage(GetMacAddress('\\MHEYDON');

Output = '00-02-08-E7-99-6B'

Answer:

// ======================================================================
// Return the MAC address of Machine identified by AServerName
// Format of AServerName is '\\ServerName' or 'ServerName'
// If AServerName is a Null String then local machine MAC address
// is returned.
// Return string is in format 'XX-XX-XX-XX-XX-XX'
// ======================================================================

function GetMacAddress(const AServerName: string): string;
type
TNetTransportEnum = function(pszServer: PWideChar;
Level: DWORD;
var pbBuffer: pointer;
PrefMaxLen: LongInt;
var EntriesRead: DWORD;
var TotalEntries: DWORD;
var ResumeHandle: DWORD): DWORD; stdcall;

TNetApiBufferFree = function(Buffer: pointer): DWORD; stdcall;

PTransportInfo = ^TTransportInfo;
TTransportInfo = record
quality_of_service: DWORD;
number_of_vcs: DWORD;
transport_name: PWChar;
transport_address: PWChar;
wan_ish: boolean;
end;

var
E, ResumeHandle,
EntriesRead,
TotalEntries: DWORD;
FLibHandle: THandle;
sMachineName,
sMacAddr,
Retvar: string;
pBuffer: pointer;
pInfo: PTransportInfo;
FNetTransportEnum: TNetTransportEnum;
FNetApiBufferFree: TNetApiBufferFree;
pszServer: array[0..128] of WideChar;
i, ii, iIdx: integer;
begin
sMachineName := trim(AServerName);
Retvar := '00-00-00-00-00-00';

// Add leading \\ if missing
if (sMachineName <> '') and (length(sMachineName) >= 2) then
begin
if copy(sMachineName, 1, 2) <> '\\' then
sMachineName := '\\' + sMachineName
end;

// Setup and load from DLL
pBuffer := nil;
ResumeHandle := 0;
FLibHandle := LoadLibrary('NETAPI32.DLL');

// Execute the external function
if FLibHandle <> 0 then
begin
@FNetTransportEnum := GetProcAddress(FLibHandle, 'NetWkstaTransportEnum');
@FNetApiBufferFree := GetProcAddress(FLibHandle, 'NetApiBufferFree');
E := FNetTransportEnum(StringToWideChar(sMachineName, pszServer, 129), 0,
pBuffer, -1, EntriesRead, TotalEntries, Resumehandle);

if E = 0 then
begin
pInfo := pBuffer;

// Enumerate all protocols - look for TCPIP
for i := 1 to EntriesRead do
begin
if pos('TCPIP', UpperCase(pInfo^.transport_name)) <> 0 then
begin
// Got It - now format result 'xx-xx-xx-xx-xx-xx'
iIdx := 1;
sMacAddr := pInfo^.transport_address;

for ii := 1 to 12 do
begin
Retvar[iIdx] := sMacAddr[ii];
inc(iIdx);
if iIdx in [3, 6, 9, 12, 15] then
inc(iIdx);
end;
end;

inc(pInfo);
end;
if pBuffer <> nil then
FNetApiBufferFree(pBuffer);
end;

try
FreeLibrary(FLibHandle);
except
// Silent Error
end;
end;

Result := Retvar;
end;


Nincsenek megjegyzések:

Megjegyzés küldése