I wrote a code in C# that maps logical drives to their physical disks, using WMI (System.Management).
The code working perfectly, but slow like hell.
In my machine (Windows 7 x64, Dual-Core with 3 GB RAM) it runs as least 1 second.
1 second is too slow for me, even 0.1 is more than enough to accomplish.
I more than sore that this functionallity can be done in less than 0.1 second.
Is there any Win32API functions that can help?
Any other suggestions?
this is my code so far:
List<Dictionary<string, string>> results = new List<Dictionary<string, string>>();
using (ManagementClass diskDriveClass = new ManagementClass(#"Win32_Diskdrive"))
{
using (ManagementObjectCollection diskDrives = diskDriveClass.GetInstances())
{
foreach (ManagementObject diskDrive in diskDrives)
{
string deviceId = (string)diskDrive["DeviceId"];
Dictionary<string, string> logicalDisksResults = new Dictionary<string, string>();
Trace.WriteLine(deviceId);
using (ManagementObjectCollection relatedPartitions = diskDrive.GetRelated("Win32_DiskPartition"))
{
foreach (ManagementObject relatedPartition in relatedPartitions)
{
Trace.WriteLine("-\t" + relatedPartition["Name"]);
using (ManagementObjectCollection relatedLogicalDisks = relatedPartition.GetRelated("Win32_LogicalDisk"))
{
foreach (ManagementBaseObject relatedLogicalDisk in
relatedLogicalDisks)
{
Trace.WriteLine("\t-\t" + relatedLogicalDisk["Name"] + " " + relatedLogicalDisk["FileSystem"]);
logicalDisksResults.Add((string)relatedLogicalDisk["Name"], (string)relatedLogicalDisk["FileSystem"]);
}
}
}
}
results.Add(logicalDisksResults);
}
}
}
Well here is some code which at least on my system runs (from an objective point of view) quicker and gives the same results. As the list of drives is barely likely to change on a second by second basis I am not sure why you really care so much, but anyway, see if this makes you happier. You can speed it slightly by removing the code getting Win32_DiskDrive at the start, good luck making it run in 0.1s though :)
Dictionary<string, Dictionary<string, string>> results = new Dictionary<string,Dictionary<string,string>>();
ManagementClass diskPartMap = null;
ManagementObjectCollection diskPartIns = null;
ManagementClass partLogicalMap = null;
ManagementObjectCollection partLogicalIns = null;
try
{
using (ManagementClass diskDriveClass = new ManagementClass("Win32_Diskdrive"))
{
using (ManagementObjectCollection diskDrives = diskDriveClass.GetInstances())
{
foreach (ManagementObject diskDrive in diskDrives)
{
results.Add((string)diskDrive["DeviceId"], new Dictionary<string, string>());
}
}
}
Dictionary<string, ManagementObject> partToDisk = new Dictionary<string, ManagementObject>();
Dictionary<string, ManagementObject> partToLogical = new Dictionary<string, ManagementObject>();
diskPartMap = new ManagementClass("Win32_DiskDriveToDiskPartition");
diskPartIns = diskPartMap.GetInstances();
foreach (ManagementObject diskDrive in diskPartIns)
{
ManagementObject o = new ManagementObject((string)diskDrive["Antecedent"]);
partToDisk.Add((string)diskDrive["Dependent"], o);
}
partLogicalMap = new ManagementClass("Win32_LogicalDiskToPartition");
partLogicalIns = partLogicalMap.GetInstances();
foreach (ManagementObject diskDrive in partLogicalIns)
{
ManagementObject o = new ManagementObject((string)diskDrive["Dependent"]);
string s = (string)diskDrive["Antecedent"];
partToLogical.Add(s, o);
}
foreach (KeyValuePair<string, ManagementObject> pair in partToDisk)
{
string deviceId = (string)pair.Value["DeviceId"];
Dictionary<string, string> dict = null;
if (!results.ContainsKey(deviceId))
{
dict = new Dictionary<string, string>();
results[deviceId] = dict;
}
else
{
dict = results[deviceId];
}
if (partToLogical.ContainsKey(pair.Key))
{
ManagementObject o = partToLogical[pair.Key];
dict.Add((string)o["Name"], (string)o["FileSystem"]);
}
}
}
finally
{
if (diskPartIns != null)
{
diskPartIns.Dispose();
diskPartIns = null;
}
if (diskPartMap != null)
{
diskPartMap.Dispose();
diskPartMap = null;
}
if (partLogicalIns != null)
{
partLogicalIns.Dispose();
partLogicalIns = null;
}
if (partLogicalMap != null)
{
partLogicalMap.Dispose();
partLogicalMap = null;
}
}
This is my final code, x23 faster than the first version, based on tyranid idea to use Win32_LogicalDiskToPartition.
private static Regex _logicalDiskNameRegex = new Regex("(?<=\")[^\"]*(?=\")");
private static Regex _partitionDiskIndexRegex = new Regex("(?<=\"Disk #)\\d+");
public static Dictionary<string, string>[] GetPhisicalHardDiskToDriveLettersMap()
{
DriveInfo[] driveInfoArr = DriveInfo.GetDrives();
DriveInfo lastDriveInfo = null;
Dictionary<string, DriveInfo> driveInfos = new Dictionary<string, DriveInfo>(driveInfoArr.Length);
foreach (DriveInfo driveInfo in driveInfoArr)
{
if (driveInfo.DriveType == DriveType.Fixed)
{
driveInfos.Add(driveInfo.Name.Substring(0, 2), driveInfo);
lastDriveInfo = driveInfo;
}
}
if (driveInfos.Count == 1 && lastDriveInfo != null)
{
return new Dictionary<string, string>[]
{
new Dictionary<string, string>()
{
{lastDriveInfo.Name.Substring(0, 2), lastDriveInfo.DriveFormat}
}
};
}
Dictionary<string, Dictionary<string, string>> results = new Dictionary<string, Dictionary<string, string>>();
using (ManagementClass partLogicalMap = new ManagementClass("Win32_LogicalDiskToPartition"))
{
using (ManagementObjectCollection partLogicalIns = partLogicalMap.GetInstances())
{
foreach (ManagementObject diskDrive in partLogicalIns)
{
bool lazySuccess = false;
string driveName = null;
string driveFileSystem = null;
string physicalHardDisk = null;
string logicalDiskPath = (string)diskDrive["Dependent"];
string partitionPath = (string)diskDrive["Antecedent"];
Trace.WriteLine(logicalDiskPath);
Trace.WriteLine(partitionPath);
Match logicalDiskNameMatch = _logicalDiskNameRegex.Match(logicalDiskPath);
if (logicalDiskNameMatch.Success)
{
Match partitionDiskIndexMatch = _partitionDiskIndexRegex.Match(partitionPath);
if (partitionDiskIndexMatch.Success)
{
try
{
driveName = logicalDiskNameMatch.Value;
physicalHardDisk = partitionDiskIndexMatch.Value;
driveFileSystem = driveInfos[driveName].DriveFormat;
lazySuccess = true;
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
}
}
}
if (!lazySuccess)
{
// old good code but less performance, to be on the safe side if lazy method fails.
ManagementObject logicalDiskObject = new ManagementObject(logicalDiskPath);
ManagementObject partitionObject = new ManagementObject(partitionPath);
driveName = (string)logicalDiskObject["Name"];
driveFileSystem = (string)logicalDiskObject["FileSystem"];
physicalHardDisk = partitionObject["DiskIndex"].ToString();
}
Dictionary<string, string> hardDiskDrives;
if (!results.TryGetValue(physicalHardDisk, out hardDiskDrives))
{
hardDiskDrives = new Dictionary<string, string>();
results.Add(physicalHardDisk, hardDiskDrives);
}
hardDiskDrives.Add(driveName, driveFileSystem);
}
}
}
return ToArray(results.Values);
}
I have found that the best route is to get the full data from each of the 4 classes and then do your joining with LINQ to minimize the impact on the WMI service (as it is slow under load).
As first you might think that sounds horrible, but test it out to see what I am talking about.
see this article (with code sample) about GetLogicalDrives, GetLogicalDriveStrings, GetDriveType, and GetVolumeInformation
To find physical drives, you can use FindFirstVolumeand FindNextVolume (I get "\.\Device{uiid}". Combined with GetVolumePathNamesForVolumeNameW to get the associated drive letter. Then you can get the info you want with above mentioned APIs.
If you need partition/disk numbers see DeviceIoControl to get that info
I thought you needed what is in results in your code.
Related
I'm trying to parse huge json file to 2d array.
I can parse. But required memory is almost 10times.
My sample.json file has 100,000 rows, each with a different item.
If sample.json is 500MB this code need 5GB.
How can i reduce memory usage?
I use Newtonsoft.Json, .Net6.0
Read from json
static void Read()
{
List<Dictionary<string, string>> rows = new List<Dictionary<string, string>>();
string path = #"D:\small.json";
using (FileStream fsRead = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (BufferedStream bsRead = new BufferedStream(fsRead))
using (StreamReader srRead = new StreamReader(bsRead))
{
string? line;
while ((line = srRead.ReadLine()) != null)
{
JObject jsonObject = JObject.Parse(line);
MakeRowData(jsonObject, out var row);
rows.Add(row);
}
}
}
Make row
private static void MakeRowData(JObject jsonData, out Dictionary<string, string> row)
{
Dictionary<string, string> output = new Dictionary<string, string>();
foreach (var item in jsonData)
{
int childSize = 0;
if (item.Value != null)
{
childSize = item.Value.Children().Count();
///if Item has child, explore deep
if (childSize > 0)
{
ExploreChild(item.Value, ref output);
}
///or not just add new item
else
{
string str = item.Value.ToString();
output[item.Key] = str ?? "";
}
}
}
row = output;
}
private static void ExploreChild(JToken jToken, ref Dictionary<string, string> row)
{
foreach (var item in jToken)
{
int childSize = item.Children().Count();
///if Item has child, explore deep
if (childSize > 0)
{
ExploreChild(item, ref row);
}
///or not just add new item
else
{
string path = jToken.Path.Replace('[', '(').Replace(']', ')');
string str = jToken.First.ToString();
row[path] = str?? "";
}
}
}
EDIT
Add Sample.json
It is set of json strings.
And Fields are not fixed.
Sample.json
{Field1:0,Field2:1,Field2:3}
{Field1:0,Field5:1,Field6:3}
{Field1:0,Field7:1,Field9:3}
{Field1:0,Field13:1,Field50:3,Field57:3}
...
You can try replacing the recursive exploring children with the iterative one. Something like this:
private static void MakeRowData(JObject jsonData, out Dictionary<string, string> row)
{
Dictionary<string, string> output = new Dictionary<string, string>();
foreach (var item in jsonData)
{
if (item.Value != null)
{
///if Item has child, explore deep
if (item.Value.HasValues)
{
var queue = new Queue<JToken>();
queue.Enqueue(item.Value);
while (queue.Any())
{
var currItem = queue.Dequeue();
if (currItem.HasValues)
{
foreach(var child in item)
queue.Enqueue(child);
}
else
{
// add item without children to row here
}
}
}
///or not just add new item
else
{
string str = item.Value.ToString();
output[item.Key] = str ?? "";
}
}
}
row = output;
}
Recursive calls, unless it is a tail recursion, keep the stack of a method they were called from. This can lead to extensive memory usage.
I am new here and actually very new to c#.
In a nutshell, I am using c# via Visual Studio, I am calling a data from a database and I want to save these data in a .csv file. The problem now is that I want to save these data on two columns at the same time.
My code do write them in a file but shifted not on the right rows.
Dictionary<string, string> elementNames = new Dictionary<string, string>();
Dictionary<string, string> elementTypes = new Dictionary<string, string>();
var nodes = webservice.nepService.GetAllElementsOfElementType(webservice.ext, "Busbar", ref elementNames, ref elementTypes);
Dictionary<string, string> nodeResults = new Dictionary<string, string>();
Dictionary<string, string> nodeResults1 = new Dictionary<string, string>();
foreach (var nodename in elementNames.Values)
{
var nodeRes = webservice.nepService.GetResultElementByName(webservice.ext, nodename, "Busbar", -1, "LoadFlow", null);
var Uvolt = GetXMLAttribute(nodeRes, "U");
nodeResults.Add(nodename, Uvolt);
var Upercentage = GetXMLAttribute(nodeRes, "Up");
nodeResults1.Add(nodename, Upercentage);
StringBuilder strBldr = new StringBuilder();
string outputFile = #"C:\Users\12.csv";
string separator = ",";
foreach (var res in nodeResults)
{
strBldr.AppendLine($"{res.Key}{separator}{res.Value}");
}
foreach (var res1 in nodeResults1)
{
strBldr.AppendLine($"{separator}{separator}{res1.Value}");
}
File.WriteAllText(outputFile, strBldr.ToString());
}
this is the output of the previous code:
https://ibb.co/T4trQC3
I want these shifted values to move up beside the other values like that:
https://ibb.co/4S25v0h
Thank you
if you look to the code you are using AppendLine
strBldr.AppendLine($"{separator}{separator}{res1.Value}");
and if you want to append on same line just use Append
strBldr.Append($"{separator}{separator}{res1.Value}");
EDITED:
in linq you can use Zip function to zip to lists
// using System.Linq;
var results = Results.Zip(Results1, (firstList, secondList) => firstList.Key + "," + firstList.Value + "," + secondList.Value);
Edit Full example
public static IDictionary<string, string> Results { get; set; }
public static IDictionary<string, string> Results1 { get; set; }
private static void Main(string[] args)
{
StringBuilder strBldr = new StringBuilder();
string outputFile = #"D:\12.csv";
Results = new Dictionary<string, string>()
{
{"N1", "20"},
{"N2", "0.399992"},
{"N3", "0.369442"},
{"N4", "0.369976"}
};
Results1 = new Dictionary<string, string>()
{
{"N1", "100"},
{"N2", "99.9805"},
{"N3", "92.36053"},
{"N4", "92.49407"}
};
IEnumerable<string> results = Results.Zip(Results1,
(firstList, secondList) => firstList.Key + "," + firstList.Value + "," + secondList.Value);
foreach (string res1 in results)
{
strBldr.AppendLine(res1);
}
File.WriteAllText(outputFile, strBldr.ToString());
}
for faster code you can try this
HashSet<Tuple<string, string, string>> values = new HashSet<Tuple<string, string, string>>();
var nodes = webservice.nepService.GetAllElementsOfElementType(webservice.ext, "Busbar", ref elementNames, ref elementTypes);
foreach (var nodename in elementNames.Values)
{
var nodeRes = webservice.nepService.GetResultElementByName(webservice.ext, nodename, "Busbar", -1, "LoadFlow", null);
var Uvolt = GetXMLAttribute(nodeRes, "U");
var Upercentage = GetXMLAttribute(nodeRes, "Up");
values.Add(Tuple.Create(nodename, Uvolt, Upercentage));
}
var output = string.Join("\n", values.ToList().Select(tuple => $"{tuple.Item1},{tuple.Item2},{tuple.Item3}").ToList());
string outputFile = #"C:\Users\12.csv";
File.WriteAllText(outputFile, output);
if the rowCount for Results and Results1 are same and the keys are in the same order, try:
for (int i = 0; i < Results.Count; i++)
strBldr.AppendLine($"{Results[i].Key}{separator}{Results[i].Value}{separator}{Results1[i].Value}");
Or, if the rows are not in the same order, try:
foreach (var res in Results)
strBldr.AppendLine($"{res.Key}{separator}{res.Value}{separator}{Results1.Single(x => x.Key == res.Key).Value}");
I need some kind of structure to add, remove and read (get) some values for some settings.
In PHP I would create sth. like:
["root"]["Audio"]["DuplexMode"] = full;
["root"]["AudioSource"]["A0"]["AudioEncoding"] = g711;
["root"]["Network"]["Interface"]["I0"]["Active"]["MACAddress"] = 00:40:8C:9A:1F:56;
and access it like this:
DuplexMode = ["root"]["Audio"]["DuplexMode"];
AudioEncoding = ["root"]["AudioSource"]["A0"]["AudioEncoding"];
MACAddress = ["root"]["Network"]["Interface"]["I0"]["Active"]["MACAddress"];
...
or
foreach (x in ["root"]["AudioSource"]["A0"]) {...}
should give me all the settings under root.AudioSource.A0.
But this seams not to be possible in C#. (Or at least I don't know how...)
Here is the list of settings which is a quite long string I get from a network-camera. (There are not always the same settings for each device.)
root.Audio.DuplexMode=full
root.Audio.MaxListeners=20
root.Audio.ReceiverBuffer=120
root.Audio.ReceiverTimeout=1000
root.Audio.NbrOfConfigs=1
root.Audio.DSCP=0
root.Audio.A0.Enabled=yes
root.Audio.A0.HTTPMessageType=singlepart
root.Audio.A0.Name=
root.Audio.A0.Source=0
root.Audio.A0.AlarmLevel=50
root.Audio.A0.AlarmResolution=50
root.Audio.A0.AlarmLowLimit=10
root.Audio.A0.AlarmHighLimit=6500
root.AudioSource.NbrOfSources=1
root.AudioSource.A0.Name=Audio
root.AudioSource.A0.AudioEncoding=g711
root.AudioSource.A0.InputType=mic
root.AudioSource.A0.InputGain=auto
root.AudioSource.A0.OutputGain=0
root.AudioSource.A0.SampleRate=8000
root.AudioSource.A0.HWSampleRate=16000
root.AudioSource.A0.BitRate=64000
root.AudioSource.A0.CustomReg=
root.AudioSource.A0.AudioSupport=yes
root.Bandwidth.Limit=0
root.Brand.Brand=AXIS
root.Brand.ProdFullName=AXIS M1031-W Network Camera
root.Brand.ProdShortName=AXIS M1031-W
root.Brand.ProdNbr=M1031-W
root.Brand.ProdType=Network Camera
root.Brand.WebURL=http://www.axis.com/
root.Event.E0.Name=NightLight
root.Event.E0.Type=T
root.Event.E0.Enabled=yes
root.Event.E0.Priority=1
root.Event.E0.Image=0
root.Event.E0.HWInputs=1
root.Event.E0.SWInput=
root.Event.E0.Weekdays=1111111
root.Event.E0.Starttime=19:00
root.Event.E0.Duration=12:00
root.Event.E0.MinimumTriggerInterval=00:00:00
root.Event.E0.MinimumTriggerTimePeriod=00:00:00
root.Event.E0.ImageURLSettingsEnabled=no
root.Event.E0.ImageURLSettings=
root.Event.E0.IncludePreTrigger=no
root.Event.E0.PreTriggerDuration=
root.Event.E0.PreTriggerDurationUnit=s
root.Event.E0.IncludePostTrigger=no
root.Event.E0.PostTriggerDuration=
root.Event.E0.PostTriggerDurationUnit=s
root.Event.E0.IncludeBestEffort=no
root.Event.E0.BestEffortDuration=0
root.Event.E0.BestEffortDurationUnit=s
root.Event.E0.IncludeAudio=no
root.Event.E0.MPEGPreTriggerDuration=5
root.Event.E0.MPEGPostTriggerDuration=2
root.Event.E0.VideoFormat=
root.Event.E0.FrameRate=
root.Event.E0.Actions.A0.Type=N
root.Event.E0.Actions.A0.Protocol=Light
root.Event.E0.Actions.A0.Order=0
root.Event.E0.Actions.A0.Light=1
root.Event.E0.Actions.A0.Activate=100
root.Event.E0.Actions.A0.Inactivate=-0
root.Event.E0.Actions.A0.Duration=30
root.Event.E0.Actions.A0.Unit=s
root.HTTPS.Certificate=none
root.HTTPS.Enabled=no
root.HTTPS.Port=443
root.Image.TriggerDataEnabled=yes
root.Image.ReferrersEnabled=no
root.Image.Referrers=
root.Image.MaxViewers=20
root.Image.MotionDetection=yes
root.Image.NbrOfConfigs=1
root.Image.RFCCompliantMultipartEnabled=yes
root.Image.PrivacyMaskType=mask_windows
root.Image.OverlayPath=/etc/overlays/axis(128x44).ovl
root.Image.DateFormat=YYYY-MM-DD
root.Image.OwnDateFormat=%F
root.Image.OwnDateFormatEnabled=no
root.Image.TimeFormat=24
root.Image.OwnTimeFormat=%T
root.Image.OwnTimeFormatEnabled=no
root.Image.TimeResolution=1
root.Image.I0.Name=
root.Image.I0.Source=0
root.Image.I0.Appearance.Resolution=640x480
root.Image.I0.Appearance.Compression=30
root.Image.I0.Appearance.Rotation=0
root.Image.I0.Appearance.MirrorEnabled=no
root.Image.I0.Appearance.ColorEnabled=yes
root.Image.I0.MPEG.ConfigHeaderInterval=1
root.Image.I0.MPEG.UserDataEnabled=yes
root.Image.I0.MPEG.UserDataInterval=1
root.Image.I0.MPEG.ICount=1
root.Image.I0.MPEG.PCount=14
root.Image.I0.MPEG.Complexity=50
root.Image.I0.MPEG.ResyncMarkerEnabled=yes
root.Image.I0.MPEG.H264.PSEnabled=no
root.Image.I0.Overlay.Enabled=no
root.Image.I0.Overlay.XPos=0
root.Image.I0.Overlay.YPos=0
root.Image.I0.Overlay.MaskWindows.Color=black
root.Image.I0.Overlay.MaskWindows.M0.Enabled=no
root.Image.I0.Overlay.MaskWindows.M0.XPos=303
root.Image.I0.Overlay.MaskWindows.M0.YPos=2
root.Image.I0.Overlay.MaskWindows.M0.Width=160
root.Image.I0.Overlay.MaskWindows.M0.Height=48
root.Image.I0.Overlay.MaskWindows.M0.Name=Mask%200
root.Image.I0.Overlay.MaskWindows.M1.Enabled=no
root.Image.I0.Overlay.MaskWindows.M1.XPos=124
root.Image.I0.Overlay.MaskWindows.M1.YPos=4
root.Image.I0.Overlay.MaskWindows.M1.Width=148
root.Image.I0.Overlay.MaskWindows.M1.Height=56
root.Image.I0.Overlay.MaskWindows.M1.Name=Mask%201
root.Image.I0.Overlay.MaskWindows.M2.Enabled=no
root.Image.I0.Overlay.MaskWindows.M2.XPos=583
root.Image.I0.Overlay.MaskWindows.M2.YPos=52
root.Image.I0.Overlay.MaskWindows.M2.Width=54
root.Image.I0.Overlay.MaskWindows.M2.Height=113
root.Image.I0.Overlay.MaskWindows.M2.Name=Mask%202
root.Image.I0.RateControl.Mode=vbr
root.Image.I0.RateControl.Priority=framerate
root.Image.I0.RateControl.TargetBitrate=0
root.Image.I0.RateControl.MaxFPS=30
root.Image.I0.RateControl.MinFPS=1
root.Image.I0.RateControl.MaxCompression=100
root.Image.I0.RateControl.MinCompression=0
root.Image.I0.RateControl.MaxBitrate=0
root.Image.I0.SizeControl.MaxFrameSize=0
root.Image.I0.SizeControl.DiffFrameSize=0
root.Image.I0.Stream.Duration=0
root.Image.I0.Stream.NbrOfFrames=0
root.Image.I0.Stream.FPS=15
root.Image.I0.Text.DateEnabled=no
root.Image.I0.Text.ClockEnabled=no
root.Image.I0.Text.TextEnabled=no
root.Image.I0.Text.String=ET1
root.Image.I0.Text.Position=top
root.Image.I0.TriggerData.IOEnabled=yes
root.Image.I0.TriggerData.AudioEnabled=yes
root.Image.I0.TriggerData.TamperingEnabled=yes
root.Image.I0.TriggerData.MotionDetectionEnabled=yes
root.Image.I0.TriggerData.MotionLevelEnabled=no
root.Image.I0.TriggerData.UserTriggers=
root.ImageSource.NbrOfSources=1
root.ImageSource.MotionDetection=no
root.ImageSource.I0.Name=Camera
root.ImageSource.I0.Sensor.WhiteBalance=auto
root.ImageSource.I0.Sensor.Exposure=flickerfree50
root.ImageSource.I0.Sensor.MaxExposureTime=10000
root.ImageSource.I0.Sensor.MinExposureTime=10000
root.ImageSource.I0.Sensor.MaxGain=100
root.ImageSource.I0.Sensor.MinGain=0
root.ImageSource.I0.Sensor.ExposureValue=59
root.ImageSource.I0.Sensor.ExposurePriority=50
root.ImageSource.I0.Sensor.ColorDesaturation=100
root.ImageSource.I0.Sensor.Brightness=51
root.ImageSource.I0.Sensor.Contrast=56
root.ImageSource.I0.Sensor.ColorLevel=60
root.ImageSource.I0.Sensor.Sharpness=64
root.ImageSource.I0.Sensor.BacklightCompensation=yes
root.ImageSource.I0.Sensor.DynamicPixelCorrection=yes
root.ImageSource.I0.Sensor.AspectRatio=
root.ImageSource.I0.Sensor.ExposureWindow=auto
root.ImageSource.I0.Sensor.CustomExposureWindow.Weight=100
root.Input.NbrOfInputs=1
root.IOPort.I0.Configurable=no
root.IOPort.I0.Direction=input
root.IOPort.I0.Input.Name=PIR sensor
root.IOPort.I0.Input.Trig=closed
root.Layout.DefaultVideoFormat=mjpeg
root.Layout.ShowVideoFormatDropDown=yes
root.Layout.DefaultStreamProfile=
root.Layout.ViewerIE=activex
root.Layout.ViewerOther=spush
root.Layout.SetupLinkEnabled=yes
root.Layout.SnapshotEnabled=no
root.Layout.PlainConfigEnabled=no
root.Layout.ShowAMCToolbar=yes
root.Layout.AMCRecordMedia=1
root.Layout.Axis=yes
root.Layout.OwnHomePageEnabled=no
root.Layout.OwnHomePagePath=dummy
root.Layout.MPEGInstallationEnabled=yes
root.Layout.H264InstallationEnabled=yes
root.Layout.AACInstallationEnabled=yes
root.Layout.EnableBasicSetup=yes
root.Layout.InstantReplayEnabled=no
root.Layout.InstantReplayTimeOffset=30
root.Layout.PlayAudioClipEnabled=yes
root.Layout.CustomLink.C0.Enabled=no
root.Layout.CustomLink.C0.Name=Custom link 1
root.Layout.CustomLink.C0.URL=http://
root.Layout.CustomLink.C0.Usage=cgi
root.Layout.CustomLink.C1.Enabled=no
root.Layout.CustomLink.C1.Name=Custom link 2
root.Layout.CustomLink.C1.URL=http://
root.Layout.CustomLink.C1.Usage=cgi
root.Layout.CustomLink.C2.Enabled=no
root.Layout.CustomLink.C2.Name=Custom link 3
root.Layout.CustomLink.C2.URL=http://
root.Layout.CustomLink.C2.Usage=cgi
root.Layout.CustomLink.C3.Enabled=no
root.Layout.CustomLink.C3.Name=Custom link 4
root.Layout.CustomLink.C3.URL=http://
root.Layout.CustomLink.C3.Usage=cgi
root.Layout.Trigger.T0.Enabled=no
root.LightControl.L0.Name=Light
root.LightControl.L0.DriverType=pwm
root.LightControl.L0.SourceType=whiteled
root.LightControl.L0.Driver=pa18
root.LightControl.L0.Button=actinact
root.LightControl.L0.Activate=-100
root.LightControl.L0.Inactivate=-0
root.LightControl.L0.PulseTime=0
root.Log.Access.MaxSize=40000
root.Log.Access.Critical=detailed
root.Log.Access.Warning=detailed
root.Log.Access.Informational=off
root.Log.System.MaxSize=40000
root.Log.System.Critical=on
root.Log.System.Warning=on
root.Log.System.Informational=on
root.MailLogd.ToEmail=
root.MailLogd.LogSendLevel=0
root.MediaClip.MaxGroups=10
root.MediaClip.M0.Name=Burglar_Alarm_Short
root.MediaClip.M0.Location=/etc/audioclips/Burglar_Alarm_Short_8bit_32kHz_mono_PCM-16bit-little.wav
root.MediaClip.M0.Type=audio
root.MediaClip.M6.Name=Camera clicks
root.MediaClip.M6.Location=/etc/audioclips/camera_clicks16k.au
root.MediaClip.M6.Type=audio
root.MediaClip.M7.Name=Pssst, Psst!
root.MediaClip.M7.Location=/etc/audioclips/pssst_psst16k.au
root.MediaClip.M7.Type=audio
root.MediaClip.M8.Name=Intruder
root.MediaClip.M8.Location=/etc/audioclips/intruder16k.au
root.MediaClip.M8.Type=audio
root.MediaClip.M9.Name=Dog barking
root.MediaClip.M9.Location=/etc/audioclips/dog_barking16k.au
root.MediaClip.M9.Type=audio
root.Motion.M0.Name=DefaultWindow
root.Motion.M0.ImageSource=0
root.Motion.M0.Left=0
root.Motion.M0.Right=9999
root.Motion.M0.Top=86
root.Motion.M0.Bottom=9998
root.Motion.M0.WindowType=include
root.Motion.M0.Sensitivity=95
root.Motion.M0.History=93
root.Motion.M0.ObjectSize=3
root.Network.Media=auto
root.Network.Autoneg=normal
root.Network.InterfaceSelectMode=auto
root.Network.HostName=axis-00408c9a1f56
root.Network.DNSServer1=192.168.69.251
root.Network.DNSServer2=0.0.0.0
root.Network.tcpECN=1
root.Network.Enabled=yes
root.Network.BootProto=none
root.Network.IPAddress=192.168.68.127
root.Network.SubnetMask=255.255.254.0
root.Network.Broadcast=192.168.69.255
root.Network.DefaultRouter=192.168.69.254
root.Network.DomainName=
root.Network.ARPPingIPAddress.Enabled=yes
root.Network.AxisNS.Enabled=yes
root.Network.AxisNS.LockButton=no
root.Network.AxisNS.UpdatePeriod=1
root.Network.AxisNS.CheckPeriod=10
root.Network.AxisNS.ServerList=www0.axiscam.net,www1.axiscam.net,195.60.68.29,195.60.68.30
root.Network.AxisNS.ServerPath=reg_cam.php
root.Network.AxisNS.ServerLink=www.axiscam.net
root.Network.AxisNS.CheckIPAddress=0.0.0.0
root.Network.AxisNS.CheckTTL=0
root.Network.Bonjour.Enabled=yes
root.Network.Bonjour.FriendlyName=AXIS M1031-W - 00408C9A1F56
root.Network.DHCP.StoreIPAddresseth0=no
root.Network.DHCP.StoreIPAddresseth1=no
root.Network.DHCP.IPCheckEnabled=yes
root.Network.DHCP.VendorClass=AXIS,Network Camera,M1031-W,5.20.1
root.Network.DHCP.Fqdn=
root.Network.DHCP.Timeout=0
root.Network.DHCP.Retries=20
root.Network.DNSUpdate.Enabled=no
root.Network.DNSUpdate.DNSName=Securitec
root.Network.DNSUpdate.TTL=30
root.Network.eth0.MACAddress=00:40:8C:9A:1F:56
root.Network.eth0.IPAddress=192.168.68.127
root.Network.eth0.SubnetMask=255.255.254.0
root.Network.eth0.Broadcast=192.168.69.255
root.Network.eth0.IPv6.IPAddresses=fe80::240:8cff:fe9a:1f56/64
root.Network.Filter.Enabled=no
root.Network.Filter.Input.Policy=allow
root.Network.Filter.Input.AcceptAddresses=
root.Network.Filter.Log.Enabled=yes
root.Network.FTP.Enabled=yes
root.Network.HTTP.AuthenticationPolicy=basic_digest
root.Network.HTTP.AuthenticationPolicySet=yes
root.Network.HTTP.AuthenticationWithQop=no
root.Network.Interface.I0.SystemDevice=eth0
root.Network.Interface.I0.Type=802.3
root.Network.Interface.I0.Active.MACAddress=00:40:8C:9A:1F:56
root.Network.Interface.I0.Active.Active=no
root.Network.Interface.I0.Active.IPAddress=
root.Network.Interface.I0.Active.SubnetMask=
root.Network.Interface.I0.Active.Broadcast=
root.Network.Interface.I0.Active.IPv6Addresses=
root.Network.Interface.I0.dot1x.Enabled=no
root.Network.Interface.I0.dot1x.EAPOLVersion=1
root.Network.Interface.I0.dot1x.Status=Stopped
root.Network.Interface.I0.dot1x.EAPTLS.Identity=xxx
root.Network.Interface.I0.dot1x.EAPTLS.PrivateKeyPassword=*****
root.Network.Interface.I0.Link.MTU=1500
root.Network.Interface.I0.Link.BootProto=none
root.Network.Interface.I0.Link.Media=auto
root.Network.Interface.I0.Link.Autoneg=normal
root.Network.Interface.I0.Link.IPv4Enabled=yes
root.Network.Interface.I0.Link.IPv6Enabled=no
root.Network.Interface.I0.Link.AcceptRA=yes
root.Network.Interface.I0.Link.DHCPv6=auto
root.Network.Interface.I0.Manual.IPAddress=192.168.68.127
root.Network.Interface.I0.Manual.SubnetMask=255.255.254.0
root.Network.Interface.I0.Manual.Broadcast=192.168.69.255
root.Network.Interface.I0.Manual.DefaultRouter=192.168.69.254
root.Network.Interface.I0.Manual.IPv6Address=
root.Network.Interface.I0.Manual.IPv6DefaultRouter=
root.Network.Interface.I0.ZeroConf.Enabled=yes
root.Network.Interface.I0.ZeroConf.IPAddress=
root.Network.Interface.I0.ZeroConf.SubnetMask=
root.Network.Interface.I1.SystemDevice=eth1
root.Network.Interface.I1.Type=802.11
root.Network.Interface.I1.Active.MACAddress=00:40:8C:9A:1F:56
root.Network.Interface.I1.Active.Active=yes
root.Network.Interface.I1.Active.IPAddress=192.168.68.127
root.Network.Interface.I1.Active.SubnetMask=255.255.254.0
root.Network.Interface.I1.Active.Broadcast=192.168.69.255
root.Network.Interface.I1.Active.IPv6Addresses=fe80::240:8cff:fe9a:1f56/64
root.Network.Interface.I1.dot1x.EAPOLVersion=1
root.Network.Interface.I1.dot1x.EAPTLS.Identity=
root.Network.Interface.I1.dot1x.EAPTLS.PrivateKeyPassword=*****
root.Network.Interface.I1.Link.MTU=1500
root.Network.Interface.I1.Link.BootProto=none
root.Network.Interface.I1.Link.IPv4Enabled=yes
root.Network.Interface.I1.Link.IPv6Enabled=no
root.Network.Interface.I1.Link.AcceptRA=yes
root.Network.Interface.I1.Link.DHCPv6=auto
root.Network.Interface.I1.Manual.IPAddress=192.168.68.127
root.Network.Interface.I1.Manual.SubnetMask=255.255.254.0
root.Network.Interface.I1.Manual.Broadcast=192.168.69.255
root.Network.Interface.I1.Manual.DefaultRouter=192.168.69.254
root.Network.Interface.I1.Manual.IPv6Address=
root.Network.Interface.I1.Manual.IPv6DefaultRouter=
root.Network.Interface.I1.ZeroConf.Enabled=yes
root.Network.Interface.I1.ZeroConf.IPAddress=169.254.248.199
root.Network.Interface.I1.ZeroConf.SubnetMask=255.255.0.0
root.Network.IPv6.Enabled=no
root.Network.IPv6.AcceptRA=yes
root.Network.IPv6.DHCPv6=auto
root.Network.IPv6.IPAddress=
root.Network.IPv6.DefaultRouter=
root.Network.QoS.Class1.Desc=AxisLiveVideo
root.Network.QoS.Class1.DSCP=0
root.Network.QoS.Class2.Desc=AxisLiveAudio
root.Network.QoS.Class2.DSCP=0
root.Network.QoS.Class3.Desc=AxisEventAlarm
root.Network.QoS.Class3.DSCP=0
root.Network.QoS.Class4.Desc=AxisManagement
root.Network.QoS.Class4.DSCP=0
root.Network.Resolver.NameServerList=192.168.69.251
root.Network.Resolver.ObtainFromDHCP=no
root.Network.Resolver.Search=
root.Network.Resolver.NameServer1=192.168.69.251
root.Network.Resolver.NameServer2=
root.Network.Routing.DefaultRouter=192.168.69.254
root.Network.Routing.IPv6.DefaultRouter=
root.Network.RTP.NbrOfRTPGroups=1
root.Network.RTP.StartPort=50000
root.Network.RTP.EndPort=50999
root.Network.RTP.VideoDSCP=0
root.Network.RTP.AudioDSCP=0
root.Network.RTP.R0.VideoAddress=239.226.31.86
root.Network.RTP.R0.VideoPort=0
root.Network.RTP.R0.AudioAddress=239.226.31.214
root.Network.RTP.R0.AudioPort=0
root.Network.RTP.R0.TTL=5
root.Network.RTSP.Enabled=yes
root.Network.RTSP.Port=554
root.Network.RTSP.Timeout=60
root.Network.RTSP.ProtViewer=password
root.Network.RTSP.AllowPathAsURL=yes
root.Network.RTSP.AuthenticateOverHTTP=no
root.Network.RTSP.AllowClientTransportSettings=no
root.Network.UPnP.Enabled=yes
root.Network.UPnP.FriendlyName=AXIS M1031-W - Office WiFi Cam
root.Network.UPnP.NATTraversal.Enabled=no
root.Network.UPnP.NATTraversal.Router=
root.Network.UPnP.NATTraversal.ExternalIPAddress=
root.Network.UPnP.NATTraversal.Active=no
root.Network.UPnP.NATTraversal.MinPort=32768
root.Network.UPnP.NATTraversal.MaxPort=65535
root.Network.VolatileHostName.ObtainFromDHCP=no
root.Network.VolatileHostName.HostName=axis-00408c9a1f56
root.Network.Wireless.ESSID=SecuriTec
root.Network.Wireless.MODE=managed
root.Network.Wireless.W0.Enabled=yes
root.Network.Wireless.W0.Method=WPA-PSK
root.Network.Wireless.W0.GenerationMethod=psk-phrase
root.Network.Wireless.W0.Passphrase=*****
root.Network.Wireless.W0.Key=
root.Network.Wireless.W1.Enabled=no
root.Network.Wireless.W1.Method=WPA-ENTERPRISE
root.Network.Wireless.W1.Dot1XMethod=EAPTLS
root.Network.Wireless.WEP.Enabled=no
root.Network.Wireless.WEP.KeyLength=128
root.Network.Wireless.WEP.GenerationMethod=manual
root.Network.Wireless.WEP.Passphrase=
root.Network.Wireless.WEP.ActiveKey=1
root.Network.Wireless.WEP.Key1=
root.Network.Wireless.WEP.Key2=
root.Network.Wireless.WEP.Key3=
root.Network.Wireless.WEP.Key4=
root.Network.Wireless.WEP.Authentication=open
root.Network.ZeroConf.Enabled=yes
root.Network.ZeroConf.IPAddress=169.254.248.199
root.Network.ZeroConf.SubnetMask=255.255.0.0
root.Notify.AtBoot=no
root.Notify.TextType=simple
root.Notify.TextField=Your text here
root.Notify.KnownIP=192.168.68.127
root.Notify.KnownIPV6=
root.Notify.FTP.Enabled=no
root.Notify.FTP.HostName=
root.Notify.FTP.UserName=
root.Notify.FTP.Password=
root.Notify.FTP.UploadPath=
root.Notify.FTP.PassiveMode=no
root.Notify.FTP.Port=21
root.Notify.HTTP.Enabled=no
root.Notify.HTTP.URL=http://
root.Notify.HTTP.Custom=
root.Notify.HTTP.UserName=
root.Notify.HTTP.Password=
root.Notify.HTTP.Proxy=
root.Notify.HTTP.ProxyPort=
root.Notify.HTTP.ProxyUser=
root.Notify.HTTP.ProxyPass=
root.Notify.SMTP.Enabled=no
root.Notify.SMTP.ToEmail=
root.Notify.SMTP.FromEmail=
root.Notify.SMTP.Subject=
root.Output.NbrOfOutputs=0
root.PIRSensor.Sensitivity=75
root.Properties.API.HTTP.Version=3
root.Properties.API.HTTP.AdminPath=/operator/basic.shtml
root.Properties.API.Metadata.Metadata=yes
root.Properties.API.Metadata.Version=1.0
root.Properties.API.RTSP.Version=2.01
root.Properties.API.RTSP.RTSPAuth=yes
root.Properties.API.WebService.WebService=yes
root.Properties.API.WebService.ONVIF.ONVIF=yes
root.Properties.API.WebService.ONVIF.Version=1.01
root.Properties.Audio.Audio=yes
root.Properties.Audio.Format=g711,g726,aac
root.Properties.Audio.DuplexMode=full,half,post,get
root.Properties.Audio.InputType=mic
root.Properties.Audio.Decoder.Format=g711,g726,axis-mulaw-128
root.Properties.Firmware.BuildNumber=1
root.Properties.Firmware.BuildDate=Jun 23 2016 13:16
root.Properties.Firmware.Version=5.20.4
root.Properties.HTTPS.HTTPS=yes
root.Properties.Image.Rotation=0,180
root.Properties.Image.Resolution=640x480,480x360,320x240,240x180,160x120,176x144
root.Properties.Image.Format=jpeg,mjpeg,mpeg4,h264,bitmap
root.Properties.Image.NbrOfViews=1
root.Properties.LightControl.LightControl=yes
root.Properties.Motion.Motion=yes
root.Properties.Motion.MaxNbrOfWindows=10
root.Properties.RemoteService.RemoteService=yes
root.Properties.RTC.RTC=no
root.Properties.System.Language=English
root.Properties.System.HardwareID=170
root.Properties.System.SerialNumber=00408C9A1F56
root.Properties.System.Architecture=armv5tejl
root.Properties.Tampering.Tampering=yes
root.Properties.TemperatureSensor.TemperatureSensor=yes
root.Properties.TemperatureSensor.TemperatureControl=no
root.Properties.TemperatureSensor.Fan=no
root.Properties.TemperatureSensor.Heater=no
root.RemoteService.Enabled=oneclick
root.RemoteService.Proxy=
root.RemoteService.RemoteServerURL=http://dispatcher.sts.axis.com:80/axissts/axissts.cgi,http://dispatcher.sts.axis.com:8080/axissts/axissts.cgi,http://dispatchse1.sts.axis.com:80/axissts/axissts.cgi,http://dispatchse1.sts.axis.com:8080/axissts/axissts.cgi,http://dispatchse2.sts.axis.com:80/axissts/axissts.cgi,http://dispatchse2.sts.axis.com:8080/axissts/axissts.cgi,http://dispatchus1.sts.axis.com:80/axissts/axissts.cgi,http://dispatchjp1.sts.axis.com:80/axissts/axissts.cgi,http://87.237.210.63:80/axissts/axissts.cgi,http://87.237.210.63:8080/axissts/axissts.cgi,http://85.235.16.249:80/axissts/axissts.cgi,http://85.235.16.249:8080/axissts/axissts.cgi,http://85.235.16.250:80/axissts/axissts.cgi,http://85.235.16.250:8080/axissts/axissts.cgi
root.RemoteService.Timeout=100
root.RemoteService.ConnectTimeout=15
root.RemoteService.BrandSpec=1275677567
root.RemoteService.Reconnect=0
root.RemoteService.TimeMode=NTP
root.SMTP.MailServer1=
root.SMTP.MailServer2=
root.SMTP.MailServerPort1=25
root.SMTP.MailServerPort2=25
root.SMTP.MailServerSSL1=no
root.SMTP.MailServerSSL2=no
root.SMTP.FromEmail=
root.SMTP.Authentication.A1.Enabled=no
root.SMTP.Authentication.A1.UserName=
root.SMTP.Authentication.A1.Password=
root.SMTP.Authentication.A1.WeakestMethod=Login
root.SMTP.Authentication.A1.UsePOP=no
root.SMTP.Authentication.A1.POPServer=
root.SMTP.Authentication.A2.Enabled=no
root.SMTP.Authentication.A2.UserName=
root.SMTP.Authentication.A2.Password=
root.SMTP.Authentication.A2.WeakestMethod=Login
root.SMTP.Authentication.A2.UsePOP=no
root.SMTP.Authentication.A2.POPServer=
root.SMTP.SSL.S1.RootCertificate=
root.SMTP.SSL.S1.ClientCertificate=
root.SMTP.SSL.S1.ClientPrivateKey=
root.SMTP.SSL.S1.ClientPrivateKeyPasswd=
root.SMTP.SSL.S2.RootCertificate=
root.SMTP.SSL.S2.ClientCertificate=
root.SMTP.SSL.S2.ClientPrivateKey=
root.SMTP.SSL.S2.ClientPrivateKeyPasswd=
root.SNMP.Enabled=no
root.SNMP.InitialUserPasswdSet=no
root.SNMP.InitialUserPasswd=*****
root.SNMP.EngineBoots=1
root.SNMP.V1=no
root.SNMP.V2c=no
root.SNMP.V3=no
root.SNMP.V1ReadCommunity=public
root.SNMP.V1WriteCommunity=write
root.SNMP.DSCP=0
root.SNMP.Trap.Enabled=no
root.SNMP.Trap.T0.Address=
root.SNMP.Trap.T0.Community=public
root.SNMP.Trap.T0.AuthFail.Enabled=no
root.SNMP.Trap.T0.ColdStart.Enabled=no
root.SNMP.Trap.T0.LinkUp.Enabled=no
root.SNMP.Trap.T0.WarmStart.Enabled=no
root.SOCKS.Enabled=no
root.SOCKS.Server=socks
root.SOCKS.ServerPort=1080
root.SOCKS.ServerType=4
root.SOCKS.LocalNetworks=10.0.0.0/255.0.0.0, 172.16.0.0/255.240.0.0, 192.168.0.0/255.255.255.0
root.SOCKS.UserName=
root.SOCKS.Password=
root.StatusLED.Usage=on
root.StatusLED.FlashInterval=4
root.StreamCache.Size=12582912
root.StreamCache.MaxGroups=20
root.StreamCache.S0.Enabled=no
root.StreamCache.S0.Options=
root.StreamCache.S0.RequestedLengthTime=30
root.StreamProfile.MaxGroups=20
root.StreamProfile.S0.Name=Quality
root.StreamProfile.S0.Description=Best image quality and full frame rate.
root.StreamProfile.S0.Parameters=videocodec=h264&resolution=640x480&compression=20&fps=0&videokeyframeinterval=8&videobitrate=0
root.StreamProfile.S0.Default.Name=Quality
root.StreamProfile.S0.Default.Description=Best image quality and full frame rate.
root.StreamProfile.S0.Default.Parameters=videocodec=h264&resolution=640x480&compression=20&fps=0&videokeyframeinterval=8&videobitrate=0
root.StreamProfile.S1.Name=Balanced
root.StreamProfile.S1.Description=Medium image quality and frame rate.
root.StreamProfile.S1.Parameters=videocodec=h264&resolution=640x480&compression=30&fps=15&videokeyframeinterval=15&videobitrate=0
root.StreamProfile.S1.Default.Name=Balanced
root.StreamProfile.S1.Default.Description=Medium image quality and frame rate.
root.StreamProfile.S1.Default.Parameters=videocodec=h264&resolution=640x480&compression=30&fps=15&videokeyframeinterval=15&videobitrate=0
root.StreamProfile.S2.Name=Bandwidth
root.StreamProfile.S2.Description=Low bandwidth with medium image quality.
root.StreamProfile.S2.Parameters=resolution=320x240&compression=50&fps=15&videokeyframeinterval=32&videobitrate=250&videobitratepriority=framerate&videocodec=h264
root.StreamProfile.S2.Default.Name=Bandwidth
root.StreamProfile.S2.Default.Description=Low bandwidth with medium image quality.
root.StreamProfile.S2.Default.Parameters=videocodec=h264&resolution=640x480&compression=50&fps=15&videokeyframeinterval=32&videobitrate=250&videomaxbitrate=1000&videobitratepriority=framerate
root.StreamProfile.S3.Name=Mobile
root.StreamProfile.S3.Description=Mobile device settings.
root.StreamProfile.S3.Parameters=videocodec=h264&resolution=176x144&compression=50&fps=15&videokeyframeinterval=32&videobitrate=120&videomaxbitrate=128&videobitratepriority=quality&audio=0
root.StreamProfile.S3.Default.Name=Mobile
root.StreamProfile.S3.Default.Description=Mobile device settings.
root.StreamProfile.S3.Default.Parameters=videocodec=h264&resolution=176x144&compression=50&fps=15&videokeyframeinterval=32&videobitrate=120&videomaxbitrate=128&videobitratepriority=quality&audio=0
root.System.BoaPort=80
root.System.AlternateBoaPort=0
root.System.BoaDSCP=0
root.System.BoaProtViewer=password
root.System.RootPwdSet=yes
root.System.BoaGroupPolicy.admin=http
root.System.BoaGroupPolicy.operator=http
root.System.BoaGroupPolicy.viewer=http
root.Tampering.T0.DarkDetectionEnabled=yes
root.Tampering.T0.MinDuration=20
root.Tampering.T0.DarkThreshold=90
root.Time.ServerTime=10:38:13
root.Time.ServerDate=2016-10-26
root.Time.ObtainFromDHCP=no
root.Time.POSIXTimeZone=CET-1CEST,M3.5.0,M10.5.0/3
root.Time.SyncSource=NTP
root.Time.DST.Enabled=yes
root.Time.NTP.VolatileServer=
root.Time.NTP.Server=192.168.69.251
root.WebService.Enabled=no
root.WebService.UsernameToken.ReplayAttackProtection=yes
root.WebService.UsernameToken.WaitForNTP=no
How yould you do this in C#?
You can use an ExpandoObject with a params indexer to access it, something like this (that's just an example, you'll need to do some testing around it and handle things like single key access etc):
public class AssociativeArray
{
private dynamic _data = new ExpandoObject();
public object this[params string[] keys]
{
get
{
dynamic lastObject = _data;
foreach (var key in keys.Take(keys.Count() - 1))
{
var dic = lastObject as IDictionary<string, Object>;
lastObject = dic[key] as ExpandoObject;
}
return (lastObject as IDictionary<string, object>)[keys.Last()];
}
set
{
dynamic lastObject = _data;
foreach (var key in keys.Take(keys.Count() - 1))
{
var dic = lastObject as IDictionary<string, Object>;
dic.Add(key, new ExpandoObject());
lastObject = dic[key];
}
(lastObject as IDictionary<string, object>).Add(keys.Last(), value);
}
}
}
you can then use it like this:
var arr = new AssociativeArray();
arr["root", "Audio", "Dup"] = 33;
Console.Write(arr["root", "Audio", "Dup"]);
PS. I'm using the suggestion from this answer to cast the ExpandoObject as a Dictionary
You can use a ExpandoObject for this case. You can cast the ExpandoObject to a Dictionary and add the values:
var text = File.ReadAllText("$settingsfile");
var keyValuePairs = text.Split('\n')
.Select(line => Tuple.Create(line.Split('=')[0].Trim(), line.Split('=')[1].Trim()));
dynamic root = new ExpandoObject();
foreach (var tup in keyValuePairs)
{
var path = tup.Item1.Split('.').Skip(1).ToList();
var setting = path.Last();
var value = tup.Item2;
IDictionary<string, object> resolvedObject = root;
foreach (var component in path.Take(path.Count - 1))
{
if (!resolvedObject.ContainsKey(component))
{
resolvedObject.Add(component, new ExpandoObject());
}
resolvedObject = (IDictionary<string, object>) resolvedObject[component];
}
resolvedObject[setting] = value;
}
Console.WriteLine(">> " + root.System.BoaPort);
Thanks to KMoussa!
Not the most beautiful code, but it works:
public class cAssociativeArray
{
private dynamic _data = new ExpandoObject();
public object this[params string[] keys]
{
get { return getValue(keys); }
set { setValue(value, keys); }
}
private void setValue(object _value, params string[] keys)
{
dynamic lastObject = _data;
string lKey = keys.Last();
foreach (var key in keys.Take(keys.Count() - 1))
{
var dic = lastObject as IDictionary<string, Object>;
if (!dic.ContainsKey(key))
{
dic.Add(key, new ExpandoObject());
}
lastObject = dic[key];
}
if ((lastObject as IDictionary<string, object>) != null)
{
if (!(lastObject as IDictionary<string, object>).ContainsKey(keys.Last())) // add value
{
(lastObject as IDictionary<string, object>).Add(lKey, _value);
}
else //change value
{
if (keys.Count() > 1)
{
(lastObject as IDictionary<string, object>)[lKey] = _value;
}
}
}
}
private string getValue(params string[] keys)
{
dynamic lastObject = _data;
string lKey = keys.Last();
foreach (var key in keys.Take(keys.Count() - 1))
{
var dic = lastObject as IDictionary<string, Object>;
if ((dic != null) && (dic.ContainsKey(key)))
{
lastObject = dic[key] as ExpandoObject;
}
else
{
return null;
}
}
if (((lastObject as IDictionary<string, object>) != null) && ((lastObject as IDictionary<string, object>).ContainsKey(lKey))
&& (!((lastObject as IDictionary<string, object>)[lKey] is ExpandoObject)))
{
return (lastObject as IDictionary<string, object>)[lKey].ToString();
}
else
{
return null;
}
}
public string[] getKeys(params string[] keys)
{
dynamic lastObject = _data;
foreach (var key in keys.Take(keys.Count()))
{
var dic = lastObject as IDictionary<string, Object>;
if ((dic != null) && (dic.ContainsKey(key)))
{
lastObject = dic[key] as ExpandoObject;
}
else
{
return null;
}
}
if ((lastObject as IDictionary<string, object>) != null)
{
return (lastObject as IDictionary<string, object>).Keys.ToArray();
}
else
{
return null;
}
}
public int countKeys(params string[] keys)
{
dynamic lastObject = _data;
foreach (var key in keys.Take(keys.Count()))
{
var dic = lastObject as IDictionary<string, Object>;
if ((dic != null) && (dic.ContainsKey(key)))
{
lastObject = dic[key] as ExpandoObject;
}
else
{
return -1;
}
}
if ((lastObject as IDictionary<string, object>) != null)
{
return (lastObject as IDictionary<string, object>).Count();
}
else
{
return -1;
}
}
public void printDebug(params string[] keys)
{
Debug.WriteLine("");
printDebugSub("", keys);
Debug.WriteLine("");
}
private void printDebugSub(string spaceStr, params string[] keys)
{
dynamic lastObject = _data;
foreach (var key in keys.Take(keys.Count()))
{
var dic = lastObject as IDictionary<string, Object>;
if ((dic != null) && (dic.ContainsKey(key)))
{
lastObject = dic[key] as ExpandoObject;
}
}
if ((lastObject as IDictionary<string, object>) != null)
{
foreach (string keyStr in (lastObject as IDictionary<string, object>).Keys.ToArray())
{
string valueStr = "";
if (!((lastObject as IDictionary<string, object>)[keyStr] is ExpandoObject))
{
valueStr = " = " + (lastObject as IDictionary<string, object>)[keyStr].ToString();
}
Debug.WriteLine(spaceStr + keyStr + valueStr);
List<string> lst = keys.ToList();
lst.Add(keyStr);
printDebugSub(spaceStr.Trim() + "---- ", lst.ToArray());
}
}
else
{
return;
}
}
}
In my WPF application I need to get a list of Windows Services(~200) with a specific properties.
var result = new List<ServicesModel>();
ConnectionOptions connOptions = new ConnectionOptions
{
Impersonation = ImpersonationLevel.Impersonate,
EnablePrivileges = true,
};
ManagementScope manScope = new ManagementScope($#"\\{System.Environment.MachineName}\ROOT\CIMV2",
connOptions);
manScope.Connect();
SelectQuery query = new SelectQuery("SELECT * FROM Win32_Service");
using (var searcher = new ManagementObjectSearcher(manScope, query))
foreach (var o in searcher.Get())
{
var obj = (ManagementObject) o;
ServicesModel service = new ServicesModel
{
Name = obj["DisplayName"] as string,
Path = obj["PathName"] as string,
Description = obj["Description"] as string,
Pid = Convert.ToInt32(obj["ProcessId"]),
Status = obj["State"] as string,
StartMode = obj["StartMode"] as string,
LogOnAs = obj["StartName"] as string
};
result.Add(service);
}
return result;
It takes approximately ~1 minute to execute this method and return data which is unacceptable.
Looks like searcher.Get() takes all that time...
What I can do to improve execute/return time/performance?
Thanks
Based on the comments I came up with following, hope it might help someone:
public List<string> GetWindowsServicesList()
{
var result = new List<string>();
foreach (ServiceController service in ServiceController.GetServices())
{
string serviceName = service.ServiceName;
result.Add(serviceName);
}
return result;
}
public ServicesModel GetServiceProperties(string serviceName)
{
ServicesModel service = null;
string path = $"Win32_Service.Name=\"{serviceName}\"";
using (ManagementObject mngObj = new ManagementObject(path))
{
service = new ServicesModel
{
Name = mngObj.GetPropertyValue("Name") as string,
Path = mngObj.GetPropertyValue("PathName") as string,
Description = mngObj.GetPropertyValue("Description") as string,
Pid = Convert.ToInt32(mngObj.GetPropertyValue("ProcessId")),
Status = mngObj.GetPropertyValue("State") as string,
StartMode = mngObj.GetPropertyValue("StartMode") as string,
LogOnAs = mngObj.GetPropertyValue("StartName") as string
};
}
return service;
}
public List<ServicesModel> WindowsServicesCollection()
{
var result = new List<ServicesModel>();
try
{
var windowsServicesNames = GetWindowsServicesList();
for (int i = 0; i < windowsServicesNames.Count(); i++)
{
result.Add(GetServiceProperties(windowsServicesNames[i]));
}
}
catch (System.Management.ManagementException ex)
{
}
catch (System.TimeoutException ex)
{
}
return result;
}
Works much, much faster than previous solution although it seems like performance is not super consistent and it depends from some various factors that I did not identified...
Ive created a Directory Searcher to pull multiple properties from each user.
objSearchADAM = new DirectorySearcher(objADAM);
objSearchADAM.PropertiesToLoad.Add("givenname");
objSearchADAM.PropertiesToLoad.Add("lastlogontimestamp");
ect...
objSearchResults = objSearchADAM.FindAll();
I then enumerate them, and convert the interger8 timestamp to standard date/time, and save to csv file with
List<string> timeProps = new List<string>() { "lastlogontimestamp", "accountexpires", "pwdlastset", "lastlogoff", "lockouttime", "maxstorage", "usnchanged", "usncreated", "usndsalastobjremoved", "usnlastobjrem", "usnsource" };
foreach (SearchResult objResult in objSearchResults)
{
objEntry = objResult.GetDirectoryEntry();
ResultPropertyCollection myResultProp = objResult.Properties;
foreach (string myKey in myResultProp.PropertyNames)
{
foreach (Object myCollection in myResultProp[myKey])
{
Object sample = myCollection;
if (timeProps.Contains(myKey))
{
String times = sample.ToString();
long ft = Int64.Parse(times);
DateTime date;
try
{
date = DateTime.FromFileTime(ft);
}
catch (ArgumentOutOfRangeException ex)
{
date = DateTime.MinValue;
Console.WriteLine("Out of range: " + ft);
Console.WriteLine(ex.ToString());
}
sample = date;
Console.WriteLine("{0}{1}", myKey.PadRight(25), sample);
objWriter.WriteLine("{0}{1}", myKey.PadRight(25), sample);
}
else
{
Console.WriteLine("{0}{1}", myKey.PadRight(25), sample);
objWriter.WriteLine("{0}{1}", myKey.PadRight(25), sample);
}
}
now i need to create an object for each user with the strings from each result that i can put into an SQL command ive built. where the LDAP query to SQL would be givenname = FirstName and lastlogontimestamp = LastLogon and so on.
StringBuilder sb = new StringBuilder();
sb.Append("INSERT INTO activedirectory.dimUserST (FirstName, LastName) VALUES (#FirstName, #LastName)");
loadStagingCommand.Parameters.AddWithValue("#FirstName", FirstName).DbType = DbType.AnsiString;
ect...
loadStagingCommand.CommandText = sb.ToString();
loadStagingCommand.ExecuteNonQuery();
i tried to use IDictionary in my first foreach (similar to code found here http://ideone.com/vChWD ) but couldn't get it to work. I read about IList and reflection, but im not sure how i could incorporate these.
UPDATE
I researched and found ExpandoObjects and attempted to write in code based off of what i saw in here Creating Dynamic Objects
however i run this new code I return "employeenumber System.Collections.Generic.List`1[System.Dynamic.ExpandoObject]"
if(employeeNumber.Contains(myKey))
{
string[] columnNames = { "EmployeeNumber" };
List<string[]> listOfUsers = new List<string[]>();
for (int i = 0; i < 10; i++)
{
listOfUsers.Add(new[] { myKey});
}
var testData = new List<ExpandoObject>();
foreach (string[] columnValue in listOfUsers)
{
dynamic data = new ExpandoObject();
for (int j = 0; j < columnNames.Count(); j++)
{
((IDictionary<String, Object>)data).Add(columnNames[j], listOfUsers[j]);
}
testData.Add(data);
Console.WriteLine("{0}{1}", myKey.PadRight(25), testData);
objWriter.WriteLine("{0}{1}", myKey.PadRight(25), testData);
}
}
I am obviously missing something here and cant seem to wrap my head around what the problem is. I might even be going about this the wrong way. Basically all i need to do is pull users and their properties from Active Directory and put into SQL database tabels. And I've worked out how to do both separately, but I cant figure out how to put it all together.
If the CSV is just being used to cache the results, you could use a Dictionary to store the contents of the search results instead. Separating your code into functions could be helpful:
private static object GetFirstValue(ResultPropertyCollection properties,
string propertyName)
{
var propertyValues = properties[propertyName];
var result = propertyValues.Count == 0 ? null : propertyValues[0];
return result;
}
Then you could either use a dictionary to hold the property values, or you could create a type:
var results = new List<Dictionary<string, object>>();
foreach(SearchResult objResult in objSearchResults)
{
var properties = objResult.Properties;
var propertyDictionary = new Dictionary<string, object> {
{"FirstName", GetFirstValue(properties, "givenname")},
{"LastName", GetFirstValue(properties, "sn")},
{"UserName", GetFirstValue(properties, "samaccountname")},
};
results.Add(propertyDictionary);
}
Now you have a list of property bags.
This could also be a simple LINQ statement:
var results = objSearchResults.OfType<SearchResult>()
.Select(s => s.Properties)
.Select(p => new {
FirstName = (string)GetFirstValue(properties, "givenname"),
LastName = (string)GetFirstValue(properties, "sn"),
UserName = (string)GetValue(properties, "samaccountname"),
AccountExpires = GetDateTimeValue(properties, "accountexpires")
});
Use the dictionaries like this:
foreach(var item in results)
{
var command = new SqlCommand();
...
command.Parameters.AddWithValue("firstName", item["FirstName"]);
...
}