WinLLDPService
WinLLDPService is free, open source and tiny Windows service. It sends Windows’ machine network information via LLDP so that network administrators can find computers with ease. See also SNMP as it’s often used to gather more detailed information from network devices.
WinLLDPService acts only as an announcer to the switch (sends packets to the switch). It will not query switches’ internal LLDP data.
Possible errors are logged to Windows Event Log.
Report possible bugs and feature requests to issues page.
Requirements:
Download from GitHub
Sources can be found at GitHub.
See GitHub Releases page for downloads if list above failed to load.
Install with Chocolatey
choco install winlldpservice
See chocolatey site for additional information.
Screenshots
Tested with
- Windows Server 2012 R2
- Windows 10 Professional edition 64 bit
- Windows 7 Ultimate edition 64 bit with Service Pack 1
- Windows 7 Professional edition 64 bit with Service Pack 1
Configuring
WinLLDPService uses PowerShell for it’s configuration. PowerShell was chosen so that system administrators can add only the needed information. You must set PowerShell execution policy accordingly. See About Execution Policies @ Microsoft. Recommended ExecutionPolicy is AllSigned
. See Help about_signing
for how to sign PowerShell scripts.
Search paths are:
$Env:APPDATA\WinLLDPService\
$Env:LOCALAPPDATA\WinLLDPService\
- Registry:
HKLM:Software\WinLLDPService
InstallPath
value. - Current directory of WinLLDPService.exe
These are translated to:
C:\WINDOWS\system32\config\systemprofile\AppData\Local\WinLLDPService\
C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\WinLLDPService\
C:\Program Files\WinLLDPService\
(default install path x64)C:\Program Files (x86)\WinLLDPService\
(default install path x86)
Filenames that are searched:
Configuration.ps1
Configuration.default.ps1
If Configuration.ps1
is not found then Configuration.default.ps1
is used.
The search is run once after service starts. To rescan paths simply restart the service.
The configuration file is run each time before packet is sent.
Example deployment
There are 10 machines. Every machine has $Env:LOCALAPPDATA\WinLLDPService\Configuration.default.ps1
. Let’s say 3 are virtual machines. For those machines you could create $Env:LOCALAPPDATA\WinLLDPService\Configuration.ps1
which reports additional information.
Writing configuration
You can test the configuration generation from PowerShell by simply opening PowerShell prompt. This allows using Tab for code completion.
PS C:\Users\raspi> Add-Type -Path 'C:\Program Files\WinLLDPService\LLDPBase.dll'
PS C:\Users\raspi> $config = New-Object WinLLDPService.Configuration
PS C:\Users\raspi> $config
Separator : |
ChassisType : MacAddress
PortDescription : {}
SystemName : HASTUR
SystemDescription : {}
PS C:\Users\raspi> $config.PortDescription.Add("test")
PS C:\Users\raspi> $config
Separator : |
ChassisType : MacAddress
PortDescription : {test}
SystemName : HASTUR
SystemDescription : {}
PS C:\Users\raspi> $config.ToString()
WinLLDPService.Configuration
Chassis type: 'MacAddress'
System name: 'MYPC'
Port description: 'test'
System description: ''
Example configuration file
To make your own custom configuration simply copy the Configuration.default.ps1
to one of the directories mentioned above. Do not modify the installed Configuration.default.ps1
as it may change when new version is released.
For information how to get details about machine see PowerShell Documentation.
Example C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\WinLLDPService\Configuration.ps1
:
# Fetch system specific information
# -- Get Operating system name such as "Win 10 Pro"
$replaceTable = @{
"Microsoft" = ""
"Windows" = "Win"
"Professional" = "Pro"
"Ultimate" = "Ult"
"Enterprise" = "Ent"
"Edition" = "Ed"
"Service Pack" = "SP"
}
$operatingsystem = (Get-WmiObject Caption -Class Win32_OperatingSystem | Select-Object -ExpandProperty Caption)
$replaceTable.GetEnumerator() | ForEach-Object {
$operatingsystem = $operatingsystem -replace $_.Key, $_.Value
}
$operatingsystem = $operatingsystem.Trim()
# -- Get serial number
$serialnumber = (Get-WmiObject SerialNumber -Class Win32_bios | Select-Object -ExpandProperty SerialNumber)
# -- Get processor ID
$processorid = (Get-WmiObject ProcessorId -Class Win32_Processor | Select-Object -ExpandProperty ProcessorId)
# -- Get logged in user list (not recommended for LLDP, see SNMP)
$explorerprocesses = @(Get-WmiObject -Query "SELECT * FROM Win32_Process WHERE Name='explorer.exe'" -ErrorAction SilentlyContinue)
$logged_in_users_list = @{}
if ($explorerprocesses.Count -ne 0)
{
foreach ($i in $explorerprocesses)
{
$username = $i.GetOwner().User
$domain = $i.GetOwner().Domain.ToLower()
if(!$logged_in_users_list.ContainsKey($domain)) {
$logged_in_users_list.Add($domain, $username)
}
}
}
# change to <domain>: user1, user2, ..
$logged_in_users_list = $logged_in_users_list | Sort-Object
$logged_in_users = ""
foreach($dom in $logged_in_users_list.KEYS.GetEnumerator()) {
$logged_in_users += $dom + ": "
foreach($user in $logged_in_users_list[$dom]) {
$logged_in_users += $user + ", "
}
}
$logged_in_users = $logged_in_users.Trim().TrimEnd(',')
# -- Get uptime (not recommended for LLDP, see SNMP)
$up = (Get-Date) - [Management.ManagementDateTimeConverter]::ToDateTime((Get-WmiObject LastBootUpTime -Class Win32_OperatingSystem).LastBootUpTime)
# change to XXXdXXhXXmXXs
$uptime = "{0:D3}d{1:D2}h{2:D2}m{3:D2}s" -f $up.Days, $up.Hours, $up.Minutes, $up.Seconds
# Initialize WinLLDPService.Configuration object
$config = New-Object WinLLDPService.Configuration
$config.PortDescription.Add("my new port descr..")
# Add operating system
$config.SystemDescription.Add("OS: " + $operatingsystem)
# Add serial number
$config.SystemDescription.Add("SN: " + $serialnumber)
# Add processor ID
$config.SystemDescription.Add("ID: " + $processorid)
# Add users logged in
$config.SystemDescription.Add("U: " + $logged_in_users_list)
# Add uptime
$config.SystemDescription.Add("Up: " + $uptime)
$config.SystemName.Add("my machine")
$config.Separator = "|"
# Must always return WinLLDPService.Configuration object
Return $config
It is recommended to use PowerShell modules and caching non-realtime information such as operating system name.
So the above script becomes something like this with modules:
Import-Module MyCustomModule
Import-Module MyCustomModuleOther
# Initialize WinLLDPService.Configuration object
$config = New-Object WinLLDPService.Configuration
$config.PortDescription.Add("my new port descr..")
# Add operating system
$config.SystemDescription.Add(Get-OperatingSystem)
# Add serial number
$config.SystemDescription.Add(Get-SerialNumber)
# Add processor ID
$config.SystemDescription.Add(Get-ProcessorId)
# Add users logged in
$config.SystemDescription.Add(Get-LoggedInUsers)
# Add uptime
$config.SystemDescription.Add(Get-Uptime)
$config.SystemName.Add("my machine")
$config.Separator = "|"
# Must always return WinLLDPService.Configuration object
Return $config
This way you can simply just update the module(s)/script(s) and keep the configuration file the same for all machines.