-
Notifications
You must be signed in to change notification settings - Fork 0
/
WmiMacros.fs
251 lines (230 loc) · 11.1 KB
/
WmiMacros.fs
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
namespace Macros
open System
open System.Management
open Microsoft.FSharp.Reflection
open BReusable
open BReusable.StringHelpers
// http://www.iislogs.com/articles/12/
// usage: http://stackoverflow.com/a/26111634/57883
module WmiMacros =
type Win32_Process = {
Caption:string
CommandLine:string
CreationClassName:string
CreationDate:DateTime
CSCreationClassName:string
CSName:string
Description:string
ExecutablePath:string
ExecutionState:UInt16
Handle:string
HandleCount:UInt32
InstallDate:DateTime
KernelModeTime:UInt64
MaximumWorkingSetSize:UInt32
MinimumWorkingSetSize:UInt32
Name:string
OSCreationClassName:string
OSName:string
OtherOperationCount:UInt64
OtherTransferCount:UInt64
PageFaults:UInt32
PageFileUsage:UInt32
ParentProcessId:UInt32
PeakPageFileUsage:UInt32
PeakVirtualSize:UInt64
PeakWorkingSetSize:UInt32
Priority:UInt32
PrivatePageCount:UInt64
ProcessId:UInt32
QuotaNonPagedPoolUsage:UInt32
QuotaPagedPoolUsage:UInt32
QuotaPeakNonPagedPoolUsage:UInt32
QuotaPeakPagedPoolUsage:UInt32
ReadOperationCount:UInt64
ReadTransferCount:UInt64
SessionId:UInt32
Status:string
TerminationDate:DateTime
ThreadCount:UInt32
UserModeTime:UInt64
VirtualSize:UInt64
WindowsVersion:string
WorkingSetSize:UInt64
WriteOperationCount:UInt64
WriteTransferCount:UInt64
}
[<NoComparison>]
type ScopeItem =
| Scope of ManagementScope
| Creation of string*bool*bool
type ProcessDisplay = {
ProcessId: UInt32
ThreadCount: UInt32
AppPool:string
Name:string
Config:string
CreationDate:string
PageFileUsage:string
PeakPageFileUsage:string
VirtualSize:string
PeakVirtualSize:string
PeakWorkingSetSize:string
PrivatePageCount:string
InstallDate:string
}
with static member FromWin32Process (p:Win32_Process) =
// "C:\Windows\SysWOW64\inetsrv\w3wp.exe -ap "MarketOnce.WebApi" -v "v4.0" -l "webengine4.dll" -a \\.\pipe\iisipm31653017-1eb6-4324-8724-afdc023ff248 -h "C:\inetpub\temp\apppools\MarketOnce.WebApi\MarketOnce.WebApi.config" -w "" -m 0";
printfn "cmd: %s" p.CommandLine
let appPool = if p.CommandLine.Contains("-ap ") then p.CommandLine |> after "-ap \"" |> before "\"" else String.Empty
let cleanCommandLine i = i |> after "-h" |> after "\"" |> before "\""
let memoryToUi32 (n:UInt32) =
if n> 2048u then n.ToString("n0")
else string (n / 1024u) + "Kb"
let memoryToUi64 (n:UInt64) =
let kb = n / 1024UL
if kb<2000UL then kb.ToString("n0") + "Kb"
else kb/1024UL |> toFormatString "n0"|>fun x -> x + "Mb"
let cleaned = cleanCommandLine p.CommandLine
{
AppPool = appPool
ProcessDisplay.ProcessId = p.ProcessId
ThreadCount = p.ThreadCount
Name = cleaned |> before ".config" |> afterLast "\\"
Config = p.CommandLine
CreationDate = p.CreationDate.ToString()
PageFileUsage = memoryToUi32 p.PageFileUsage
PeakPageFileUsage = memoryToUi32 p.PeakPageFileUsage
VirtualSize = memoryToUi64 p.VirtualSize
PeakVirtualSize = memoryToUi64 p.PeakVirtualSize
PeakWorkingSetSize = memoryToUi32 p.PeakWorkingSetSize
PrivatePageCount = memoryToUi64 p.PrivatePageCount
InstallDate = if p.InstallDate < DateTime.Now.AddYears -50 then String.Empty else p.InstallDate.ToString()
}
let private createAdvancedScope (path:string) requiresDomainSecurity requiresPacketSecurity =
let scope =
if requiresDomainSecurity then
let conn = ConnectionOptions(Authority=sprintf "ntlmdomain:%s" Environment.UserDomainName)
ManagementScope(path, conn)
else
ManagementScope(path, null)
if requiresPacketSecurity then scope.Options.Authentication <- AuthenticationLevel.PacketPrivacy
scope.Connect()
scope
let private createNamedScope ``namespace`` machineName requiresSecurity =
let path = sprintf "\\\\%s\\%s" machineName ``namespace``
printfn "using path %s" path
createAdvancedScope path (machineName <> "localhost") requiresSecurity
// scope.Options.EnablePrivileges <- true
// scope.Options.Impersonation <- ImpersonationLevel.Impersonate
let private createScope machineName =
createNamedScope "root\\CIMV2" machineName false
let private GetPropertyNames (pds:PropertyData seq) =
pds
|> Seq.map( fun pd -> pd.Name)
|> Array.ofSeq
let private GetPropertyCollectionNames (mo:PropertyDataCollection) =
mo
|> Seq.cast<PropertyData>
|> GetPropertyNames
let private MapManagementProperty name (t:Type) (value:obj) :obj =
try
if value = null then null else
match name with
| "CreationDate" | "InstallDate" ->
// printfn "doing %s of type %A with inputType %A" name t (value.GetType())
upcast ManagementDateTimeConverter.ToDateTime(value :?> String)
| _ -> value
with ex ->
printfn "fail: %s of type %A" name t
printfn "%A" ex
null
let private mapWin32Process (managementObjects:ManagementObjectCollection) =
let fields = typeof<Win32_Process>.GetProperties() |> Seq.map (fun p -> p.Name,p.PropertyType)
managementObjects
|> Seq.cast<ManagementObject>
|> Seq.map(fun mo -> printfn "commandLine=%A" mo.Properties.["CommandLine"].Value; mo)
// |> Seq.map(fun mo -> MakeRecord(typeof<Win32_Process>,Array.ma
|> Seq.map (fun mo -> fields |> Seq.map(fun (name,propType) -> MapManagementProperty name propType mo.[name] ) |> Array.ofSeq)
|> Seq.map (fun values -> FSharpValue.MakeRecord(typeof<Win32_Process>, values) :?> Win32_Process)
let QueryFiles machineName = // scans just the root of the c drive currently
let scope = createScope machineName
let drive = "c:"
let query = new ObjectQuery(sprintf "SELECT * FROM CIM_DataFile Where Drive='%s' and Path='%s'" drive "\\\\")
use searcher = new ManagementObjectSearcher(scope, query)
for wmiObj in searcher.Get() do
printfn "%A" wmiObj.["FileName"]
/// Sample Usage: Macros.WmiMacros.QueryWmiAdvanced (Macros.WmiMacros.ScopeItem.Creation("\\\\servername\\root\\MicrosoftIISv2", true,true)) "SELECT Name,ServerComment FROM IIsWebServerSetting"
/// |> Seq.map (fun e -> e.Properties.["Name"].Value,e.Properties.["ServerComment"].Value)
let QueryWmiAdvanced (scopeInput: ScopeItem) query =
let scope =
match scopeInput with
| Scope s -> s
| Creation (path, requiresDomainSecurity, requiresPacketSecurity) -> createAdvancedScope path requiresDomainSecurity requiresPacketSecurity
// createAdvancedScope path requiresDomainSecurity requiresPacketSecurity
let query = new ObjectQuery(query)
use searcher = new ManagementObjectSearcher(scope, query)
use results = searcher.Get()
results |> Seq.cast<ManagementObject> |> Array.ofSeq
let QueryWmi machineName ``namespace`` query requireSecurity =
let scope = createNamedScope ``namespace`` machineName requireSecurity // requiresSecurity
let query = new ObjectQuery(query)
use searcher = new ManagementObjectSearcher(scope, query)
use results = searcher.Get()
results |> Seq.cast<ManagementObject> |> Array.ofSeq
let QueryIis machineName =
let scope = createScope machineName
let query = new SelectQuery( sprintf "select * FROM Win32_Process WHERE name='w3wp.exe'")
use searcher = new ManagementObjectSearcher(scope, query)
use results = searcher.Get()
let records = mapWin32Process results
printfn "%A" records
records
|> Seq.map ProcessDisplay.FromWin32Process
|> Array.ofSeq
let QueryIisV2 machineName =
let scope = createNamedScope "root\\MicrosoftIISv2" machineName true // requiresSecurity
let queryText = sprintf "SELECT * FROM IIsWebVirtualDir"
printfn "Query = %s" queryText
let query = new SelectQuery(queryText)
use searcher = new ManagementObjectSearcher(scope,query)
use results = searcher.Get()
let allResults =
results
|> Seq.cast<ManagementObject>
//|> Seq.map(fun mo -> mo.Properties)
|> Array.ofSeq
printfn "length: %i" allResults.Length
allResults
let QueryIisV2Virtuals machineName =
let scope = createNamedScope "root\\MicrosoftIISv2" machineName true // requiresSecurity
let query = new SelectQuery (sprintf "SELECT * FROM IIsWebVirtualDir_IIsWebVirtualDir")
use searcher = new ManagementObjectSearcher(scope,query)
use results = searcher.Get()
let allResults =
results
|> Seq.cast<ManagementObject>
//|> Seq.map(fun mo -> mo.Properties)
|> Array.ofSeq
printfn "length: %i" allResults.Length
allResults
let QueryProcesses machineName =
let scope = createScope machineName
// let query = new ObjectQuery(sprintf "SELECT CommandLine FROM Win32_Process WHERE Name LIKE '%s%%'" "explorer") //" AND Name LIKE '%%%s'"
let query = new ObjectQuery(sprintf "SELECT * FROM Win32_Process") //" AND Name LIKE '%%%s'"
use searcher = new ManagementObjectSearcher(scope, query)
let values =
searcher.Get()
|> mapWin32Process
printfn "values %A" values
let procs = values |> Array.ofSeq
procs
// maybe try http://www.nullskull.com/faq/283/c-net-get-the-logged-on-user-on-windows-7-using-wmi-query.aspx ?
let QueryUsers machineName =
let scope = createScope machineName
let query = new ObjectQuery("SELECT username FROM Win32_ComputerSystem")
use searcher = new ManagementObjectSearcher(scope, query)
searcher.Get()
|> Seq.cast<ManagementObject>
|> Seq.map (fun mo -> mo.["username"])
|> Array.ofSeq