Obtaining raw property value with .NET DirectoryServices - c#

Does anyone know if it's possible to get value of any LDAP object's property X? It seems like that .NET or ADSI removes stuff it cannot handle (de.Properties.Values.Count == de.Properties.PropertyNames.Count > de.Properties.Values.props.valueTable.Count).
binddn.Text = "cn=admin,o=system";
bindpass.Password = "XXXXX";
server.Text = "10.X.X.X";
basedn.Text = "cn=server,o=system";
StringBuilder basepath = new StringBuilder("LDAP://");
basepath.Append(server.Text).Append("/").Append(basedn.Text);
DirectoryEntry myDirectoryEntry = new DirectoryEntry(basepath.ToString());
myDirectoryEntry.Username = binddn.Text;
myDirectoryEntry.Password = bindpass.Password;
myDirectoryEntry.AuthenticationType = AuthenticationTypes.ServerBind;
foreach (string key in myDirectoryEntry.Properties.PropertyNames)
{
object val = myDirectoryEntry.Properties[key].Value;
}
This crashes on networkAddress property which is binary field ( http://ldapwiki.willeke.com/wiki/Ldapsearch%20Networkaddress ).

Related

Why is PropertyDataCollection object persisting multiple records to database

I have a utility that reads the status of MicrosoftBizTalk Server resources .. specifically the ReceiveLocation component. My problem is that the program is submitting multiple entries of each item i.e each item in the data returned is being multiplied by 25 such that instead of persisting only 5 rows the data being persisted is 125. So for example instead of having just 1 row for my first row returned i have 25.
This is my program :
public List<BizTalk> GetBizTalkServicesStatistics()
{
List<BizTalk> model = new List<BizTalk>();
try
{
//Create the WMI search object.
ManagementObjectSearcher Searcher = new ManagementObjectSearcher();
ConnectionOptions options = new ConnectionOptions
{
Username = "+username+",
Password = "+password+",
Authority = "+domain+"
};
var server = "+server+";
// create the scope node so we can set the WMI root node correctly.
ManagementScope Scope = new ManagementScope("\\\\" + server + "\\root\\MicrosoftBizTalkServer", options);
Searcher.Scope = Scope;
// Build a Query to enumerate the MSBTS_ReceiveLocation instances if an argument
// is supplied use it to select only the matching RL.
//if (args.Length == 0)
SelectQuery Query = new SelectQuery();
Query.QueryString = "SELECT * FROM MSBTS_ReceiveLocation";
// else
//Query.QueryString = "SELECT * FROM MSBTS_ReceiveLocation WHERE Name = '" + args[0] + "'";
// Set the query for the searcher.
Searcher.Query = Query;
// Execute the query and determine if any results were obtained.
ManagementObjectCollection QueryCol = Searcher.Get();
// Use a bool to tell if we enter the for loop
// below because Count property is not supported
bool ReceiveLocationFound = false;
// Enumerate all properties.
foreach (ManagementBaseObject envVar in QueryCol)
{
// There is at least one Receive Location
ReceiveLocationFound = true;
PropertyDataCollection envVarProperties = envVar.Properties;
foreach (PropertyData envVarProperty in envVarProperties)
{
BizTalk bizTalk = new BizTalk();
bizTalk.Name = Convert.ToString(envVar["Name"]);
bizTalk.TransportType = Convert.ToString(envVar["AdapterName"]);
bizTalk.Uri = Convert.ToString(envVar["InboundTransportURL"]);
bizTalk.Status = Convert.ToString(envVar["Name"]);
bizTalk.ReceiveHandler = Convert.ToString(envVar["HostName"]);
bizTalk.ReceivePort = Convert.ToString(envVar["ReceivePortName"]);
bizTalk.RunDate = DateTime.Now;
bizTalk.ApplicationId = 24;
bizTalk.ServerId = 8;
bizTalk.InstanceName = "FBCZOP";
model.Add(bizTalk);
}
}
if (!ReceiveLocationFound)
{
Console.WriteLine("No receive locations found matching the specified name.");
}
}
catch (Exception excep)
{
ExceptionLogger.SendErrorToText(excep);
}
return model;
}
Save Function
public void SaveStatistics(BizTalk entity)
{
List<BizTalk> ServerInfo = new List<BizTalk>();
ServerInfo = GetBizTalkServicesStatistics();
foreach (var di in ServerInfo)
{
entity.RunDate = di.RunDate;
entity.Name = di.Name;
entity.Status = di.Status;
entity.Uri = di.Uri;
entity.InstanceName = di.InstanceName;
entity.ReceivePort = di.ReceivePort;
entity.TransportType= di.TransportType;
entity.RunDate = DateTime.Now;
entity.ReceiveHandler = di.ReceiveHandler;
entity.ServerId = entity.ServerId;
entity.ApplicationId = entity.ApplicationId;
appEntities.BizTalk.Add(entity);
appEntities.SaveChanges();
}
}
When i step through the code variable envVarProperties shows record count as 125 under envVarProperties << ResultsView :
Link 1
whilst QueryCol variable shows count of 5 :
Link 2
It looks like you're iterating an extra time in your GetBizTalkServicesStatistics() method.
Remove the foreach loop that starts with foreach (PropertyData envVarProperty in envVarProperties). This is looping through each property the object has (All 25 properties) for each instance (5 instances)... 25 * 5 = 125 values you are retrieving. You only want to iterate through your instances and pull the properties you want. That way you end up with 5 objects in your model object.
I'd suggest maybe something like this (untested because I don't have BizTalk)
public List<BizTalk> GetBizTalkServicesStatistics()
{
List<BizTalk> model = new List<BizTalk>();
try
{
//Create the WMI search object.
ConnectionOptions options = new ConnectionOptions
{
Username = "+username+",
Password = "+password+",
Authority = "+domain+"
};
var server = "+server+";
// create the scope node so we can set the WMI root node correctly.
ManagementScope Scope = new ManagementScope("\\\\" + server + "\\root\\MicrosoftBizTalkServer", options);
ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, new ObjectQuery("SELECT * FROM MSBTS_ReceiveLocation"));
// Enumerate all properties.
foreach (ManagementObject instance in Searcher.Get())
{
{
BizTalk bizTalk = new BizTalk();
bizTalk.Name = instance.Properties["Name"]?.Value?.ToString();
bizTalk.TransportType = instance.Properties["AdapterName"]?.Value?.ToString();
bizTalk.Uri = instance.Properties["InboundTransportURL"]?.Value?.ToString();
bizTalk.Status = instance.Properties["Name"]?.Value?.ToString();
bizTalk.ReceiveHandler = instance.Properties["HostName"]?.Value?.ToString();
bizTalk.ReceivePort = instance.Properties["ReceivePortName"]?.Value?.ToString();
bizTalk.RunDate = DateTime.Now;
bizTalk.ApplicationId = 24;
bizTalk.ServerId = 8;
bizTalk.InstanceName = "FBCZOP";
model.Add(bizTalk);
}
}
// Determine
if (model.Count == 0)
{
Console.WriteLine("No receive locations found matching the specified name.");
}
}
catch (Exception excep)
{
ExceptionLogger.SendErrorToText(excep);
}
return model;
}
Also, this can be simplified more if you remove the connectionoptions (unless you are hard coding credentials which is highly advised against). If you are just using the identity of the executing user, that data is not needed.
-Paul
You are adding the same entity 25 times and overwrite its properties by reference. You need to initialize a new entity inside your loop:
foreach (var di in ServerInfo)
{
var entity = new BizTalk();
entity.RunDate = di.RunDate;
entity.Name = di.Name;
entity.Status = di.Status;
entity.Uri = di.Uri;
entity.InstanceName = di.InstanceName;
entity.ReceivePort = di.ReceivePort;
entity.TransportType= di.TransportType;
entity.RunDate = DateTime.Now;
entity.ReceiveHandler = di.ReceiveHandler;
entity.ServerId = entity.ServerId;
entity.ApplicationId = entity.ApplicationId;
appEntities.BizTalk.Add(entity);
appEn.SaveChanges();
}
}
As you don't show the code where "SaveStatistics" is called it's not sure this will fix your complete problem, but it's at least one method that does not do what you expect it to do.

