Commit ca5e6d7e7dbc023e7e8da3e33f6d7288e08c172a
1 parent
82130b9f
v1.8.0
- Pinger beépítése a MaintenanceTool csoportba
Showing
8 changed files
with
1180 additions
and
7 deletions
Show diff stats
Vrh.Log4Pro.MaintenanceConsole/ConsoleFunction - ColorConsole.cs
... | ... | @@ -148,6 +148,7 @@ namespace Vrh.Log4Pro.MaintenanceConsole.ColorConsoleNS |
148 | 148 | if (silentMode) { return; } |
149 | 149 | Console.SetCursorPosition(remembercursorleft, remembercursortop); |
150 | 150 | } |
151 | + public static void SetCursorStartOfLine() { SetCursorPosition(0, ColorConsole.CursorTop); } | |
151 | 152 | |
152 | 153 | public static int CursorLeft { get { return Console.CursorLeft; } } |
153 | 154 | public static int CursorTop { get { return Console.CursorTop; } } | ... | ... |
Vrh.Log4Pro.MaintenanceConsole/ConsoleFunction - CommandLineParser.cs
... | ... | @@ -302,6 +302,7 @@ namespace Vrh.Log4Pro.MaintenanceConsole.CommandLineParserNS |
302 | 302 | public static class Functions |
303 | 303 | { |
304 | 304 | public static class RegexTester { public const string KEY = "RGX"; } |
305 | + public static class TCPIPTester { public const string KEY = "TCP"; } | |
305 | 306 | public static class Tool { public const string KEY = "TOL"; } |
306 | 307 | } |
307 | 308 | } | ... | ... |
Vrh.Log4Pro.MaintenanceConsole/ConsoleFunction - Tools - TcpIp.cs
0 → 100644
... | ... | @@ -0,0 +1,957 @@ |
1 | +using System; | |
2 | +using System.Collections.Generic; | |
3 | +using System.Diagnostics; | |
4 | +using System.IO; | |
5 | +using System.Linq; | |
6 | +using System.Net; | |
7 | +using System.Net.NetworkInformation; | |
8 | +using System.Net.Sockets; | |
9 | +using System.Text; | |
10 | +using System.Threading.Tasks; | |
11 | +using System.Timers; | |
12 | +using System.Xml.Linq; | |
13 | + | |
14 | +namespace Vrh.Log4Pro.MaintenanceConsole.ToolsNS | |
15 | +{ | |
16 | + /// <summary> | |
17 | + /// A pinger objektum ping ciklusokat indít (egy ping ciklusban több ping kérés van/lehet), és ezek eredményét | |
18 | + /// tárolja tömörített formátumban elsősorban abból a célból, hogy a tárolt adatok alapján trend diagramot lehessen | |
19 | + /// készíteni a kapcsolat minőségének kimutatására. | |
20 | + /// </summary> | |
21 | + public class Pinger : IDisposable | |
22 | + { | |
23 | + /// <summary> | |
24 | + /// Egy Pinger objektum létrehozása xml-ből | |
25 | + /// </summary> | |
26 | + /// <param name="hostNameOrAddress">a ping célállomása</param> | |
27 | + /// <param name="pingerconfig">a pinger konfigurációs paramétereit tartalmazó xml struktúra</param> | |
28 | + public Pinger(string hostNameOrAddress, XElement pingerconfig) : this(hostNameOrAddress, new PingerConfig(pingerconfig)) { } | |
29 | + | |
30 | + /// <summary> | |
31 | + /// Egy Pinger objektum létrehozása PrinterConfig osztályból | |
32 | + /// </summary> | |
33 | + /// <param name="hostNameOrAddress">a ping célállomása</param> | |
34 | + /// <param name="pc">a konfigurációt tartalmazó pinger objektum</param> | |
35 | + private Pinger(string hostNameOrAddress, PingerConfig pc) | |
36 | + { | |
37 | + this.HostNameOrAddress = hostNameOrAddress; | |
38 | + this.History = new PingHistory(hostNameOrAddress, pc.pingerhistorylength, pc.pingcyclefrequency); | |
39 | + this.PingTimeout = pc.pingtimeout; | |
40 | + this.PingCycleFrequency = pc.pingcyclefrequency; | |
41 | + this.PingCycleNumberOfPackages = pc.pingcyclenumofpackages; | |
42 | + this.PingerActiveLength = pc.pingeractivlength; | |
43 | + this.Configuration = pc; | |
44 | + } | |
45 | + | |
46 | + /// <summary> | |
47 | + /// A pinger indítása/újraindítása; elindítja a ping ciklus időzítőt, és elkezdi/folytatja a ping státusz adatok letárolását | |
48 | + /// </summary> | |
49 | + /// <param name="pingerconfig">pinger konfig xml struktúra, amely | |
50 | + /// (jellemzően újraindítás esetén) a Pinger részleges átkonfigurálását teszi lehetővé</param> | |
51 | + public void Start(XElement pingerconfig = null) | |
52 | + { | |
53 | + lock (pingcyclelocker) | |
54 | + { | |
55 | + CycleTimerStop(); | |
56 | + Reconfigure(pingerconfig); | |
57 | + CycleTimerStart(); | |
58 | + | |
59 | + if (this.PingerActiveLength > 0) | |
60 | + { | |
61 | + AutoStopTimerStop(); | |
62 | + AutoStopTimerStart(); | |
63 | + } | |
64 | + } | |
65 | + } | |
66 | + | |
67 | + /// <summary> | |
68 | + /// A pinger leállítása; kikapcsolja a ping ciklus időzítőt, és leállítja a ping státusz adatok letárolását | |
69 | + /// </summary> | |
70 | + public void Stop() | |
71 | + { | |
72 | + CycleTimerStop(); | |
73 | + } | |
74 | + | |
75 | + /// <summary> | |
76 | + /// A Pinge objektum átkonfigurálás a a megadott xml struktúra alapján | |
77 | + /// </summary> | |
78 | + /// <param name="pingerconfig"></param> | |
79 | + private void Reconfigure(XElement pingerconfig = null) | |
80 | + { | |
81 | + lock (pingcyclelocker) | |
82 | + { | |
83 | + if (pingerconfig != null) | |
84 | + { | |
85 | + var pc = new PingerConfig(pingerconfig); | |
86 | + this.PingTimeout = pc.pingtimeout; | |
87 | + this.PingCycleFrequency = pc.pingcyclefrequency; | |
88 | + this.PingCycleNumberOfPackages = pc.pingcyclenumofpackages; | |
89 | + this.PingerActiveLength = pc.pingeractivlength; | |
90 | + this.History.SetHistoryLength(pc.pingerhistorylength); | |
91 | + } | |
92 | + } | |
93 | + } | |
94 | + | |
95 | + /// <summary> | |
96 | + /// A pinger autostop lejártakor végrehajtandó metódus | |
97 | + /// </summary> | |
98 | + /// <param name="source"></param> | |
99 | + /// <param name="e"></param> | |
100 | + private void AutoStop(Object source, ElapsedEventArgs e) { CycleTimerStop(); } | |
101 | + | |
102 | + private void CycleTimerStop() | |
103 | + { | |
104 | + lock (pingcyclelocker) { if (this.CycleTimer != null) { this.CycleTimer.Enabled = false; } this.Operating = false; } | |
105 | + } | |
106 | + private void CycleTimerStart() | |
107 | + { | |
108 | + lock (pingcyclelocker) | |
109 | + { | |
110 | + if (this.CycleTimer == null) { this.CycleTimer = new System.Timers.Timer(); this.CycleTimer.Elapsed += StartPingCycle; this.CycleTimer.AutoReset = true; } | |
111 | + this.CycleTimer.Interval = this.PingCycleFrequency; | |
112 | + this.CycleTimer.Enabled = true; | |
113 | + this.Operating = true; | |
114 | + } | |
115 | + } | |
116 | + private void AutoStopTimerStop() | |
117 | + { | |
118 | + lock (pingcyclelocker) | |
119 | + { | |
120 | + if (this.AutoStopTimer != null) { this.AutoStopTimer.Enabled = false; } | |
121 | + } | |
122 | + } | |
123 | + private void AutoStopTimerStart() | |
124 | + { | |
125 | + lock (pingcyclelocker) | |
126 | + { | |
127 | + if (this.AutoStopTimer == null) { this.AutoStopTimer = new System.Timers.Timer(); this.AutoStopTimer.Elapsed += AutoStop; this.AutoStopTimer.AutoReset = false; } | |
128 | + this.AutoStopTimer.Interval = this.PingerActiveLength; | |
129 | + this.AutoStopTimer.Enabled = true; | |
130 | + } | |
131 | + } | |
132 | + /// <summary> | |
133 | + /// Dispose | |
134 | + /// </summary> | |
135 | + public void Dispose() | |
136 | + { | |
137 | + Stop(); | |
138 | + if (this.CycleTimer != null) { this.CycleTimer.Dispose(); this.CycleTimer = null; } | |
139 | + if (this.AutoStopTimer != null) { this.AutoStopTimer.Dispose(); this.AutoStopTimer = null; } | |
140 | + this.History.Dispose(); | |
141 | + } | |
142 | + | |
143 | + /// <summary> | |
144 | + /// Visszadja a history listát | |
145 | + /// </summary> | |
146 | + /// <returns></returns> | |
147 | + public Pinger.PingHistory GetHistory() | |
148 | + { | |
149 | + lock (pingcyclelocker) { this.History.PingerState = this.CycleTimer != null && this.CycleTimer.Enabled ? PingerStatus.Operating : PingerStatus.Still; return this.History; } | |
150 | + } | |
151 | + | |
152 | + #region public fields | |
153 | + /// <summary> | |
154 | + /// A ping célállomása | |
155 | + /// </summary> | |
156 | + public string HostNameOrAddress; | |
157 | + /// <summary> | |
158 | + /// true: a pingcycle timer működik, a pingelés folyamataos | |
159 | + /// false: a pingcycle timer NEM működik, a pingelés áll | |
160 | + /// </summary> | |
161 | + public bool Operating; | |
162 | + /// <summary> | |
163 | + /// Egy ciklusban kiadott ping kérések száma. | |
164 | + /// </summary> | |
165 | + public PingerConfig Configuration; | |
166 | + #endregion public fields | |
167 | + | |
168 | + #region private metódusok | |
169 | + /// <summary> | |
170 | + /// A ping ciklus időzítés lejártakor elindított metódus, ami végrehajt egy ping ciklust és eredményét bedolgozza a PingStateQueue sorba | |
171 | + /// </summary> | |
172 | + /// <param name="source"></param> | |
173 | + /// <param name="e"></param> | |
174 | + private void StartPingCycle(Object source, ElapsedEventArgs e) | |
175 | + { | |
176 | + lock (pingcyclelocker) | |
177 | + { | |
178 | + this.CycleTimer.Enabled = false; // kikapcsoljuk a timer-t a ciklus végrehajtása alatt | |
179 | + var newpc = new PingCycle(this.HostNameOrAddress, this.PingCycleNumberOfPackages, this.PingTimeout).Execute(); | |
180 | + this.History.Merge(newpc); | |
181 | + this.CycleTimer.Interval = this.PingCycleFrequency;// ha esetleg közben újrakonfigurálták.... | |
182 | + this.CycleTimer.Enabled = true; // a ciklus végrehajtása után ismét elindítjuk az időzítőt | |
183 | + } | |
184 | + } | |
185 | + #endregion private metódusok | |
186 | + | |
187 | + #region private fields | |
188 | + /// <summary> | |
189 | + /// Az egyes ping kérések maximális timeout-ja (millisecundum) | |
190 | + /// </summary> | |
191 | + private int PingTimeout; | |
192 | + /// <summary> | |
193 | + /// A ping ciklus befejeződése után ennyi idővel indítja a következőt (másodpercben) | |
194 | + /// </summary> | |
195 | + private int PingCycleFrequency; | |
196 | + /// <summary> | |
197 | + /// A ping vizsgálat teljes időtartama; Ennyi idő eltelte után nem indít több több ping ciklust. | |
198 | + /// Érték percben. Ha az érték 0, akkor végtelen hosszú időn keresztül indít ping ciklusokat. | |
199 | + /// </summary> | |
200 | + private int PingerActiveLength; | |
201 | + /// <summary> | |
202 | + /// Egy ciklusban kiadott ping kérések száma. | |
203 | + /// </summary> | |
204 | + private int PingCycleNumberOfPackages; | |
205 | + /// <summary> | |
206 | + /// A ping ciklusok keveredését megakadályozó locker objektum | |
207 | + /// </summary> | |
208 | + private object pingcyclelocker = new object(); | |
209 | + /// <summary> | |
210 | + /// A Pinger működési periódusának hossza (az autostop timer kikapcsolási ideje) (perc) | |
211 | + /// </summary> | |
212 | + private System.Timers.Timer AutoStopTimer; | |
213 | + /// <summary> | |
214 | + /// A Ping ciklus timere | |
215 | + /// </summary> | |
216 | + private System.Timers.Timer CycleTimer; | |
217 | + /// <summary> | |
218 | + /// Ping history | |
219 | + /// </summary> | |
220 | + private PingHistory History; | |
221 | + #endregion private fields | |
222 | + | |
223 | + #region PingerConfig class | |
224 | + /// <summary> | |
225 | + /// PingerConfig osztály | |
226 | + /// </summary> | |
227 | + public class PingerConfig | |
228 | + { | |
229 | + /// <summary> | |
230 | + /// példány létrehozása xml struktúra alapján | |
231 | + /// </summary> | |
232 | + /// <param name="pingerconfig"></param> | |
233 | + public PingerConfig(XElement pingerconfig) | |
234 | + { | |
235 | + if (pingerconfig != null) | |
236 | + { | |
237 | + var _pingtimeout = GetPositiveIntFromXml(PINGTIMEOUT, pingerconfig, DEFAULT_PINGTIMEOUT); | |
238 | + var _pingcyclefrequency = GetPositiveIntFromXml(PINGCYCLEFREQUENCY, pingerconfig, 0); | |
239 | + var _pingcyclenumofpackages = GetPositiveIntFromXml(PINGCYCLENUMOFPACKAGES, pingerconfig, DEFAULT_PINGCYCLENUMOFPACKAGES); | |
240 | + var _pingeractivlength = GetPositiveIntFromXml(PINGERACTIVELENGTHTOSTOPPERIOD, pingerconfig, DEFAULT_PINGERACTIVELENGTH); | |
241 | + var _pingerhistorylength = GetPositiveIntFromXml(PINGERHISTORYLENGTH, pingerconfig, DEFAULT_PINGERHISTORYLENGTH); | |
242 | + SetValues(_pingtimeout, _pingcyclefrequency, _pingcyclenumofpackages, _pingeractivlength, _pingerhistorylength); | |
243 | + } | |
244 | + else { SetValues(); } | |
245 | + } | |
246 | + | |
247 | + /// <summary> | |
248 | + /// Példány létrehozása paraméterek alapján; a konstruktor célja a mértékegységek és a default értékek kezelése | |
249 | + /// </summary> | |
250 | + /// <param name="pingtimeout">millisecond</param> | |
251 | + /// <param name="pingcyclefrequency">seconds</param> | |
252 | + /// <param name="pingcyclenumofpackages">pcs</param> | |
253 | + /// <param name="pingeractivelength">minutes</param> | |
254 | + /// <param name="pingerhistorylength">minutes</param> | |
255 | + public PingerConfig(int pingtimeout = 0, int pingcyclefrequency = 0, int pingcyclenumofpackages = 0, int pingeractivelength = 0, int pingerhistorylength = 0) | |
256 | + { | |
257 | + SetValues(pingtimeout, pingcyclefrequency, pingcyclenumofpackages, pingeractivelength, pingerhistorylength); | |
258 | + } | |
259 | + | |
260 | + /// <summary> | |
261 | + /// Beállítja a field-ek értékét a megfelelő mértékegységben a paraméterek, illetve az alapértelmezések szerint | |
262 | + /// </summary> | |
263 | + /// <param name="pingtimeout">millisecond</param> | |
264 | + /// <param name="pingcyclefrequency">seconds</param> | |
265 | + /// <param name="pingcyclenumofpackages">pcs</param> | |
266 | + /// <param name="pingeractivelength">minutes</param> | |
267 | + /// <param name="pingerhistorylength">minutes</param> | |
268 | + private void SetValues(int pingtimeout = 0, int pingcyclefrequency = 0, int pingcyclenumofpackages = 0, int pingeractivelength = 0, int pingerhistorylength = 0) | |
269 | + { | |
270 | + this.pingtimeout = pingtimeout <= 0 ? PingerConfig.DEFAULT_PINGTIMEOUT : pingtimeout; | |
271 | + this.pingcyclefrequency = pingcyclefrequency * 1000; | |
272 | + if (this.pingcyclefrequency < this.pingtimeout) { this.pingcyclefrequency = this.pingtimeout; } | |
273 | + this.pingcyclenumofpackages = pingcyclenumofpackages <= 0 ? PingerConfig.DEFAULT_PINGCYCLENUMOFPACKAGES : pingcyclenumofpackages; | |
274 | + this.pingeractivlength = (pingeractivelength <= 0 ? PingerConfig.DEFAULT_PINGERACTIVELENGTH : pingeractivelength) * 60 * 1000; | |
275 | + this.pingerhistorylength = (pingerhistorylength <= 0 ? PingerConfig.DEFAULT_PINGERHISTORYLENGTH : pingerhistorylength) * 60 * 1000; | |
276 | + } | |
277 | + /// <summary> | |
278 | + /// Egy int értéket kiemel a megadott xml struktúrából, ha nincs ott a keresett érték, | |
279 | + /// vagy nem integer, vagy nem pozitív, akkor az alapértelmezést adja vissza | |
280 | + /// </summary> | |
281 | + /// <param name="xname">az xml struktúrában a keresett elem neve</param> | |
282 | + /// <param name="pingerconfig">az xml struktúra</param> | |
283 | + /// <param name="defaultvalue">az alapértelmezett érték</param> | |
284 | + /// <returns></returns> | |
285 | + private static int GetPositiveIntFromXml(string xname, XElement pingerconfig, int defaultvalue) | |
286 | + { | |
287 | + string valstr = pingerconfig?.Element(XName.Get(xname))?.Value; | |
288 | + int val = defaultvalue; | |
289 | + if (valstr != null && int.TryParse(valstr, out int val1) && val1 > 0) { val = val1; } | |
290 | + return val; | |
291 | + } | |
292 | + | |
293 | + public int pingtimeout; | |
294 | + public int pingcyclefrequency; | |
295 | + public int pingcyclenumofpackages; | |
296 | + public int pingeractivlength; | |
297 | + public int pingerhistorylength; | |
298 | + | |
299 | + const string PINGTIMEOUT = "PingTimeout"; | |
300 | + const string PINGCYCLEFREQUENCY = "PingCycleFrequency"; | |
301 | + const string PINGCYCLENUMOFPACKAGES = "PingCycleNumOfPackages"; | |
302 | + const string PINGERACTIVELENGTHTOSTOPPERIOD = "PingerActiveLength"; | |
303 | + const string PINGERHISTORYLENGTH = "PingerHistoryLength"; | |
304 | + public const int DEFAULT_PINGTIMEOUT = PingCycle.MAXROUNDTRIPTIMEOUTCATEGORY; | |
305 | + public const int DEFAULT_PINGCYCLENUMOFPACKAGES = 4; | |
306 | + public const int DEFAULT_PINGERACTIVELENGTH = 60; | |
307 | + public const int DEFAULT_PINGERHISTORYLENGTH = 60; | |
308 | + } | |
309 | + #endregion PingerConfig class | |
310 | + | |
311 | + #region PingHistory class | |
312 | + /// <summary> | |
313 | + /// Ping history struktúra | |
314 | + /// </summary> | |
315 | + public class PingHistory : IDisposable | |
316 | + { | |
317 | + /// <summary> | |
318 | + /// Ping állapot-sor. Minden eleme egy kezdő-időponttól fogva a következő elem kezdőidopontjáig fennálló állapotot ír le. | |
319 | + /// Ha az új státusz állapot-ban a RoundtripTimeCategory vagy StatusCategory értéke a sorban levő legutolsó elemben levő értékekhez képes | |
320 | + /// KÜLÖNBÖZIK, akkor Új elem kerül be a sorba; | |
321 | + /// AZONOS, akkor a legutolsó elemben a PackagesSent és PackagesLost értékekhez hozzáadódik az új elemben levő megfelelő érték, de új elem nem kerül hozzáadásra | |
322 | + /// </summary> | |
323 | + public List<PingCycle> PingStateQueue; | |
324 | + /// <summary> | |
325 | + /// A PingStateQueue utolsó eleme | |
326 | + /// </summary> | |
327 | + private PingCycle LastPingCycle; | |
328 | + | |
329 | + /// <summary> | |
330 | + /// A tárolt history hossza percben | |
331 | + /// </summary> | |
332 | + public int Length; | |
333 | + | |
334 | + /// <summary> | |
335 | + /// A ping ciklusok gyakorisága | |
336 | + /// </summary> | |
337 | + public int PingCycleFrequency; | |
338 | + | |
339 | + public string HostNameOrAddress; | |
340 | + public PingerStatus PingerState = PingerStatus.Still; | |
341 | + public DateTime StartTime; | |
342 | + | |
343 | + private object historylocker = new object(); | |
344 | + | |
345 | + public PingHistory(string hostnameoraddress, int pingerhistorylength,int pingcyclefrequency) | |
346 | + { | |
347 | + this.HostNameOrAddress = hostnameoraddress; | |
348 | + this.PingStateQueue = new List<PingCycle>(); | |
349 | + this.LastPingCycle = null; | |
350 | + this.Length = pingerhistorylength; | |
351 | + this.PingCycleFrequency = pingcyclefrequency; | |
352 | + } | |
353 | + public PingHistory(PingHistory ph) | |
354 | + { | |
355 | + this.HostNameOrAddress = ph.HostNameOrAddress; | |
356 | + this.PingStateQueue = ph.PingStateQueue.Select(x=>new PingCycle(x)).ToList(); | |
357 | + this.LastPingCycle = ph.LastPingCycle; | |
358 | + this.Length = ph.Length; | |
359 | + this.PingCycleFrequency = ph.PingCycleFrequency; | |
360 | + } | |
361 | + | |
362 | + public void Dispose() | |
363 | + { | |
364 | + this.PingStateQueue = null; | |
365 | + this.LastPingCycle = null; | |
366 | + } | |
367 | + /// <summary> | |
368 | + /// A PrintCycle beillesztése a sor végére, vagy "hozzáadása" az utolsó elemhez | |
369 | + /// </summary> | |
370 | + /// <param name="newpc"></param> | |
371 | + public void Merge(PingCycle newpc) | |
372 | + { | |
373 | + lock (historylocker) | |
374 | + { | |
375 | + if (this.LastPingCycle?.isDifferent(newpc) ?? true) { this.PingStateQueue.Add(newpc); this.LastPingCycle = newpc; } | |
376 | + else | |
377 | + { | |
378 | + var totalrtt = ((this.LastPingCycle.RoundtripTimeAverage * this.LastPingCycle.NumberOfCycles) + newpc.RoundtripTimeAverage); | |
379 | + this.LastPingCycle.NumberOfCycles++; | |
380 | + this.LastPingCycle.RoundtripTimeAverage = totalrtt / this.LastPingCycle.NumberOfCycles; | |
381 | + this.LastPingCycle.PackagesSent += newpc.PackagesSent; | |
382 | + this.LastPingCycle.PackagesLost += newpc.PackagesLost; | |
383 | + this.LastPingCycle.LastTimestamp = newpc.StartTimestamp; | |
384 | + if (newpc.RoundtripTimeMax != -1 && this.LastPingCycle.RoundtripTimeMax != -1) | |
385 | + { | |
386 | + if (this.LastPingCycle.RoundtripTimeMax < newpc.RoundtripTimeMax) { this.LastPingCycle.RoundtripTimeMax = newpc.RoundtripTimeMax; } | |
387 | + if (this.LastPingCycle.RoundtripTimeMin > newpc.RoundtripTimeMin) { this.LastPingCycle.RoundtripTimeMin = newpc.RoundtripTimeMin; } | |
388 | + } | |
389 | + } | |
390 | + | |
391 | + var borderts = newpc.StartTimestamp.AddMilliseconds(-1 * this.Length); | |
392 | + this.PingStateQueue.RemoveAll(x => x.LastTimestamp <= borderts); | |
393 | + var firstelement = this.PingStateQueue.FirstOrDefault(); | |
394 | + if (firstelement != null && firstelement.StartTimestamp < borderts) | |
395 | + { | |
396 | + var partiallength = (firstelement.LastTimestamp - borderts).TotalMilliseconds; | |
397 | + var fulllength = (firstelement.LastTimestamp - firstelement.StartTimestamp).TotalMilliseconds; | |
398 | + firstelement.PackagesSent = (int)((double)firstelement.PackagesSent * partiallength / fulllength); | |
399 | + firstelement.PackagesLost = (int)((double)firstelement.PackagesLost * partiallength / fulllength); | |
400 | + firstelement.NumberOfCycles = (int)((double)firstelement.NumberOfCycles * partiallength / fulllength); | |
401 | + if (firstelement.NumberOfCycles == 0 || firstelement.PackagesSent == 0) { this.PingStateQueue.Remove(firstelement); firstelement = this.PingStateQueue.FirstOrDefault(); } | |
402 | + | |
403 | + var packagelostratio = firstelement.PackagesLost / firstelement.PackagesSent; | |
404 | + firstelement.PackagesSentCategory = | |
405 | + packagelostratio == 0 ? PingCycle.LostPackageCategory.Excellent | |
406 | + : packagelostratio < 0.1 ? PingCycle.LostPackageCategory.Good | |
407 | + : packagelostratio < 0.3 ? PingCycle.LostPackageCategory.Acceptable | |
408 | + : PingCycle.LostPackageCategory.Bad; | |
409 | + firstelement.StartTimestamp = borderts; | |
410 | + } | |
411 | + StartTime = firstelement?.StartTimestamp ?? DateTime.MaxValue; | |
412 | + } | |
413 | + } | |
414 | + | |
415 | + /// <summary> | |
416 | + /// Beállítja a history hosszát | |
417 | + /// </summary> | |
418 | + /// <param name="pingerhistoryperiod"></param> | |
419 | + public void SetHistoryLength(int pingerhistoryperiod) | |
420 | + { | |
421 | + lock (historylocker) { this.Length = pingerhistoryperiod; } | |
422 | + } | |
423 | + } | |
424 | + #endregion PingHistory class | |
425 | + | |
426 | + #region PingCycle class | |
427 | + /// <summary> | |
428 | + /// A ping history-ban szereplő elemek típusa | |
429 | + /// </summary> | |
430 | + public class PingCycle | |
431 | + { | |
432 | + /// <summary> | |
433 | + /// Ping ciklus objektum létrehozása | |
434 | + /// </summary> | |
435 | + /// <param name="hostnameoraddress">a pingek célja</param> | |
436 | + /// <param name="numofpings">ennyi ping-et kell végrehajtani</param> | |
437 | + /// <param name="pingtimeout">ennyi az egyes ping-ek timeout-ja</param> | |
438 | + public PingCycle(string hostnameoraddress, int numofpings, int pingtimeout) | |
439 | + { | |
440 | + this.HostNameOrAddress = hostnameoraddress; | |
441 | + this.PackagesSent = numofpings; | |
442 | + this.PingTimeout = pingtimeout; | |
443 | + this.PackagesLost = 0; | |
444 | + this.PackagesSentCategory = LostPackageCategory.Excellent; | |
445 | + this.NumberOfCycles = 1; | |
446 | + this.StatusCategory = IPStatusCategory.NotExecuted; | |
447 | + this.RoundtripTimeAverage = 0; | |
448 | + this.RoundtripTimeMin = -1; | |
449 | + this.RoundtripTimeMax = -1; | |
450 | + } | |
451 | + public PingCycle(PingCycle pc) | |
452 | + { | |
453 | + this.HostNameOrAddress = pc.HostNameOrAddress; | |
454 | + this.PackagesSent = pc.PackagesSent; | |
455 | + this.PingTimeout = pc.PingTimeout; | |
456 | + this.PackagesLost = pc.PackagesLost; | |
457 | + this.PackagesSentCategory = pc.PackagesSentCategory; | |
458 | + this.NumberOfCycles = pc.NumberOfCycles; | |
459 | + this.StatusCategory = pc.StatusCategory; | |
460 | + this.RoundtripTimeAverage = pc.RoundtripTimeAverage; | |
461 | + this.RoundtripTimeMax = pc.RoundtripTimeMax; | |
462 | + this.RoundtripTimeMin= pc.RoundtripTimeMin; | |
463 | + } | |
464 | + | |
465 | + #region public fields,enums | |
466 | + /// <summary> | |
467 | + /// A maximális ping timeout kategória értéke | |
468 | + /// </summary> | |
469 | + public const int MAXROUNDTRIPTIMEOUTCATEGORY = 5000; | |
470 | + /// <summary> | |
471 | + /// A Ping állapot ezen időpillanattól kezdődően állt/áll fenn | |
472 | + /// </summary> | |
473 | + public DateTime StartTimestamp; | |
474 | + /// <summary> | |
475 | + /// A Ping állapot ezen időpillanattól kezdődően állt/áll fenn | |
476 | + /// </summary> | |
477 | + public DateTime LastTimestamp; | |
478 | + /// <summary> | |
479 | + /// Az állapot ilyen válaszidőt jelent (valójában ez is egy kategória, de egy konkrét idő érték jellemzi) | |
480 | + /// </summary> | |
481 | + public int RoundtripTime; | |
482 | + | |
483 | + /// <summary> | |
484 | + /// A ping ciklusban végrehajtott ping-ek maximális válaszideje | |
485 | + /// </summary> | |
486 | + public int RoundtripTimeMax=-1; | |
487 | + /// <summary> | |
488 | + /// A ping ciklusban végrehajtott ping-ek minimális válaszideje | |
489 | + /// </summary> | |
490 | + public int RoundtripTimeMin=-1; | |
491 | + | |
492 | + /// <summary> | |
493 | + /// A pontos válaszidők átlaga | |
494 | + /// </summary> | |
495 | + public int RoundtripTimeAverage; | |
496 | + | |
497 | + /// <summary> | |
498 | + /// Az állapot ilyen válaszidő kategóriát jelent | |
499 | + /// </summary> | |
500 | + public RoundTripTimeCategory RoundtripTimeCategory; | |
501 | + /// <summary> | |
502 | + /// Az állapot ilyen IPStatus kategóriát jelent | |
503 | + /// </summary> | |
504 | + public IPStatusCategory StatusCategory; | |
505 | + /// <summary> | |
506 | + /// Ebben a státus állapotban ennyi csomag került kiküldésre | |
507 | + /// </summary> | |
508 | + public int PackagesSent; | |
509 | + /// <summary> | |
510 | + /// Ebben a státus állapotban ennyi csomag veszett el nem Success | |
511 | + /// </summary> | |
512 | + public int PackagesLost; | |
513 | + /// <summary> | |
514 | + /// Ebben a státus állapotban az elveszett csomagokra utaló státusz | |
515 | + /// </summary> | |
516 | + public LostPackageCategory PackagesSentCategory; | |
517 | + /// <summary> | |
518 | + /// A ping ciklusok száma ebben az egységben | |
519 | + /// </summary> | |
520 | + public int NumberOfCycles; | |
521 | + | |
522 | + /// <summary> | |
523 | + /// Válasz státusz kategóriák; minél nagyobb az érték, annál kevesebbet tudunk a hiba okáról. | |
524 | + /// </summary> | |
525 | + public enum IPStatusCategory { Success = 0, TimedOut = 10, PortUnreachable = 20, HostUnreachable = 30, NetworkUnreachable = 40, Failed = 50, NotExecuted = 100, } | |
526 | + public enum LostPackageCategory { Excellent = 0, Good = 1, Acceptable = 2, Bad = 3, } | |
527 | + public enum RoundTripTimeCategory { Q1 = 0, Q2 = 1, Q3 = 2, Q4 = 3, } | |
528 | + #endregion public fields,enums | |
529 | + | |
530 | + #region isDifferent | |
531 | + /// <summary> | |
532 | + /// Eldönti, hogy a két objektum azonosnak tekinthető-e, vagy sem | |
533 | + /// </summary> | |
534 | + /// <param name="pc"></param> | |
535 | + /// <returns></returns> | |
536 | + public bool isDifferent(PingCycle pc) | |
537 | + { | |
538 | + return this.StatusCategory != pc.StatusCategory || this.RoundtripTime != pc.RoundtripTime; | |
539 | + } | |
540 | + #endregion isDifferent | |
541 | + | |
542 | + #region Execute | |
543 | + /// <summary> | |
544 | + /// Egy ping ciklus végrehajtása; | |
545 | + /// </summary> | |
546 | + /// <returns> | |
547 | + /// StatusCategory: értéke NotExecuted értéktől különbözni fog. | |
548 | + /// StartTimestamp: értéke a hívás időpillanata lesz. | |
549 | + /// PackagesLost: a nem Success-sel visszatérő ping-ek száma | |
550 | + /// RoundtripTimeCategory: a válaszidő kategória értéke | |
551 | + /// </returns> | |
552 | + public PingCycle Execute() | |
553 | + { | |
554 | + this.StartTimestamp = DateTime.Now; | |
555 | + this.LastTimestamp = this.StartTimestamp; | |
556 | + for (var i = 0; i < this.PackagesSent; i++) | |
557 | + { | |
558 | + var pr = PingTool.Ping(this.HostNameOrAddress, (int)PingTimeout);//egy ping kérés feladása | |
559 | + AddResponse(pr, i + 1);//a ping válasz "bedolgozása" a pingciklus-állapotba | |
560 | + } | |
561 | + | |
562 | + this.RoundtripTime = RoundTripTimeLimits.LastOrDefault(x => x <= this.RoundtripTimeAverage); | |
563 | + var RoundTripTimeyCategoryValue = RoundTripTimeyCategoryLimits.LastOrDefault(x => x < this.RoundtripTimeAverage); | |
564 | + var RoundTripTimeyCategoryIndex = RoundTripTimeyCategoryLimits.FindIndex(x => x == RoundTripTimeyCategoryValue); | |
565 | + this.RoundtripTimeCategory = RoundTripTimeyCategoryIndex == 0 ? RoundTripTimeCategory.Q1 | |
566 | + : RoundTripTimeyCategoryIndex == 1 ? RoundTripTimeCategory.Q2 | |
567 | + : RoundTripTimeyCategoryIndex == 2 ? RoundTripTimeCategory.Q3 | |
568 | + : RoundTripTimeCategory.Q4; | |
569 | + return this; | |
570 | + } | |
571 | + #endregion Execute | |
572 | + | |
573 | + #region private elemek | |
574 | + /// <summary> | |
575 | + /// a ping célcíme | |
576 | + /// </summary> | |
577 | + private string HostNameOrAddress; | |
578 | + /// <summary> | |
579 | + /// A FINOM válaszidő kategóriákat tartalmazza; egy válasz az i. válaszidő kategóriába tartozik, ha a pontos válaszidő nagyobb, vagy egyenlő, | |
580 | + /// mint az i. elem értéke, de kisebb, mint az i+1. elem értéke.A sor első elemének értéke mindig 0!!!! | |
581 | + /// Ha a sor értékei: 0:0,1:100,2:200,3:300,4:400,5:500, a pontos válaszidő 350, akkor ez a 2. kategóriába tartozik, ha pontos válaszidő. | |
582 | + /// </summary> | |
583 | + private static List<int> RoundTripTimeLimits = new List<int> { 0, 25, 50, 75, 100, 150, 200, 250, 300, 400, 500, 750, 1000, 1250, 1500, 1750, 2000, 2500, 3000, 3500, 4000, 4500, PingCycle.MAXROUNDTRIPTIMEOUTCATEGORY, }; | |
584 | + | |
585 | + /// <summary> | |
586 | + /// A DURVA válaszidő kategóriákat tartalmazza; egy válasz az i. válaszidő kategóriába tartozik, ha a pontos válaszidő nagyobb, vagy egyenlő, | |
587 | + /// mint az i. elem értéke, de kisebb, mint az i+1. elem értéke.A sor első elemének értéke mindig 0!!!! | |
588 | + /// Ha a sor értékei: 0:0,1:100,2:200,3:300,4:400,5:500, a pontos válaszidő 350, akkor ez a 2. kategóriába tartozik, ha pontos válaszidő. | |
589 | + /// </summary> | |
590 | + private static List<int> RoundTripTimeyCategoryLimits = new List<int> { 0, 50, 250, 750, }; | |
591 | + /// <summary> | |
592 | + /// Az egyes ping kérések timeout-ja | |
593 | + /// </summary> | |
594 | + private int PingTimeout; | |
595 | + /// <summary> | |
596 | + /// A ping válasz bedolgozása a pingciklus státuszba | |
597 | + /// </summary> | |
598 | + /// <param name="pr">a ping válasza</param> | |
599 | + /// <param name="i">a ping kérés indexe; 1,2,....</param> | |
600 | + private void AddResponse(PingReply pr, int i) | |
601 | + { | |
602 | + var ipsCat = GetIPStatusCategory(pr); | |
603 | + if (ipsCat==IPStatusCategory.Success) | |
604 | + { | |
605 | + int prroundtriptime = pr.RoundtripTime >= int.MaxValue ? int.MaxValue : (int)pr.RoundtripTime; | |
606 | + this.RoundtripTimeMin = prroundtriptime < this.RoundtripTimeMin || this.RoundtripTimeMin ==-1 ? prroundtriptime : this.RoundtripTimeMin; | |
607 | + this.RoundtripTimeMax = prroundtriptime > this.RoundtripTimeMax || this.RoundtripTimeMax == -1 ? prroundtriptime : this.RoundtripTimeMax; | |
608 | + this.RoundtripTimeAverage = ((i - 1) * this.RoundtripTimeAverage + prroundtriptime) / i;// az átlagos válaszidőt tárolja | |
609 | + } | |
610 | + else { this.PackagesLost++; } | |
611 | + if (ipsCat < this.StatusCategory) { this.StatusCategory = ipsCat; }// a legjobb státuszt tárolja | |
612 | + } | |
613 | + /// <summary> | |
614 | + /// Visszaadja, hogy a PingReply adat alapján a válasz melyik státusz kategóriába tartozik | |
615 | + /// </summary> | |
616 | + /// <param name="pr"></param> | |
617 | + /// <returns></returns> | |
618 | + private IPStatusCategory GetIPStatusCategory(PingReply pr) | |
619 | + { | |
620 | + switch (pr.Status) | |
621 | + { | |
622 | + case IPStatus.Success: return IPStatusCategory.Success;//Success = 0,The ICMP echo request succeeded; an ICMP echo reply was received. When you get this status code, the other System.Net.NetworkInformation.PingReply properties contain valid data. | |
623 | + | |
624 | + case IPStatus.DestinationNetworkUnreachable: //DestinationNetworkUnreachable = 11002,The ICMP echo request failed because the network that contains the destination computer is not reachable. | |
625 | + return IPStatusCategory.NetworkUnreachable; | |
626 | + | |
627 | + case IPStatus.BadRoute: //BadRoute = 11012,The ICMP echo request failed because there is no valid route between the source and destination computers. | |
628 | + case IPStatus.DestinationUnreachable: //DestinationUnreachable = 11040,The ICMP echo request failed because the destination computer that is specified in an ICMP echo message is not reachable; the exact cause of problem is unknown. | |
629 | + case IPStatus.DestinationHostUnreachable: //DestinationHostUnreachable = 11003,The ICMP echo request failed because the destination computer is not reachable. | |
630 | + return IPStatusCategory.HostUnreachable; | |
631 | + | |
632 | + case IPStatus.TtlReassemblyTimeExceeded://TtlReassemblyTimeExceeded = 11014,The ICMP echo request failed because the packet was divided into fragments for transmission and all of the fragments were not received within the time allottedfor reassembly. RFC 2460 (available at www.ietf.org) specifies 60 seconds as the time limit within which all packet fragments must be received. | |
633 | + case IPStatus.TtlExpired://TtlExpired = 11013,The ICMP echo request failed because its Time to Live (TTL) value reached zero, causing the forwarding node (router or gateway) to discard the packet. | |
634 | + case IPStatus.TimeExceeded: //TimeExceeded = 11041,The ICMP echo request failed because its Time to Live (TTL) value reached zero, causing the forwarding node (router or gateway) to discard the packet. | |
635 | + case IPStatus.TimedOut: //TimedOut = 11010,The ICMP echo Reply was not received within the allotted time. The default time allowed for replies is 5 seconds. You can change this value using theOverload:System.Net.NetworkInformation.Ping.Send or Overload:System.Net.NetworkInformation.Ping.SendAsync methods that take a timeout parameter. | |
636 | + return IPStatusCategory.TimedOut; | |
637 | + | |
638 | + //DestinationProhibited = 11004,The ICMPv6 echo request failed because contact with the destination computer is administratively prohibited. This value applies only to IPv6. | |
639 | + case IPStatus.DestinationProtocolUnreachable://DestinationProtocolUnreachable = 11004, The ICMP echo request failed because the destination computer that is specified in an ICMP echo message is not reachable, because it does not support the packet'sprotocol. This value applies only to IPv4. This value is described in IETF RFC 1812 as Communication Administratively Prohibited. | |
640 | + case IPStatus.DestinationPortUnreachable: //DestinationPortUnreachable = 11005,Summary: The ICMP echo request failed because the port on the destination computer is not available. | |
641 | + case IPStatus.Unknown://Unknown = -1,The ICMP echo request failed for an unknown reason. | |
642 | + case IPStatus.NoResources: //NoResources = 11006,Summary: The ICMP echo request failed because of insufficient network resources. | |
643 | + case IPStatus.BadOption: //BadOption = 11007,The ICMP echo request failed because it contains an invalid option. | |
644 | + case IPStatus.HardwareError: //HardwareError = 11008,The ICMP echo request failed because of a hardware error. | |
645 | + case IPStatus.PacketTooBig: //PacketTooBig = 11009,The ICMP echo request failed because the packet containing the request is larger than the maximum transmission unit (MTU) of a node (router or gateway) located between the source and destination. The MTU defines the maximum size of a transmittable packet. | |
646 | + case IPStatus.ParameterProblem: //ParameterProblem = 11015,The ICMP echo request failed because a node (router or gateway) encountered problems while processing the packet header. This is the status if, for example, the header contains invalid field data or an unrecognized option. | |
647 | + case IPStatus.SourceQuench: //SourceQuench = 11016,The ICMP echo request failed because the packet was discarded. This occurs when the source computer's output queue has insufficient storage space, or when packetsarrive at the destination too quickly to be processed. | |
648 | + case IPStatus.BadDestination: //BadDestination = 11018,The ICMP echo request failed because the destination IP address cannot receive ICMP echo requests or should never appear in the destination address field ofany IP datagram. For example, calling Overload:System.Net.NetworkInformation.Ping.Send and specifying IP address "000.0.0.0" returns this status. | |
649 | + case IPStatus.BadHeader: //BadHeader = 11042,The ICMP echo request failed because the header is invalid. | |
650 | + case IPStatus.UnrecognizedNextHeader://UnrecognizedNextHeader = 11043,The ICMP echo request failed because the Next Header field does not contain a recognized value. The Next Header field indicates the extension header type (ifpresent) or the protocol above the IP layer, for example, TCP or UDP. | |
651 | + case IPStatus.IcmpError: //IcmpError = 11044,The ICMP echo request failed because of an ICMP protocol error. | |
652 | + case IPStatus.DestinationScopeMismatch://DestinationScopeMismatch = 11045, The ICMP echo request failed because the source address and destination address that are specified in an ICMP echo message are not in the same scope. This istypically caused by a router forwarding a packet using an interface that is outside the scope of the source address. Address scopes (link-local, site-local, andglobal scope) determine where on the network an address is valid. } | |
653 | + return IPStatusCategory.Failed; | |
654 | + } | |
655 | + return IPStatusCategory.Failed; | |
656 | + } | |
657 | + #endregion private elemek | |
658 | + } | |
659 | + #endregion PingCycle class | |
660 | + | |
661 | + public enum PingerStatus { NotExisting = 2, Still = 1, Operating = 0, } | |
662 | + } | |
663 | + | |
664 | + /// <summary> | |
665 | + /// TCP Ping eszközök | |
666 | + /// </summary> | |
667 | + public static class PingTool | |
668 | + { | |
669 | + /// <summary> | |
670 | + /// Elérhető e az állomás? | |
671 | + /// </summary> | |
672 | + /// <param name="hostNameOrAddress">Ip, vagy host név</param> | |
673 | + /// <param name="timeOut">timeout</param> | |
674 | + /// <returns></returns> | |
675 | + public static bool IsHostAccessible(string hostNameOrAddress, int timeOut = 1000) | |
676 | + { | |
677 | + PingReply reply = Ping(hostNameOrAddress, timeOut); | |
678 | + return reply.Status == IPStatus.Success; | |
679 | + } | |
680 | + | |
681 | + /// <summary> | |
682 | + /// Visszadja az állomás ping idejét (millisecundum) | |
683 | + /// </summary> | |
684 | + /// <param name="hostNameOrAddress">Ip, vagy host név</param> | |
685 | + /// <param name="timeOut">timeout</param> | |
686 | + /// <returns></returns> | |
687 | + public static long GetPingTime(string hostNameOrAddress, int timeOut = 1000) | |
688 | + { | |
689 | + PingReply reply = Ping(hostNameOrAddress, timeOut); | |
690 | + return reply.RoundtripTime; | |
691 | + } | |
692 | + | |
693 | + /// <summary> | |
694 | + /// Visszadja az állomás ping szerinti státuszát (IPStatus) | |
695 | + /// </summary> | |
696 | + /// <param name="hostNameOrAddress">Ip, vagy host név</param> | |
697 | + /// <param name="timeOut">timeout</param> | |
698 | + /// | |
699 | + | |
700 | + /// <returns></returns> | |
701 | + public static IPStatus GetPingStatus(string hostNameOrAddress, int timeOut = 1000) | |
702 | + { | |
703 | + PingReply reply = Ping(hostNameOrAddress, timeOut); | |
704 | + return reply.Status; | |
705 | + } | |
706 | + | |
707 | + /// <summary> | |
708 | + /// Ping | |
709 | + /// </summary> | |
710 | + /// <param name="hostNameOrAddress">Ip, vagy host név</param> | |
711 | + /// <param name="timeOut">timeout</param> | |
712 | + /// <returns>PingReply</returns> | |
713 | + public static PingReply Ping(string hostNameOrAddress, int timeOut = 1000) | |
714 | + { | |
715 | + Ping ping = new Ping(); | |
716 | + return ping.Send(hostNameOrAddress, timeOut); | |
717 | + } | |
718 | + | |
719 | + /// <summary> | |
720 | + /// Ping specifikált adatokkal | |
721 | + /// </summary> | |
722 | + /// <param name="hostNameOrAddress">Ip, vagy host név</param> | |
723 | + /// <param name="timeOut">timeout</param> | |
724 | + /// <param name="buffer">ping adatok</param> | |
725 | + /// <returns>PingReply</returns> | |
726 | + public static PingReply Ping(string hostNameOrAddress, int timeOut, byte[] buffer) | |
727 | + { | |
728 | + if (buffer.Length > 65500) | |
729 | + { | |
730 | + throw new ArgumentException("Ping data too big! Maximum 65500 bytes allowed!"); | |
731 | + } | |
732 | + Ping ping = new Ping(); | |
733 | + return ping.Send(hostNameOrAddress, timeOut, buffer); | |
734 | + } | |
735 | + | |
736 | + /// <summary> | |
737 | + /// Ping specifikált adatokkal és beállításokkal (PingOptions) | |
738 | + /// </summary> | |
739 | + /// <param name="hostNameOrAddress">Ip, vagy host név</param> | |
740 | + /// <param name="timeOut">timeout</param> | |
741 | + /// <param name="buffer">ping adatok</param> | |
742 | + /// <param name="options">ping beállítások</param> | |
743 | + /// <returns>PingReply</returns> | |
744 | + public static PingReply Ping(string hostNameOrAddress, int timeOut, byte[] buffer, PingOptions options) | |
745 | + { | |
746 | + if (buffer.Length > 65500) | |
747 | + { | |
748 | + throw new ArgumentException("Ping data too big! Maximum 65500 bytes allowed!"); | |
749 | + } | |
750 | + Ping ping = new Ping(); | |
751 | + return ping.Send(hostNameOrAddress, timeOut, buffer, options); | |
752 | + } | |
753 | + } | |
754 | + /// <summary> | |
755 | + /// IPv4 kezeléssel kapcsolatos eszközök | |
756 | + /// </summary> | |
757 | + public static class IPv4Tool | |
758 | + { | |
759 | + /// <summary> | |
760 | + /// Visszad egy IPAddress osztályt, amit a megadott byte értékekből épít fel | |
761 | + /// </summary> | |
762 | + /// <param name="ip"></param> | |
763 | + /// <returns></returns> | |
764 | + public static IPAddress BuildIPAddress(params byte[] ip) | |
765 | + { | |
766 | + if (ip.Length != 4) | |
767 | + { | |
768 | + throw new ArgumentException("Invalid IP! Specific 4 byte value for valid IP address!"); | |
769 | + } | |
770 | + return new IPAddress(ip); | |
771 | + } | |
772 | + | |
773 | + public static IPAddress BuildIPAddress(string ipOrHostname) | |
774 | + { | |
775 | + IPAddress ip; | |
776 | + | |
777 | + if (IPAddress.TryParse(ipOrHostname, out ip)) | |
778 | + { | |
779 | + // IP | |
780 | + return ip; | |
781 | + } | |
782 | + else | |
783 | + { | |
784 | + // Hostname | |
785 | + try | |
786 | + { | |
787 | + IPHostEntry hostEntry; | |
788 | + hostEntry = Dns.GetHostEntry(ipOrHostname); | |
789 | + foreach (var address in hostEntry.AddressList) | |
790 | + { | |
791 | + if (address.AddressFamily == AddressFamily.InterNetwork) | |
792 | + { | |
793 | + return address; | |
794 | + } | |
795 | + } | |
796 | + throw new ArgumentException(String.Format("Bad input argument! (Argument is not Ip or DNS resorvable host name.)", ipOrHostname)); | |
797 | + } | |
798 | + catch (Exception ex) | |
799 | + { | |
800 | + throw new ArgumentException(String.Format("Bad input argument! (Argument is not Ip or DNS resorvable host name.)", ipOrHostname), ex); | |
801 | + } | |
802 | + } | |
803 | + } | |
804 | + } | |
805 | + | |
806 | + /// <summary> | |
807 | + /// MAC address lekérdezése IP alapján | |
808 | + /// </summary> | |
809 | + public static class MACTool | |
810 | + { | |
811 | + /// <summary> | |
812 | + /// Gets the MAC address (<see cref="PhysicalAddress"/>) associated with the specified IP. | |
813 | + /// </summary> | |
814 | + /// <param name="ipAddress">The remote IP address.</param> | |
815 | + /// <returns>The remote machine's MAC address.</returns> | |
816 | + public static PhysicalAddress GetMacAddress(IPAddress ipAddress) | |
817 | + { | |
818 | + const int MacAddressLength = 6; | |
819 | + int length = MacAddressLength; | |
820 | + var macBytes = new byte[MacAddressLength]; | |
821 | + SendARP(BitConverter.ToInt32(ipAddress.GetAddressBytes(), 0), 0, macBytes, ref length); | |
822 | + return new PhysicalAddress(macBytes); | |
823 | + } | |
824 | + | |
825 | + public static PhysicalAddress GetMacAddress(string ipAddressOrHostName) | |
826 | + { | |
827 | + return MACTool.GetMacAddress(IPv4Tool.BuildIPAddress(ipAddressOrHostName)); | |
828 | + } | |
829 | + | |
830 | + public static PhysicalAddress GetMacAddress(params byte[] ipAddress) | |
831 | + { | |
832 | + return MACTool.GetMacAddress(IPv4Tool.BuildIPAddress(ipAddress)); | |
833 | + } | |
834 | + | |
835 | + public static string ToString(this PhysicalAddress mac, char byteSeparator) | |
836 | + { | |
837 | + return HexString.ByteArrayToHexViaLookup32(mac.GetAddressBytes(), byteSeparator); | |
838 | + } | |
839 | + | |
840 | + /// <summary> | |
841 | + /// Netbiostól kér a mac címet, csak netbiost megvalósító eszközökre működik!!! | |
842 | + /// Elég lassú... | |
843 | + /// </summary> | |
844 | + /// <param name="ipAddress"></param> | |
845 | + /// <returns></returns> | |
846 | + public static string GetMacAddressFromNetBios(string ipAddress) | |
847 | + { | |
848 | + string macAddress = string.Empty; | |
849 | + | |
850 | + if (!PingTool.IsHostAccessible(ipAddress)) | |
851 | + { | |
852 | + return String.Empty; | |
853 | + } | |
854 | + try | |
855 | + { | |
856 | + ProcessStartInfo processStartInfo = new ProcessStartInfo(); | |
857 | + Process process = new Process(); | |
858 | + if (Environment.Is64BitOperatingSystem) | |
859 | + { | |
860 | + string filePath = Environment.GetFolderPath(Environment.SpecialFolder.Windows) + "\\sysnative"; | |
861 | + processStartInfo.FileName = Path.Combine(filePath, "nbtstat"); | |
862 | + } | |
863 | + else | |
864 | + { | |
865 | + processStartInfo.FileName = "nbtstat"; | |
866 | + } | |
867 | + processStartInfo.RedirectStandardInput = false; | |
868 | + processStartInfo.RedirectStandardOutput = true; | |
869 | + processStartInfo.Arguments = "-a " + ipAddress; | |
870 | + processStartInfo.UseShellExecute = false; | |
871 | + process = Process.Start(processStartInfo); | |
872 | + string line = null; | |
873 | + do | |
874 | + { | |
875 | + line = macAddress = process.StandardOutput.ReadLine(); | |
876 | + if (line != null) | |
877 | + { | |
878 | + if (macAddress.Trim().ToLower().IndexOf("mac address", 0) > -1) | |
879 | + { | |
880 | + macAddress = line; | |
881 | + break; | |
882 | + } | |
883 | + } | |
884 | + } while (line != null); | |
885 | + process.WaitForExit(); | |
886 | + if (macAddress.IndexOf('=') > -1) | |
887 | + { | |
888 | + macAddress = macAddress.Substring(macAddress.IndexOf('=') + 1); | |
889 | + } | |
890 | + macAddress = macAddress.Trim(); | |
891 | + } | |
892 | + catch (Exception e) | |
893 | + { | |
894 | + // Something unexpected happened? Inform the user | |
895 | + // The possibilities are: | |
896 | + // 1.That the machine is not on the network currently | |
897 | + // 2. The IP address/hostname supplied are not on the same network | |
898 | + // 3. The host was not found on the same subnet or could not be | |
899 | + // resolved | |
900 | + } | |
901 | + return macAddress; | |
902 | + } | |
903 | + | |
904 | + /// <summary> | |
905 | + /// ARP query kiküldése | |
906 | + /// </summary> | |
907 | + /// <param name="DestIP"></param> | |
908 | + /// <param name="SrcIP"></param> | |
909 | + /// <param name="pMacAddr"></param> | |
910 | + /// <param name="PhyAddrLen"></param> | |
911 | + /// <returns></returns> | |
912 | + // http://www.codeproject.com/KB/IP/host_info_within_network.aspx | |
913 | + [System.Runtime.InteropServices.DllImport("iphlpapi.dll", ExactSpelling = true)] | |
914 | + static extern int SendARP(int DestIP, int SrcIP, byte[] pMacAddr, ref int PhyAddrLen); | |
915 | + } | |
916 | + | |
917 | + | |
918 | + public static class HexString | |
919 | + { | |
920 | + private static readonly uint[] _lookup32 = CreateLookup32(); | |
921 | + | |
922 | + private static uint[] CreateLookup32() | |
923 | + { | |
924 | + var result = new uint[256]; | |
925 | + for (int i = 0; i < 256; i++) | |
926 | + { | |
927 | + string s = i.ToString("X2"); | |
928 | + result[i] = ((uint)s[0]) + ((uint)s[1] << 16); | |
929 | + } | |
930 | + return result; | |
931 | + } | |
932 | + | |
933 | + public static string ByteArrayToHexViaLookup32(byte[] bytes, char separator) | |
934 | + { | |
935 | + var lookup32 = _lookup32; | |
936 | + byte multipier = 2; | |
937 | + int length = bytes.Length * 2; | |
938 | + if (separator != '\0') | |
939 | + { | |
940 | + length = bytes.Length * 3 - 1; | |
941 | + multipier = 3; | |
942 | + } | |
943 | + var result = new char[length]; | |
944 | + for (int i = 0; i < bytes.Length; i++) | |
945 | + { | |
946 | + var val = lookup32[bytes[i]]; | |
947 | + result[multipier * i] = (char)val; | |
948 | + result[multipier * i + 1] = (char)(val >> 16); | |
949 | + if (separator != '\0' && i != bytes.Length - 1) | |
950 | + { | |
951 | + result[multipier * i + 2] = separator; | |
952 | + } | |
953 | + } | |
954 | + return new string(result); | |
955 | + } | |
956 | + } | |
957 | +} | |
0 | 958 | \ No newline at end of file | ... | ... |
Vrh.Log4Pro.MaintenanceConsole/Manager - BackupPackageManager.cs
... | ... | @@ -81,8 +81,8 @@ namespace Vrh.Log4Pro.MaintenanceConsole.BackupPackageManagerNS |
81 | 81 | if (!Directory.Exists(destinationfolder)) { Directory.CreateDirectory(destinationfolder); } |
82 | 82 | |
83 | 83 | var destinationfilename = Path.GetFileNameWithoutExtension(bp.Xml_PackageFilePath); |
84 | - var temprootfolder=string.IsNullOrEmpty(bp.Xml_TempDirectoryPath) ? destinationfolder : bp.Xml_TempDirectoryPath; | |
85 | - string tempfolderpath = Path.Combine(temprootfolder, destinationfilename); | |
84 | + var temprootfolder =string.IsNullOrEmpty(bp.Xml_TempDirectoryPath) ? destinationfolder : bp.Xml_TempDirectoryPath; | |
85 | + string tempfolderpath = Path.Combine(temprootfolder, Path.GetRandomFileName()); // destinationfilename | |
86 | 86 | |
87 | 87 | if (Directory.Exists(tempfolderpath)) { Directory.Delete(tempfolderpath, true); } |
88 | 88 | if (!Directory.Exists(tempfolderpath)) { Directory.CreateDirectory(tempfolderpath); } | ... | ... |
Vrh.Log4Pro.MaintenanceConsole/Manager - MaintenanceToolManager.cs
... | ... | @@ -21,6 +21,7 @@ using Vrh.Log4Pro.MaintenanceConsole.ToolsNS; |
21 | 21 | using Vrh.XmlProcessing; |
22 | 22 | using System.Xml.Linq; |
23 | 23 | using System.Text.RegularExpressions; |
24 | +using System.Net; | |
24 | 25 | |
25 | 26 | namespace Vrh.Log4Pro.MaintenanceConsole.MaintenanceToolManagerNS |
26 | 27 | { |
... | ... | @@ -39,6 +40,7 @@ namespace Vrh.Log4Pro.MaintenanceConsole.MaintenanceToolManagerNS |
39 | 40 | |
40 | 41 | var menufunctions = new Menu("Maintenance Tools", "Select function!") |
41 | 42 | .AddMenuItem(new Menu.Item(CLP.Module.MaintenanceToolManager.Functions.RegexTester.KEY, "Regex tester", RegexTester,new Menu.ExecutorParameter(cfg:config))) |
43 | + .AddMenuItem(new Menu.Item(CLP.Module.MaintenanceToolManager.Functions.TCPIPTester.KEY, "TcpIp Tester", TcpIpTester, new Menu.ExecutorParameter(cfg: config, null))) | |
42 | 44 | .AddMenuItem(new Menu.Item(CLP.Module.MaintenanceToolManager.Functions.Tool.KEY, "Tool sample", Tool2, new Menu.ExecutorParameter(cfg: config, null))) |
43 | 45 | .SetSelectionMode(Menu.SelectionMode.Single); |
44 | 46 | foreach (var x in config.ExternalUtilityConfigList) |
... | ... | @@ -100,10 +102,179 @@ namespace Vrh.Log4Pro.MaintenanceConsole.MaintenanceToolManagerNS |
100 | 102 | } |
101 | 103 | #endregion RegexTester |
102 | 104 | |
105 | + #region TcpIpTester | |
106 | + private static List<Pinger> PingerList = new List<Pinger>(); | |
107 | + private static object TcpIpTester(object parameter, object o) | |
108 | + { | |
109 | + var config = (parameter as Menu.ExecutorParameter).GetConfig<MaintenanceToolsXmlProcessor>(); | |
110 | + var pingerconfigxml = config.PingerConfigXml; | |
111 | + var iplist = config.PingerIpAddressList; | |
112 | + DisplayPingerParameters(pingerconfigxml); | |
113 | + var firstrun = true; | |
114 | + var suppresserroneousipaddresses = false; | |
115 | + while (true) | |
116 | + { | |
117 | + DisplayAllPingerStatus(pingerconfigxml,iplist, suppresserroneousipaddresses); | |
118 | + suppresserroneousipaddresses = true; | |
119 | + if (!firstrun) { DisplayPingerCommands(); } | |
120 | + | |
121 | + var command = firstrun ? "STARTANDSHOW *" : ColorConsole.ReadLine(); | |
122 | + if (command == "EX") { break; } | |
123 | + if (command == "") { continue; } | |
124 | + var cmdarray = command.Split(' '); | |
125 | + if (cmdarray.Length!=2) { ColorConsole.WriteLine($"Incorrect answer!", ConsoleColor.Red); continue; } | |
126 | + var cmd = cmdarray[0]; | |
127 | + var inpip = cmdarray[1]; | |
128 | + | |
129 | + List<Pinger> selectedpingers; | |
130 | + if (inpip=="ALL" || inpip =="*") { selectedpingers = PingerList; } | |
131 | + else | |
132 | + { | |
133 | + var pinger = PingerList.FirstOrDefault(x => x.HostNameOrAddress == inpip); | |
134 | + if (pinger == null) { ColorConsole.WriteLine($"IP does not exist.", ConsoleColor.Red); continue; } | |
135 | + selectedpingers = new List<Pinger>() { pinger }; | |
136 | + } | |
137 | + | |
138 | + if (cmd.ToLower() == "start") { StartPingers(selectedpingers, pingerconfigxml); } | |
139 | + if (cmd.ToLower() == "startandshow") { StartPingers(selectedpingers, pingerconfigxml); DisplayPingerHistory(selectedpingers); } | |
140 | + else if (cmd.ToLower() == "stop") { StopPingers(selectedpingers); } | |
141 | + else if (cmd.ToLower() == "drop") { DisposePingers(selectedpingers); } | |
142 | + else if (cmd.ToLower() == "show") { DisplayPingerHistory(selectedpingers); } | |
143 | + else { ColorConsole.WriteLine($"Incorrect answer!", ConsoleColor.Red); continue; } | |
144 | + firstrun = false; | |
145 | + } | |
146 | + | |
147 | + ColorConsole.ReadLine($"{nameof(TcpIpTester)} completed...", ConsoleColor.Yellow); | |
148 | + return o; | |
149 | + } | |
150 | + private static void StartPingers(List<Pinger> selectedpingers, XElement pingerconfigxml) | |
151 | + { | |
152 | + foreach (var pinger in selectedpingers) { pinger.Start(pingerconfigxml); } | |
153 | + } | |
154 | + private static void StopPingers(List<Pinger> selectedpingers) | |
155 | + { | |
156 | + foreach (var pinger in selectedpingers) { pinger.Stop(); } | |
157 | + } | |
158 | + private static void DisposePingers(List<Pinger> selectedpingers) | |
159 | + { | |
160 | + foreach (var pinger in selectedpingers) { pinger.Dispose(); } | |
161 | + } | |
162 | + | |
163 | + private static void DisplayPingerCommands() | |
164 | + { | |
165 | + ColorConsole.WriteLine($"Enter 'START [ip address]' to start/restart pinging.", ConsoleColor.Yellow); | |
166 | + ColorConsole.WriteLine($"Enter 'STOP [ip address]' to stop pinging.", ConsoleColor.Yellow); | |
167 | + ColorConsole.WriteLine($"Enter 'DROP [ip address]' to drop collected data.", ConsoleColor.Yellow); | |
168 | + ColorConsole.WriteLine($"Enter 'SHOW [ip address]' to start monitoring .", ConsoleColor.Yellow); | |
169 | + ColorConsole.WriteLine($"Set [ip address] to 'ALL' or '*' for action to all ip addresses.", ConsoleColor.Yellow); | |
170 | + } | |
171 | + | |
172 | + private static void DisplayPingerParameters(XElement pingerconfigxml) | |
173 | + { | |
174 | + ColorConsole.WriteLine($"Pinger configuration parameters:", ConsoleColor.Yellow); | |
175 | + var pconfig = new Pinger("127.0.0.1", pingerconfigxml).Configuration; | |
176 | + ColorConsole.WriteLine(pconfig.pingtimeout.ToString(), ConsoleColor.Yellow, prefix: " pingtimeout :", suffix: "ms"); | |
177 | + ColorConsole.WriteLine(pconfig.pingcyclenumofpackages.ToString(), ConsoleColor.Yellow, prefix: " pings per cycle:", suffix: "pings"); | |
178 | + ColorConsole.WriteLine((pconfig.pingcyclefrequency / 1000).ToString(), ConsoleColor.Yellow, prefix: " cycle frequency:", suffix: "sec"); | |
179 | + ColorConsole.WriteLine((pconfig.pingeractivlength / 60000).ToString(), ConsoleColor.Yellow, prefix: " pinger liftime :", suffix: "min"); | |
180 | + ColorConsole.WriteLine((pconfig.pingerhistorylength / 60000).ToString(), ConsoleColor.Yellow, prefix: " history length :", suffix: "min"); | |
181 | + ColorConsole.WriteLine($"Pinger status for the following addresses:", ConsoleColor.Yellow); | |
182 | + } | |
183 | + private static void DisplayPingerHistory(List<Pinger> selectedpingers) | |
184 | + { | |
185 | + ColorConsole.WriteLine(); | |
186 | + var cursorleftposition = ColorConsole.CursorLeft; | |
187 | + var cursortopposition = ColorConsole.CursorTop; | |
188 | + while (true) | |
189 | + { | |
190 | + var pingcyclefrequency = 0; | |
191 | + ColorConsole.SetCursorPosition(cursorleftposition, cursortopposition); | |
192 | + var monitorcyclestart = DateTime.Now; | |
193 | + foreach (var pinger in selectedpingers) { pingcyclefrequency=DisplayOnePingerHistory(pinger); if (ColorConsole.KeyAvailable) { goto finishdisplayhistory; };} | |
194 | + var elapsed = DateTime.Now.Subtract(monitorcyclestart).TotalMilliseconds; | |
195 | + if (elapsed < pingcyclefrequency) { Thread.Sleep((int)((double)pingcyclefrequency - elapsed)); } | |
196 | + ColorConsole.WriteLine(); | |
197 | + ColorConsole.WriteLine($"Press any key to exit from monitoring...", ConsoleColor.Yellow); | |
198 | + } | |
199 | + finishdisplayhistory:; | |
200 | + } | |
201 | + private static int DisplayOnePingerHistory(Pinger pinger) | |
202 | + { | |
203 | + var _h = pinger.GetHistory(); | |
204 | + if (_h == null) { return 0; } | |
205 | + var h = new Pinger.PingHistory(pinger.GetHistory());//klónozzuk, mert egyébként ha az adatgyűjtés miatt megváltozik akkor exception-re fut a foreach | |
206 | + ColorConsole.Write(pinger.HostNameOrAddress, ConsoleColor.Yellow, suffix: ": "); | |
207 | + var pingerstatus = pinger.Operating ? "pinging" : "still"; | |
208 | + var pingerstatuscolor = pinger.Operating ? ConsoleColor.Green : ConsoleColor.Yellow; | |
209 | + ColorConsole.Write(pingerstatus.PadRight(10), pingerstatuscolor); | |
210 | + | |
211 | + var lc = h.PingStateQueue.LastOrDefault(); | |
212 | + if (lc != null) | |
213 | + { | |
214 | + var responseinfo = lc.StatusCategory != Pinger.PingCycle.IPStatusCategory.Success ? $"{lc.StatusCategory}" : $"RT:{lc.RoundtripTime} [{lc.RoundtripTimeMin}<{lc.RoundtripTimeAverage}<{lc.RoundtripTimeMax}]ms, LP:{lc.PackagesSentCategory}"; | |
215 | + responseinfo=responseinfo.PadRight(35)+" "; | |
216 | + ColorConsole.Write(responseinfo, GetPingCycleDisplayColor(lc)); | |
217 | + | |
218 | + foreach (var he in h.PingStateQueue) | |
219 | + { | |
220 | + var pcd = GetPingCycleDisplayCharacter(he); | |
221 | + var pcdc=GetPingCycleDisplayColor(he); | |
222 | + for (var i = 0; i < he.NumberOfCycles; i++) { ColorConsole.Write(pcd, pcdc); } | |
223 | + if (ColorConsole.KeyAvailable) { goto finishdisplayhistory; }; | |
224 | + } | |
225 | + } | |
226 | + finishdisplayhistory: | |
227 | + ColorConsole.WriteLine(); | |
228 | + return h.PingCycleFrequency; | |
229 | + } | |
230 | + private static string GetPingCycleDisplayCharacter(Pinger.PingCycle he) { return he.StatusCategory != Pinger.PingCycle.IPStatusCategory.Success ? "9" : he.RoundtripTimeCategory.ToString().Substring(1); } | |
231 | + private static ConsoleColor GetPingCycleDisplayColor(Pinger.PingCycle pingcycle) | |
232 | + { | |
233 | + return pingcycle.StatusCategory != Pinger.PingCycle.IPStatusCategory.Success ? ConsoleColor.Red | |
234 | + : pingcycle.PackagesSentCategory == Pinger.PingCycle.LostPackageCategory.Excellent ? ConsoleColor.DarkGreen | |
235 | + : pingcycle.PackagesSentCategory == Pinger.PingCycle.LostPackageCategory.Good ? ConsoleColor.Green | |
236 | + : pingcycle.PackagesSentCategory == Pinger.PingCycle.LostPackageCategory.Acceptable ? ConsoleColor.DarkYellow | |
237 | + : pingcycle.PackagesSentCategory == Pinger.PingCycle.LostPackageCategory.Bad ? ConsoleColor.Yellow | |
238 | + : ConsoleColor.Red; | |
239 | + } | |
240 | + private static void DisplayAllPingerStatus(XElement pingerconfigxml,List<MaintenanceToolsXmlProcessor.IPAddressParsingResult> iplist, bool suppresserroneousipaddresses=false) | |
241 | + { | |
242 | + foreach (var ip in iplist) { DisplayOnePingerStatus(ip, pingerconfigxml, suppresserroneousipaddresses); } | |
243 | + } | |
244 | + private static void DisplayOnePingerStatus(MaintenanceToolsXmlProcessor.IPAddressParsingResult ip, XElement pingerconfigxml,bool suppresserroneousipaddresses = false) | |
245 | + { | |
246 | + if (ip.GoodIP) | |
247 | + { | |
248 | + ColorConsole.Write($"{ip.IP}", ConsoleColor.Green); | |
249 | + | |
250 | + var pingerlist = PingerList.Select(x => x.HostNameOrAddress).ToList(); | |
251 | + Pinger pinger; | |
252 | + if (pingerlist.Contains(ip.IP.ToString())) | |
253 | + { | |
254 | + pinger = PingerList.FirstOrDefault(x => x.HostNameOrAddress == ip.IP.ToString()); | |
255 | + ColorConsole.Write($" Pinger exist.", ConsoleColor.Green); | |
256 | + } | |
257 | + else | |
258 | + { | |
259 | + pinger = new Pinger(ip.IP.ToString(), pingerconfigxml); | |
260 | + PingerList.Add(pinger); | |
261 | + ColorConsole.Write($" Pinger created.", ConsoleColor.Green); | |
262 | + } | |
263 | + | |
264 | + if (pinger.Operating) { ColorConsole.Write($" Pinger running.", ConsoleColor.Green); } | |
265 | + else { ColorConsole.Write($" Pinger still.", ConsoleColor.Green); } | |
266 | + ColorConsole.WriteLine(); | |
267 | + } | |
268 | + else { if (!suppresserroneousipaddresses) { ColorConsole.WriteLine(ip.ErrorMessage, ConsoleColor.Red); } } | |
269 | + } | |
270 | + #endregion TcpIpTester | |
271 | + | |
272 | + | |
103 | 273 | #region Tool templates |
104 | 274 | private static object Tool2(object parameter, object o) |
105 | 275 | { |
106 | - var config = parameter as MaintenanceToolsXmlProcessor; | |
276 | + var config = (parameter as Menu.ExecutorParameter).GetConfig<MaintenanceToolsXmlProcessor>(); | |
277 | + var regexptesterconfig = config.RegexpTesterConfig; | |
107 | 278 | ColorConsole.ReadLine($"{nameof(Tool2)} is not ready yet...", ConsoleColor.Yellow); |
108 | 279 | return o; |
109 | 280 | } |
... | ... | @@ -134,12 +305,42 @@ namespace Vrh.Log4Pro.MaintenanceConsole.MaintenanceToolManagerNS |
134 | 305 | public bool Valid; |
135 | 306 | } |
136 | 307 | public XElement RegexpTesterConfig; |
308 | + public XElement PingerConfigXml; | |
309 | + public class IPAddressParsingResult | |
310 | + { | |
311 | + public IPAddress IP; | |
312 | + public bool GoodIP; | |
313 | + public string ErrorMessage; | |
314 | + public IPAddressParsingResult(IPAddress ip,bool result, string errormessage=null) { IP = ip;GoodIP = result; ErrorMessage = errormessage; } | |
315 | + } | |
316 | + public List<IPAddressParsingResult> PingerIpAddressList; | |
137 | 317 | public List<ExternalUtilityConfig> ExternalUtilityConfigList = new List<ExternalUtilityConfig>(); |
138 | 318 | |
139 | 319 | #region constructor |
140 | 320 | public MaintenanceToolsXmlProcessor(string xmlcs, string basefolder, string lcid) : base(xmlcs, basefolder, lcid, null) |
141 | 321 | { |
142 | 322 | RegexpTesterConfig = GetXElement(nameof(XmlStructure.RegexpTester)); |
323 | + | |
324 | + var TcpIpTesterXml = GetXElement(nameof(XmlStructure.TcpIpTester)); | |
325 | + if (TcpIpTesterXml != null) | |
326 | + { | |
327 | + PingerConfigXml = GetXElement(TcpIpTesterXml, nameof(XmlStructure.TcpIpTester.Pinger)); | |
328 | + var iplistinstring = GetXElement(TcpIpTesterXml, nameof(XmlStructure.TcpIpTester.IPAddresses))?.Value; | |
329 | + List<string> iplist; | |
330 | + PingerIpAddressList = new List<IPAddressParsingResult>(); | |
331 | + if (!string.IsNullOrWhiteSpace(iplistinstring)) | |
332 | + { | |
333 | + iplist = iplistinstring.Split(new char[] { ' ','/', ',', ';', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries).ToList(); | |
334 | + foreach (var ipcandidate in iplist) | |
335 | + { | |
336 | + var ipc=ipcandidate.Trim(); | |
337 | + if (!IPAddress.TryParse(ipc, out IPAddress IP)) { PingerIpAddressList.Add(new IPAddressParsingResult(IP,false, $"{ipc} Format incorrect!")); } | |
338 | + else if (PingerIpAddressList.Select(x=>x.IP).ToList().Contains(IP)) { PingerIpAddressList.Add(new IPAddressParsingResult(IP, false, $"{ipc} Duplicated IP address!")); } | |
339 | + else { PingerIpAddressList.Add(new IPAddressParsingResult(IP,true)); }; | |
340 | + } | |
341 | + } | |
342 | + } | |
343 | + | |
143 | 344 | var euElementList = GetAllXElements(nameof(XmlStructure.ExternalUtility)); |
144 | 345 | foreach (var euElement in euElementList) { var euc = new ExternalUtilityConfig(euElement); if (euc.Valid && !ExternalUtilityConfigList.Exists(x=>x.Key==euc.Key)) { ExternalUtilityConfigList.Add(euc); } } |
145 | 346 | } |
... | ... | @@ -159,6 +360,18 @@ namespace Vrh.Log4Pro.MaintenanceConsole.MaintenanceToolManagerNS |
159 | 360 | public static class WaitForExit { public static class Values { public static bool DEFAULT = true; } } |
160 | 361 | } |
161 | 362 | } |
363 | + public static class TcpIpTester | |
364 | + { | |
365 | + public static class Pinger | |
366 | + { | |
367 | + public static class PingTimeout { } | |
368 | + public static class PingCycleFrequency { } | |
369 | + public static class PingCycleNumOfPackages { } | |
370 | + public static class PingerActiveLength { } | |
371 | + public static class PingerHistoryLength { } | |
372 | + } | |
373 | + public static class IPAddresses{ } | |
374 | + } | |
162 | 375 | } |
163 | 376 | #endregion XmlStructure |
164 | 377 | } | ... | ... |
Vrh.Log4Pro.MaintenanceConsole/Manager - SQLDataBaseManager.cs
... | ... | @@ -833,7 +833,7 @@ namespace Vrh.Log4Pro.MaintenanceConsole.SQLDataBaseManagerNS |
833 | 833 | vars[nameof(DBSubstitutionName.DBDATAGROUP)] = ""; |
834 | 834 | string zipfilename = VRH.Common.StringConstructor.ResolveConstructorR(vars, backupfilenamemask, "{}@@") + ".zip"; |
835 | 835 | zipfilefullpath = Path.Combine(backupdirectorypath, zipfilename); |
836 | - tempbackupdirectorypath = Path.Combine(backupdirectorypath, "TEMP_" + Path.GetFileNameWithoutExtension(zipfilename)); | |
836 | + tempbackupdirectorypath = Path.Combine(backupdirectorypath, Path.GetRandomFileName()); | |
837 | 837 | if (Directory.Exists(tempbackupdirectorypath)) { Directory.Delete(tempbackupdirectorypath, recursive: true); } |
838 | 838 | if (!Directory.Exists(tempbackupdirectorypath)) { Directory.CreateDirectory(tempbackupdirectorypath); } |
839 | 839 | } |
... | ... | @@ -950,7 +950,7 @@ namespace Vrh.Log4Pro.MaintenanceConsole.SQLDataBaseManagerNS |
950 | 950 | vars[nameof(DBSubstitutionName.DBONAME)] = ""; |
951 | 951 | vars[nameof(DBSubstitutionName.DBDATAGROUP)] = ""; |
952 | 952 | string zipfilename = VRH.Common.StringConstructor.ResolveConstructorR(vars, backupfilenamemask, "{}@@") + ".zip"; |
953 | - tempbackupdirectorypath = Path.Combine(backupdirectorypath, "TEMP_"+Path.GetFileNameWithoutExtension(zipfilename)); | |
953 | + tempbackupdirectorypath = Path.Combine(backupdirectorypath, Path.GetRandomFileName()); | |
954 | 954 | zipfilefullpath = Path.Combine(backupdirectorypath, zipfilename); |
955 | 955 | if (Directory.Exists(tempbackupdirectorypath)) { Directory.Delete(tempbackupdirectorypath, recursive: true); } |
956 | 956 | if (!Directory.Exists(tempbackupdirectorypath)) { Directory.CreateDirectory(tempbackupdirectorypath); } | ... | ... |
Vrh.Log4Pro.MaintenanceConsole/Properties/AssemblyInfo.cs
... | ... | @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; |
32 | 32 | // You can specify all the values or you can default the Build and Revision Numbers |
33 | 33 | // by using the '*' as shown below: |
34 | 34 | // [assembly: AssemblyVersion("1.0.*")] |
35 | -[assembly: AssemblyVersion("1.7.3.0")] | |
36 | -[assembly: AssemblyFileVersion("1.7.3.0")] | |
35 | +[assembly: AssemblyVersion("1.8.0.0")] | |
36 | +[assembly: AssemblyFileVersion("1.8.0.0")] | ... | ... |
Vrh.Log4Pro.MaintenanceConsole/Vrh.Log4Pro.MaintenanceConsole.csproj
... | ... | @@ -348,6 +348,7 @@ |
348 | 348 | </Reference> |
349 | 349 | </ItemGroup> |
350 | 350 | <ItemGroup> |
351 | + <Compile Include="ConsoleFunction - Tools - TcpIp.cs" /> | |
351 | 352 | <Compile Include="ConsoleFunction - CommandLineParser.cs" /> |
352 | 353 | <Compile Include="ConsoleFunction - ColorConsole.cs" /> |
353 | 354 | <Compile Include="ConsoleFunction - Menu.cs" /> | ... | ... |