The Network List Manager (NLM) API (introduced on Windows Vista) allows you to retrieve a list of available connections and properties of each network .Also the NLM API support notifications (events) about the availability of new network connections or changes to existing network connections. This API is useful for filter networks, based on his attributes and signatures. Also you can use this API in your own Application to adjust their logic depending on: which network they are connected to; or what the network properties are.
Ok, So the first step to use this API from Delphi is import the Network List Manager Type Library (C:\WINDOWS\system32\netprofm.dll) from the option Component-> Import Component as is show below.


After of this the NETWORKLIST_TLB unit will be created containing all the Interfaces, Types and Enumerations of the NLM API.
Note: Depending of your Windows version the content of the imported type library can change, because some additional Interfaces and types was added in Windows 8.
INetworkListManager
The INetworkListManager is the main interface to access the methods to perform NLM API functions Like enumerate Networks, Connections and check the overall connectivity state of the current machine.
This is the definition of the INetworkListManager interface.
INetworkListManager = interface(IDispatch)
['{DCB00000-570F-4A9B-8D69-199FDBA5723B}']
function GetNetworks(Flags: NLM_ENUM_NETWORK): IEnumNetworks; safecall;
function GetNetwork(gdNetworkId: TGUID): INetwork; safecall;
function GetNetworkConnections: IEnumNetworkConnections; safecall;
function GetNetworkConnection(gdNetworkConnectionId: TGUID): INetworkConnection; safecall;
function Get_IsConnectedToInternet: WordBool; safecall;
function Get_IsConnected: WordBool; safecall;
function GetConnectivity: NLM_CONNECTIVITY; safecall;
procedure SetSimulatedProfileInfo(var pSimulatedInfo: NLM_SIMULATED_PROFILE_INFO); safecall; //Introduced on Windows 8.1
procedure ClearSimulatedProfileInfo; safecall; //Introduced on Windows 8.1
property IsConnectedToInternet: WordBool read Get_IsConnectedToInternet;
property IsConnected: WordBool read Get_IsConnected;
end;
In order to access to this interface you must declare a INetworkListManager variable and call the CoNetworkListManager.Create; method to get an instance to such Interface.
Check the next sample console application which shows the current connectivity of the machine and if the internet connection is available.
{$APPTYPE CONSOLE}
uses
SysUtils,
ActiveX,
ComObj,
Windows,
NETWORKLIST_TLB in 'NETWORKLIST_TLB.pas';
//https://msdn.microsoft.com/en-us/library/windows/desktop/aa370795(v=vs.85).aspx
function GetNetworkConnectivity(Connectivity : NLM_CONNECTIVITY) : string;
begin
Result:='';
if NLM_CONNECTIVITY_DISCONNECTED and Connectivity <> 0 then Result := Result+ 'Disconnected, ';
if NLM_CONNECTIVITY_IPV4_NOTRAFFIC and Connectivity <> 0 then Result := Result+ 'Connected but not ipv4 traffic, ';
if NLM_CONNECTIVITY_IPV6_NOTRAFFIC and Connectivity <> 0 then Result := Result+ 'Connected but not ipv6 traffic, ';
if NLM_CONNECTIVITY_IPV4_SUBNET and Connectivity <> 0 then Result := Result+ 'Subnet ipv4, ';
if NLM_CONNECTIVITY_IPV4_LOCALNETWORK and Connectivity <> 0 then Result := Result+ 'LocalNetwork ipv4, ';
if NLM_CONNECTIVITY_IPV4_INTERNET and Connectivity <> 0 then Result := Result+ 'Internet ipv4, ';
if NLM_CONNECTIVITY_IPV6_SUBNET and Connectivity <> 0 then Result := Result+ 'Subnet ipv6, ';
if NLM_CONNECTIVITY_IPV6_LOCALNETWORK and Connectivity <> 0 then Result := Result+ 'LocalNetwork ipv6, ';
if NLM_CONNECTIVITY_IPV6_INTERNET and Connectivity <> 0 then Result := Result+'Internet ipv6, ';
Result:= StringReplace('['+Result+']', ', ]', ']', [rfReplaceAll]);
end;
procedure GetNetworkListManagerInfo;
var
NetworkListManager: INetworkListManager;
begin
NetworkListManager := CoNetworkListManager.Create;
Writeln(Format('Connected : %s', [boolToStr(NetworkListManager.IsConnected, True)]));
Writeln(Format('Internet : %s', [boolToStr(NetworkListManager.IsConnectedToInternet, True)]));
Writeln(Format('Connectivity : %s', [GetNetworkConnectivity(NetworkListManager.GetConnectivity)]));
end;
begin
try
//Check is Windows Vista at least
if TOSVersion.Check(6) then
begin
CoInitialize(nil);
try
GetNetworkListManagerInfo;
finally
CoUninitialize;
end;
end
else
Writeln('This windows version doesn''t support the NLM API');
except
on E:EOleException do
Writeln(Format('EOleException %s %x', [E.Message, E.ErrorCode]));
on E:Exception do
Writeln(E.Classname, ':', E.Message);
end;
Writeln('Press Enter to exit');
Readln;
end.
Enumerating Connections
The NLM API allow you to enumerate network connections using the INetworkListManager.GetNetworkConnections method, this function returns an instance to the IEnumNetworkConnections interface that enumerates all network connections on the machine, each element returned by the IEnumNetworkConnections.Next method represents a INetworkConnection object.
INetworkConnection = interface(IDispatch)
['{DCB00005-570F-4A9B-8D69-199FDBA5723B}']
function GetNetwork: INetwork; safecall;
function Get_IsConnectedToInternet: WordBool; safecall;
function Get_IsConnected: WordBool; safecall;
function GetConnectivity: NLM_CONNECTIVITY; safecall;
function GetConnectionId: TGUID; safecall;
function GetAdapterId: TGUID; safecall;
function GetDomainType: NLM_DOMAIN_TYPE; safecall;
property IsConnectedToInternet: WordBool read Get_IsConnectedToInternet;
property IsConnected: WordBool read Get_IsConnected;
end;
Check the next sample console application which shows how enumerate the connections with his connectivity, domain type, network adapters associated and so on.
{$APPTYPE CONSOLE}
uses
SysUtils,
ActiveX,
ComObj,
Windows,
NETWORKLIST_TLB in 'NETWORKLIST_TLB.pas';
//https://msdn.microsoft.com/en-us/library/windows/desktop/aa370796(v=vs.85).aspx
function GetNetworkDomainType(DomainType : NLM_DOMAIN_TYPE) : string;
begin
Result:='';
case DomainType of
NLM_DOMAIN_TYPE_NON_DOMAIN_NETWORK : Result := 'Non Domain Network'; //The Network is not an Active Directory Network
NLM_DOMAIN_TYPE_DOMAIN_NETWORK : Result := 'Domain Network';//The Network is an Active Directory Network, but this machine is not authenticated against it.
NLM_DOMAIN_TYPE_DOMAIN_AUTHENTICATED : Result := 'Domain Network Authenticated';//The Network is an Active Directory Network, and this machine is authenticated against it.
end;
end;
//https://msdn.microsoft.com/en-us/library/windows/desktop/aa370795(v=vs.85).aspx
function GetNetworkConnectivity(Connectivity : NLM_CONNECTIVITY) : string;
begin
Result:='';
if NLM_CONNECTIVITY_DISCONNECTED and Connectivity <> 0 then Result := Result+ 'Disconnected, ';
if NLM_CONNECTIVITY_IPV4_NOTRAFFIC and Connectivity <> 0 then Result := Result+ 'Connected but not ipv4 traffic, ';
if NLM_CONNECTIVITY_IPV6_NOTRAFFIC and Connectivity <> 0 then Result := Result+ 'Connected but not ipv6 traffic, ';
if NLM_CONNECTIVITY_IPV4_SUBNET and Connectivity <> 0 then Result := Result+ 'Subnet ipv4, ';
if NLM_CONNECTIVITY_IPV4_LOCALNETWORK and Connectivity <> 0 then Result := Result+ 'LocalNetwork ipv4, ';
if NLM_CONNECTIVITY_IPV4_INTERNET and Connectivity <> 0 then Result := Result+ 'Internet ipv4, ';
if NLM_CONNECTIVITY_IPV6_SUBNET and Connectivity <> 0 then Result := Result+ 'Subnet ipv6, ';
if NLM_CONNECTIVITY_IPV6_LOCALNETWORK and Connectivity <> 0 then Result := Result+ 'LocalNetwork ipv6, ';
if NLM_CONNECTIVITY_IPV6_INTERNET and Connectivity <> 0 then Result := Result+'Internet ipv6, ';
Result:= StringReplace('['+Result+']', ', ]', ']', [rfReplaceAll]);
end;
procedure GetConnections;
var
NetworkListManager: INetworkListManager;
EnumNetworkConnections: IEnumNetworkConnections;
NetworkConnection : INetworkConnection;
pceltFetched: ULONG;
begin
NetworkListManager := CoNetworkListManager.Create;
EnumNetworkConnections := NetworkListManager.GetNetworkConnections();
while true do
begin
EnumNetworkConnections.Next(1, NetworkConnection, pceltFetched);
if (pceltFetched>0) then
begin
Writeln(Format('Adapter Id : %s', [GuidToString(NetworkConnection.GetAdapterId)]));
Writeln(Format('Connection Id : %s', [GuidToString(NetworkConnection.GetConnectionId)]));
Writeln(Format('Domain Type : %s', [GetNetworkDomainType(NetworkConnection.GetDomainType)]));
Writeln(Format('Connected : %s', [boolToStr(NetworkConnection.IsConnected, True)]));
Writeln(Format('Internet : %s', [boolToStr(NetworkConnection.IsConnectedToInternet, True)]));
Writeln(Format('Network : %s', [NetworkConnection.GetNetwork.GetName]));
Writeln(Format('Connectivity : %s', [GetNetworkConnectivity(NetworkConnection.GetConnectivity)]));
end
else
Break;
end;
end;
begin
try
//Check is Windows Vista at least
if TOSVersion.Check(6) then
begin
CoInitialize(nil);
try
GetConnections;
finally
CoUninitialize;
end;
end
else
Writeln('This windows version doesn''t support the NLM API');
except
on E:EOleException do
Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
on E:Exception do
Writeln(E.Classname, ':', E.Message);
end;
Writeln('Press Enter to exit');
Readln;
end.
Enumerating Networks
For enumerate the networks available on the local machine you must use the INetworkListManager.GetNetworks method passing a valid NLM_ENUM_NETWORK value.
- NLM_ENUM_NETWORK_CONNECTED Returns connected networks
- NLM_ENUM_NETWORK_DISCONNECTED Returns disconnected networks
- NLM_ENUM_NETWORK_ALL Returns connected and disconnected networks
from here you can gain access to several elements related to the network like Name, Description, Connectivity, Network Category and the local date and time when the network was created and connected.
Sample code to enumerate the networks using the NLM API
{$APPTYPE CONSOLE}
uses
SysUtils,
ActiveX,
ComObj,
Windows,
NETWORKLIST_TLB in 'NETWORKLIST_TLB.pas';
//https://msdn.microsoft.com/en-us/library/windows/desktop/aa370796(v=vs.85).aspx
function GetNetworkDomainType(DomainType : NLM_CONNECTIVITY) : string;
begin
Result:='';
case DomainType of
NLM_DOMAIN_TYPE_NON_DOMAIN_NETWORK : Result := 'Non Domain Network'; //The Network is not an Active Directory Network
NLM_DOMAIN_TYPE_DOMAIN_NETWORK : Result := 'Domain Network';//The Network is an Active Directory Network, but this machine is not authenticated against it.
NLM_DOMAIN_TYPE_DOMAIN_AUTHENTICATED : Result := 'Domain Network Authenticated';//The Network is an Active Directory Network, and this machine is authenticated against it.
end;
end;
function GetNetworkCategory(Category : NLM_NETWORK_CATEGORY) : string;
begin
Result:='';
case Category of
NLM_NETWORK_CATEGORY_PUBLIC : Result := 'Public';
NLM_NETWORK_CATEGORY_PRIVATE : Result := 'Private';
NLM_NETWORK_CATEGORY_DOMAIN_AUTHENTICATED : Result := 'Authenticated';
end;
end;
procedure GetNetworks;
var
NetworkListManager: INetworkListManager;
EnumNetworks: IEnumNetworks;
EnumNetworksConnections: IEnumNetworkConnections;
NetworkConnection : INetworkConnection;
Network: INetwork;
fetched, pceltFetched: ULONG;
pdwLowDateTimeCreated: LongWord;
pdwHighDateTimeCreated: LongWord;
pdwLowDateTimeConnected: LongWord;
pdwHighDateTimeConnected: LongWord;
lpFileTime : TFileTime;
lpSystemTime: TSystemTime;
LDateTime : TDateTime;
begin
NetworkListManager := CoNetworkListManager.Create;
EnumNetworks := NetworkListManager.GetNetworks(NLM_ENUM_NETWORK_CONNECTED);
while true do
begin
EnumNetworks.Next(1, Network, fetched);
if (fetched>0) then
begin
Writeln(Format('%s - %s', [Network.GetName, Network.GetDescription]));
Writeln(Format('Network Id : %s', [GuidToString(Network.GetNetworkId)]));
Writeln(Format('Domain Type : %s', [GetNetworkDomainType(Network.GetDomainType)]));
Writeln(Format('Category : %s', [GetNetworkCategory(Network.GetCategory)]));
//https://msdn.microsoft.com/en-us/library/windows/desktop/aa370787(v=vs.85).aspx
Network.GetTimeCreatedAndConnected(pdwLowDateTimeCreated, pdwHighDateTimeCreated, pdwLowDateTimeConnected, pdwHighDateTimeConnected);
lpFileTime.dwLowDateTime := pdwLowDateTimeCreated;
lpFileTime.dwHighDateTime := pdwHighDateTimeCreated;
if FileTimeToSystemTime(lpFileTime, lpSystemTime) then
begin
LDateTime := SystemTimeToDateTime(lpSystemTime);
Writeln('Created : '+FormatDateTime('dd/mm/yyyy hh:nn', LDateTime));
end;
lpFileTime.dwLowDateTime := pdwLowDateTimeConnected;
lpFileTime.dwHighDateTime := pdwHighDateTimeConnected;
if FileTimeToSystemTime(lpFileTime, lpSystemTime) then
begin
LDateTime := SystemTimeToDateTime(lpSystemTime);
Writeln('Last Connection : '+FormatDateTime('dd/mm/yyyy hh:nn', LDateTime));
end;
Writeln(Format('Connected : %s', [boolToStr(Network.IsConnected, True)]));
Writeln(Format('Internet : %s', [boolToStr(Network.IsConnectedToInternet, True)]));
EnumNetworksConnections := Network.GetNetworkConnections();
Writeln;
Writeln('Connections');
Writeln('-----------');
while true do
begin
EnumNetworksConnections.Next(1, NetworkConnection, pceltFetched);
if (pceltFetched>0) then
begin
Writeln(Format(' Adapter Id : %s', [GuidToString(NetworkConnection.GetAdapterId)]));
Writeln(Format(' Connection Id : %s', [GuidToString(NetworkConnection.GetConnectionId)]));
end
else
break;
end;
Writeln;
end
else
Break;
end;
end;
begin
try
//Check is Windows Vista at least
if TOSVersion.Check(6) then
begin
CoInitialize(nil);
try
GetNetworks;
finally
CoUninitialize;
end;
end
else
Writeln('This windows version doesn''t support the NLM API');
except
on E:EOleException do
Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
on E:Exception do
Writeln(E.Classname, ':', E.Message);
end;
Writeln('Press Enter to exit');
Readln;
end.
Events
The NML API exposes several events (notifications) that you Application must implements to get network related events. These callback functions that are called automatically when the respective events are raised.
These are the notifications interfaces available on the NLM API
Note : The next sample shows how subscribe to the INetworkEvents only. I will leave it as reader’s exercise the implementation of the another events.
The INetworkEvents interface can inform when a Network was added, deleted or modified. To receive the notifications related to these events you must inherit a class from this interface and implement the next methods.
INetworkEvents = interface(IUnknown)
['{DCB00004-570F-4A9B-8D69-199FDBA5723B}']
function NetworkAdded(networkId: TGUID): HResult; stdcall;
function NetworkDeleted(networkId: TGUID): HResult; stdcall;
function NetworkConnectivityChanged(networkId: TGUID; newConnectivity: NLM_CONNECTIVITY): HResult; stdcall;
function NetworkPropertyChanged(networkId: TGUID; Flags: NLM_NETWORK_PROPERTY_CHANGE): HResult; stdcall;
end;
then you need get an instance to the IConnectionPointContainer interface, after using the IConnectionPointContainer.FindConnectionPoint return a connection point for the interface and finally call the IConnectionPoint.Advise method to establish the connection with the event.
NetworkListManager := CoNetworkListManager.Create;
if Succeeded(NetworkListManager.QueryInterface(IID_IConnectionPointContainer, LConnectionPointContainer)) then
if Succeeded(LConnectionPointContainer.FindConnectionPoint(IID_INetworkEvents, LConnectionPoint)) then
LConnectionPoint.Advise(Self as IUnknown, dwCookie);
When you not longer need to use the event, you must to terminate the advisory connection previously established with the connection point using the IConnectionPoint.Unadvise method.
if Succeeded(NetworkListManager.QueryInterface(IID_IConnectionPointContainer, LConnectionPointContainer)) then
if Succeeded(LConnectionPointContainer.FindConnectionPoint(IID_INetworkEvents, LConnectionPoint)) then
begin
LConnectionPoint.Unadvise(dwCookie);
LConnectionPoint := nil;
end;
Check the next sample console application which implements the INetworkEvents interface.
{$APPTYPE CONSOLE}
uses
Winapi.Windows,
{$IF CompilerVersion > 18.5}
Vcl.Forms,
{$IFEND }
System.SysUtils,
Winapi.ActiveX,
System.Win.ComObj,
NETWORKLIST_TLB in 'NETWORKLIST_TLB.pas';
type
TNetworkEvents = class(TInterfacedObject, INetworkEvents)
private
NetworkListManager : INetworkListManager;
dwCookie : Integer;
public
function NetworkAdded(networkId: TGUID): HResult; stdcall;
function NetworkDeleted(networkId: TGUID): HResult; stdcall;
function NetworkConnectivityChanged(networkId: TGUID; newConnectivity: NLM_CONNECTIVITY): HResult; stdcall;
function NetworkPropertyChanged(networkId: TGUID; Flags: NLM_NETWORK_PROPERTY_CHANGE): HResult; stdcall;
constructor Create;
procedure Start;
procedure Stop;
end;
//Detect when a key was pressed in the console window
function KeyPressed:Boolean;
var
lpNumberOfEvents : DWORD;
lpBuffer : TInputRecord;
lpNumberOfEventsRead : DWORD;
nStdHandle : THandle;
begin
Result:=false;
nStdHandle := GetStdHandle(STD_INPUT_HANDLE);
lpNumberOfEvents:=0;
GetNumberOfConsoleInputEvents(nStdHandle, lpNumberOfEvents);
if (lpNumberOfEvents<> 0) then
begin
PeekConsoleInput(nStdHandle, lpBuffer, 1, lpNumberOfEventsRead);
if lpNumberOfEventsRead <> 0 then
begin
if lpBuffer.EventType = KEY_EVENT then
begin
if lpBuffer.Event.KeyEvent.bKeyDown then
Result:=true
else
FlushConsoleInputBuffer(nStdHandle);
end
else
FlushConsoleInputBuffer(nStdHandle);
end;
end;
end;
//https://msdn.microsoft.com/en-us/library/windows/desktop/aa370795(v=vs.85).aspx
function GetNetworkConnectivity(Connectivity : NLM_CONNECTIVITY) : string;
begin
Result:='';
if NLM_CONNECTIVITY_DISCONNECTED and Connectivity <> 0 then Result := Result+ 'Disconnected, ';
if NLM_CONNECTIVITY_IPV4_NOTRAFFIC and Connectivity <> 0 then Result := Result+ 'Connected but not ipv4 traffic, ';
if NLM_CONNECTIVITY_IPV6_NOTRAFFIC and Connectivity <> 0 then Result := Result+ 'Connected but not ipv6 traffic, ';
if NLM_CONNECTIVITY_IPV4_SUBNET and Connectivity <> 0 then Result := Result+ 'Subnet ipv4, ';
if NLM_CONNECTIVITY_IPV4_LOCALNETWORK and Connectivity <> 0 then Result := Result+ 'LocalNetwork ipv4, ';
if NLM_CONNECTIVITY_IPV4_INTERNET and Connectivity <> 0 then Result := Result+ 'Internet ipv4, ';
if NLM_CONNECTIVITY_IPV6_SUBNET and Connectivity <> 0 then Result := Result+ 'Subnet ipv6, ';
if NLM_CONNECTIVITY_IPV6_LOCALNETWORK and Connectivity <> 0 then Result := Result+ 'LocalNetwork ipv6, ';
if NLM_CONNECTIVITY_IPV6_INTERNET and Connectivity <> 0 then Result := Result+'Internet ipv6, ';
Result:= StringReplace('['+Result+']', ', ]', ']', [rfReplaceAll]);
end;
//https://msdn.microsoft.com/en-us/library/windows/desktop/aa370801(v=vs.85).aspx
function GetNetworkPropertyChange(PropertyChange : NLM_NETWORK_PROPERTY_CHANGE) : string;
begin
Result:='';
if NLM_NETWORK_PROPERTY_CHANGE_CONNECTION and PropertyChange <> 0 then Result := Result+ 'Connection, ';
if NLM_NETWORK_PROPERTY_CHANGE_DESCRIPTION and PropertyChange <> 0 then Result := Result+ 'Description, ';
if NLM_NETWORK_PROPERTY_CHANGE_NAME and PropertyChange <> 0 then Result := Result+ 'Name, ';
if NLM_NETWORK_PROPERTY_CHANGE_ICON and PropertyChange <> 0 then Result := Result+ 'Icon, ';
if NLM_NETWORK_PROPERTY_CHANGE_CATEGORY_VALUE and PropertyChange <> 0 then Result := Result+ 'Category value, ';
Result:= StringReplace('['+Result+']', ', ]', ']', [rfReplaceAll]);
end;
{ TNetworkEvents }
const
IID_IConnectionPointContainer: TGUID = (
D1:$B196B284;D2:$BAB4;D3:$101A;D4:($B6,$9C,$00,$AA,$00,$34,$1D,$07));
constructor TNetworkEvents.Create;
begin
dwCookie := 0;
end;
function TNetworkEvents.NetworkAdded(networkId: TGUID): HResult;
begin
Writeln(Format('Network Added : %s', [GuidToString(networkId)]));
Result := S_OK;
end;
function TNetworkEvents.NetworkConnectivityChanged(networkId: TGUID;
NewConnectivity: NLM_CONNECTIVITY): HResult;
begin
Writeln(Format('Network Connectivity Changed : %s - %s', [GuidToString(networkId), GetNetworkConnectivity(NewConnectivity)]));
Result := S_OK;
end;
function TNetworkEvents.NetworkDeleted(networkId: TGUID): HResult;
begin
Writeln(Format('Network Deleted : %s', [GuidToString(networkId)]));
Result := S_OK;
end;
function TNetworkEvents.NetworkPropertyChanged(networkId: TGUID; Flags: NLM_NETWORK_PROPERTY_CHANGE): HResult;
begin
Writeln(Format('Network Property Changed : %s - %s', [GuidToString(networkId), GetNetworkPropertyChange(Flags)]));
Result := S_OK;
end;
procedure TNetworkEvents.Start;
var
LConnectionPointContainer: IConnectionPointContainer;
LConnectionPoint: IConnectionPoint;
begin
if dwCookie > 0 then exit;
NetworkListManager := CoNetworkListManager.Create;
if Succeeded(NetworkListManager.QueryInterface(IID_IConnectionPointContainer, LConnectionPointContainer)) then
begin
if Succeeded(LConnectionPointContainer.FindConnectionPoint(IID_INetworkEvents, LConnectionPoint)) then
begin
LConnectionPoint.Advise(Self as IUnknown, dwCookie);
LConnectionPoint := nil;
end;
end;
end;
procedure TNetworkEvents.Stop;
var
LConnectionPointContainer: IConnectionPointContainer;
LConnectionPoint: IConnectionPoint;
begin
if dwCookie = 0 then exit;
if Succeeded(NetworkListManager.QueryInterface(IID_IConnectionPointContainer, LConnectionPointContainer)) then
if Succeeded(LConnectionPointContainer.FindConnectionPoint(IID_INetworkEvents, LConnectionPoint)) then
begin
LConnectionPoint.Unadvise(dwCookie);
LConnectionPoint := nil;
end;
end;
var
NLMEvents : TNetworkEvents;
begin
try
//Check is Windows Vista at least
if TOSVersion.Check(6) then
begin
NLMEvents:=TNetworkEvents.Create;
try
NLMEvents.Start;
Writeln('Listening NLM events - press any key to stop');
//The next loop is only necessary on this sample console App
//In VCL forms Apps you don't need use a loop
while not KeyPressed do
begin
Sleep(100);
Application.ProcessMessages;
end;
finally
NLMEvents.Stop;
Writeln('NLM events - Done');
end;
end
else
Writeln('This windows version doesn''t support the NLM API');
except
on E:EOleException do
Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
on E:Exception do
Writeln(E.Classname, ':', E.Message);
end;
Readln;
end.
All the source code posted on this article is available on Github.
Rodrigo.