Assigning values from a object with known properties

Im writing a class with witch creates a overview over the employees phones.
I am getting the info form Activesync object containing phones as children.
This is my current code. It works if the child dont contain any nulls.
foreach (DirectoryEntry child in directoryObject.Children)
{
var activeSyncPhone = new ActiveSync.Phone();
activeSyncPhone.Cn = child.Properties["cn"].Value.ToString(); //string
activeSyncPhone.DistinguishedName = child.Properties["distinguishedName"].Value.ToString(); //sting
activeSyncPhone.InstanceType = (int)child.Properties["instanceType"].Value; //int
activeSyncPhone.WhenCreated = (DateTime)child.Properties["whenCreated"].Value; //datetime
activeSyncPhone.WhenChanged = (DateTime)child.Properties["whenChanged"].Value; //datetime
activeSyncPhone.Name = child.Properties["name"].Value.ToString(); //string
activeSyncPhone.ObjectCategory = child.Properties["objectCategory"].Value.ToString(); //string
activeSyncPhone.MsExchFirstSyncTime = (DateTime)child.Properties["msExchFirstSyncTime"].Value;//datetime
activeSyncPhone.MsExchDeviceEASVersion = child.Properties["msExchDeviceEASVersion"].Value.ToString();//string
activeSyncPhone.MsExchDeviceFriendlyName = child.Properties["msExchDeviceFriendlyName"].Value.ToString(); //string
activeSyncPhone.MsExchDeviceAccessState = (ActiveSync.Phone.DeviceAccessState)child.Properties["msExchDeviceAccessState"].Value; //int
activeSyncPhone.MsExchDeviceID = child.Properties["msExchDeviceID"].Value.ToString(); //string
activeSyncPhone.MsExchDeviceType = child.Properties["msExchDeviceType"].Value.ToString(); //string
try
{
activeSyncPhone.MsExchDeviceIMEI = child.Properties["msExchDeviceIMEI"]?.Value.ToString(); //string
}
catch
{
activeSyncPhone.MsExchDeviceIMEI = "Could not find IMEI";
}
activeSyncPhone.MsExchDeviceUserAgent = child.Properties["msExchDeviceUserAgent"].Value.ToString(); //string
activeSyncPhone.MsExchVersion = child.Properties["msExchVersion"].Value.ToString(); //string
activeSyncPhone.MsExchDeviceAccessStateReason = (ActiveSync.Phone.DeviceAccessStateReason)child.Properties["msExchDeviceAccessStateReason"].Value; //string
activeSyncPhone.MsExchUserDisplayName = child.Properties["msExchUserDisplayName"].Value.ToString(); //string
activeSyncPhone.MsExchDeviceModel = child.Properties["msExchDeviceModel"].Value.ToString(); //string
activeSyncPhone.MsExchDeviceOS = child.Properties["msExchDeviceOS"].Value.ToString(); //string
activeSyncPhone.ObjectGUID = child.Properties["objectGUID"].Value.ToString(); //string
activeSyncUnits.PhoneList.Add(activeSyncPhone);
child.Close();
}
directoryObject.Close();
I was wondering if there was any way to make this a bit more robust. I was looking into setting the ActiveSyncPhone's propertys dynamically and then with a list set all the properties. But C# is a strongly-typed language and I figured id take advantage of the type safety and performance advantages that accompany that aspect. I think there might be a better way then checking every child.property for null with if statements? and aslo is there a better way for getting the child properties?
You could create a generic function for that:
// you'll have to figure out the type of the `child.Properties`
public static T GetValue<T>(TypeOfChildProperties properties, string name, T defaultValue = default(T))
{
var value = properties[name];
if (value == null)
return defaultValue;
return (T)value;
// if you have some cast problems, you could use this:
return (T)Convert.ChangeType(value, typeof(T));
}
activeSyncPhone.Cn = GetValue<string>(child.Properties, "cn");
activeSyncPhone.DistinguishedName = GetValue<string>(child.Properties, "distinguishedName");
activeSyncPhone.InstanceType = GetValue<int>(child.Properties, "instanceType");
activeSyncPhone.MsExchDeviceIMEI = GetValue<string>(child.Properties, "msExchDeviceIMEI", "Could not find IMEI");

