-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathGetServices.ps1
101 lines (92 loc) · 3.4 KB
/
GetServices.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# Get protocols from "services" file
#
# usage:
# to be sourced in powershell (:> . GetServices.ps1)
#
function Get-Protocol
{
# CmdletBinding points to a parameter set with no parameters, 'All'.
# Using this trick, it's possible to have a good default behavior with
# no parameters without complex parameter guessing logic
[CmdletBinding(DefaultParameterSetName='All')]
param(
# Get a named protocol
[Parameter(Mandatory=$true, Position='0', ValueFromPipelineByPropertyName=$true, ParameterSetName='SpecificProtocols')]
[Alias('Name')]
[String[]]$Protocol,
# Get protocols on a port
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName='SpecificPorts')]
[int[]]$Port,
# Only return TCP protocols
[switch]$OnlyTCP,
# Only return UDP protocols
[switch]$OnlyUDP
)
#region Parse Services File
begin {
$servicesFilePath = "$env:windir\System32\drivers\etc\services"
# <service name> <port number>/<protocol> [aliases...] [#<comment>]
$lines = [IO.File]::ReadAllText("$env:windir\System32\drivers\etc\services") -split
# filter out all comment lines
([Environment]::NewLine) -notlike "#*"
$protocols = foreach ($line in $lines)
{
# not empty lines
if (-not $line) { continue }
# split lines into name, port+proto, alias+comment
$serviceName, $portAndProtocol, $aliasesAndComments = $line.Split(' ', [StringSplitOptions]'RemoveEmptyEntries')
# split port+proto into port, proto
$portNumber, $protocolName = $portAndProtocol.Split("/")
# filter alias+comment into alias
$aliases = @($aliasesAndComments) -notlike "#*"
# filter alias+comment into comment
$comments = @($aliasesAndComments) -like "#*"
# combine them in a PSObject
$result = New-Object PSObject -Property @{
ServiceName = $serviceName
Port = $portNumber
Protocol = $protocolName
Aliases = $aliases
Comments = $comments
}
# hidden typename to make formatting work
$result.PSObject.TypeNames.add("Network.Protocol")
$result
}
}
#endregion
#region Process Input
process {
$filter = $null
if ($OnlyTCP) {
$filter = { $_.Protocol -eq 'TCP' }
} elseif ($OnlyUDP) {
$filter = { $_.Protocol -eq 'UDP' }
}
# By checking to see if the filter is defined,
# we can save time and not filter
if ($Filter) {
$filtererdProtocols = $protocols | Where-Object $filter
} else {
$filtererdProtocols = $protocols
}
# If the Parameter Set is "All", we output all of the protocols
if ($psCmdlet.ParameterSetName -eq 'All')
{
Write-Output $filtererdProtocols
} elseif ($psCmdlet.ParameterSetName -eq 'SpecificPorts') {
# Otherwise, if we're looking for ports, we add another Where-Object
# to find ports, and output that.
$filtererdProtocols | Where-Object {
$Port -contains $_.Port
} | Write-Output
} elseif ($psCmdlet.ParameterSetName -eq 'SpecificProtocols') {
# Otherwise, if we're looking for protcols, we add another Where-Object
# to find ports, and output that.
$filtererdProtocols | Where-Object {
$Protocol -contains $_.ServiceName
}| Write-Output
}
}
#endregion
}