-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpowershellColonObjects.py
133 lines (121 loc) · 3.73 KB
/
powershellColonObjects.py
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
"""
Powershell objects characterized by key:value pairs
separated by colons
"""
import typing
import json
class PowershellColonObject:
"""
Powershell object characterized by key:value pairs
separated by colons
"""
def __init__(self,
rawFromPowershell:typing.Optional[str]=None):
""" """
if rawFromPowershell is not None:
self.decodePsResult(rawFromPowershell)
def decodePsResult(self,
rawFromPowershell:typing.Optional[str]=None):
"""
Decode from a raw powershell result
"""
key=""
val=""
for line in rawFromPowershell.strip().split('\n'):
if not line:
continue
elif line.startswith(' '): # continuation
val=val+line.lstrip()
else:
kv=line.split(':',1)
key=kv[0].rstrip()
val=kv[1].lstrip()
setattr(self,key,val)
@property
def json(self)->str:
"""
This object as a json string
"""
return self.jsonStr
@property
def jsonStr(self)->str:
"""
This object as a json string
"""
return json.dumps(self.jsonObj,indent=4)
@property
def jsonObj(self)->typing.Dict[str,typing.Any]:
"""
This object as a json-compatable object
"""
ret:typing.Dict[str,typing.Any]={}
for k,v in self.__dict__.items():
if k[0].isalpha() and k[0].isupper():
ret[k]=v
return ret
def __repr__(self):
return self.json
class PowershellColonObjects:
"""
Powershell objects characterized by key:value pairs
separated by colons
"""
def __init__(self,
rawFromPowershell:typing.Optional[str]=None,
psCommand:typing.Optional[str]=None):
""" """
self._psObjects:typing.List[PowershellColonObject]=[]
if rawFromPowershell is not None:
self.decodePsResult(rawFromPowershell)
if psCommand is not None:
self.executeAndDecodeResult(psCommand)
def executeAndDecodeResult(self,psCommand:str)->None:
"""
Execute the given powershell command and then
run decodePsResult() on what comes back
"""
import subprocess
cmd=['powershell','-Command',psCommand]
po=subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
out,err=po.communicate()
errStr=err.decode('utf-8',errors='ignore').strip()
if errStr:
raise Exception(errStr)
outStr=out.decode('utf-8',errors='ignore').strip().replace('\r','')
self.decodePsResult(outStr)
def decodePsResult(self,
rawFromPowershell:str):
"""
Decode from a raw powershell result
"""
self._psObjects=[]
rawFromPowershell.replace('\r','')
for result in rawFromPowershell.split('\n\n'):
dev=PowershellColonObject(result)
self._psObjects.append(dev)
def __iter__(self)->typing.Iterator[PowershellColonObject]:
"""
Iterate over all loaded devices
"""
return iter(self._psObjects)
@property
def json(self)->str:
"""
This object as a json string
"""
return self.jsonStr
@property
def jsonStr(self)->str:
"""
This object as a json string
"""
return json.dumps(self.jsonObj,indent=4)
@property
def jsonObj(self)->typing.List[typing.Dict[str,typing.Any]]:
"""
This object as a json-compatable object
"""
return [device.jsonObj for device in self]
def __repr__(self):
return '\n-----------------------\n'.join(
[repr(item) for item in self])