Getting culture (locale) independent WMI property

I need to get the power settings for a machine using WMI. I am using the MSDN Link to get the required values. I need specific values from the list returned. The following C# code does this:
string NamespacePath = #"root\cimv2\power";
string powerPlanClass = "Win32_powerplan";
string powerSettingClass = "Win32_PowerSettingDataIndex";
ManagementClass powerPlanManagementClass = new ManagementClass(NamespacePath + ":" + powerPlanClass);
ManagementObject powerPlanManagementObject = null;
foreach (ManagementObject managementObject in powerPlanManagementClass.GetInstances())
{
if (managementObject["IsActive"] != null && Boolean.Parse(managementObject["IsActive"].ToString()))
{
powerPlanManagementObject = managementObject;
}
}
Dictionary<string, PowerSetting> powerItems = new Dictionary<string, PowerSetting>()
{
{"AC", new PowerSetting() },
{"DC", new PowerSetting() }
};
foreach (ManagementObject oObject in powerPlanManagementObject.GetRelated(powerSettingClass))
{
var instanceId = oObject["instanceId"];
string[] powerSourceSettings = instanceId.ToString().Split(new string[] { #"\" }, StringSplitOptions.RemoveEmptyEntries);
var powerSourceType = powerSourceSettings[2];
ManagementObjectCollection managementObjects = oObject.GetRelated("Win32_PowerSetting");
var elementName = string.Empty;
foreach (var managementObject in managementObjects)
{
elementName = managementObject["ElementName"].ToString();
}
var indexValue = uint.Parse(oObject["settingindexvalue"].ToString());
if (elementName.Equals("Hibernate after",StringComparison.OrdinalIgnoreCase))
{
if (powerSourceType.Equals("AC", StringComparison.Ordinal))
{
powerItems["AC"].HibernateAfter = indexValue;
}
}
}
Note the match to the string "Hibernate after". This works on a machine with locale en-us but does not work with a different locale. Is there any other way to get the WMI property independent of the machine's locale?
Probably you can use GUID in the InstanceID of Win32_PowerSetting class instead of ElementName. In my machine, it is Microsoft:PowerSetting\{9d7815a6-7ee4-497e-8888-515a05f02364}. Although I couldn't find official document, this GUID, 9d7815a6-7ee4-497e-8888-515a05f02364 seems to be common for some Windows versions and locales as the identifier for "hibernate after" or "hibernate idle".

Get value from column using a column name string c#

I have 2 lists..
The first contains rows with mapping values inlcuding column name, xcord, ycord
The second contains the data I need to map..
I need to get the value in each row using the column name from the first row..
for example
List<SheetMappings> smaps = new List<SheetMappings>();
foreach(maplist m in mlist)
{
SheetMappings newMap = new SheetMappings();
foreach(vallist v in vlist)
{
newMap.Value = v.{m.ColumnName};
newMap.xCord = m.xCord;
newMap.yCord = m.yCord;
}
smaps.Add(newMap);
}
Any assitance appreciated
Cheers
Graham
EDIT:
List<SpreadMappings> spreadMapping = new List<SpreadMappings>();
foreach (var m in mappings)
{
foreach (var v in hvalues)
{
SpreadMappings map = new SpreadMappings();
switch (m.ColumnName)
{
case “DocHeading”:
map.ColumnX = m.ColumnX;
map.ColumnY = m.ColumnY;
map.ColumnValue = v.DocHeading;
map.ColumnName = m.ColumnName;
map.ColumnId = v.Id;
map.ColumnSheetName = sheetName; spreadMapping.Add(map);
break;
If I understand what you're trying to do, you'll need to use reflection to get the value of the property represented by m.ColumnName:
var smaps = new List<SheetMappings>();
foreach(maplist m in mlist)
{
var pi = typeof(vallist).GetProperty(m.ColumnName);
var newMap = new SheetMappings();
foreach(vallist v in vlist)
{
newMap.Value = pi.GetValue(v, null);
newMap.xCord = m.xCord;
newMap.yCord = m.yCord;
}
smaps.Add(newMap);
}
So that's using reflection to get a reference to the PropertyInfo for the property represented by m.ColumnName, then calling PropertyInfo.GetValue to get the value of that property from v.
Well I think the "newMap.Value = v.{m.ColumnName}" part would be something like:
newMap.Value = v.FirstOrDefault( vitem => vitem.ColumnName == m.ColumnName );
This would give you the first item within "v" that has a "ColumnName" property that matches the "ColumnName" property of "m". This assumes that the contents of "vallist" are objects that have a "ColumnName" property.

Building objects at runtime

I have a number of objects that I need to create and add to an array. However the code below seems dirty and difficult to maintain in the long run. What I'm thinking is, I should store the Name and Value properties in a table and build each comCommand object at runtime.
However, I'm not exactly sure what the best method to about doing this... Reflection, Activator.CreateInstance or some kind of object factory?
Thanks in advance.
var engine = new comCommand() { commandName = "-e", commandValue = "PNetTNative" };
var outputFile = new comCommand() { commandName = "-f", commandValue = OutputFile };
var groupSize = new comCommand() { commandName = "-GroupSizeParamInput1ParamsIn", commandValue = GroupSize };
var pagesPerSheet = new comCommand() { commandName = "-PagesPerSheetParamInput1ParamsIn", commandValue = PagesPerSheet };
var outputFileName = new comCommand { commandName = "-OutputFileNameParamInput1ParamsIn", commandValue = OutputFileName };
var duplex = new comCommand { commandName = "-DuplexParamInput1ParamsIn", commandValue = Duplex };
var processId = new comCommand { commandName = "-ProcessIDParamInput1ParamsIn", commandValue = ProcessID };
var request = new comRunWorkFlowReq();
request.command = new[] { engine, outputFile, groupSize, pagesPerSheet, outputFileName, duplex, processId };
Create a command constructor (as Kirk suggested) and keep it as you have: multiple comCommand("-e","PNetTNative") etc calls.
The reason for keeping it in code is you get compiler-time type and error checking... Yes, you can do it at runtime (various methods) but for just 7 declarations, it's best to keep it at compile time.

Categories

Resources