Get the string with parent of device - c#

In device manager of windows7 in com port's branch I choose menu "properties" one of port. In tab of "details" I chose property "parent" and see the string:
How I can obtain this string from vb .net or another language in visual studio in cmd also will be good?
I tried to use win32_ clases: pnpentity, serialPort etc but this no solved to my problem even output of Get-WMIObject Win32_SerialPort in PS had not property "parent".
Dim objService = GetObject("winmgmts://./root/cimv2")
For Each objPort In objService.ExecQuery("SELECT * FROM Win32_PnPEntity WHERE ClassGuid='{4d36e978-e325-11ce-bfc1-08002be10318}'")
Console.WriteLine(objPort.Caption & vbCrLf)
Console.Write(objPort.DeviceID & vbCrLf)
Console.ReadLine()
Next
Except Device ID I try Caption and all syntax that available in List.
Do you have any idea, please?

My solution was the following:
Get all active ports with their PnpDeviceIds:
private static List<PortInfo> GetActivePorts()
{
var ports = new List<PortInfo>();
using (var searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_SerialPort"))
using (var collection = searcher.Get())
{
foreach (var device in collection)
{
var portInfo = new PortInfo
{
Port = (string)device.GetPropertyValue("DeviceID"),
PnPDeviceId = (string)device.GetPropertyValue("PNPDeviceID")
};
if (!string.IsNullOrEmpty(portInfo.Port) && !string.IsNullOrEmpty(portInfo.PnPDeviceId))
{
ports.Add(portInfo);
}
}
}
return ports;
}
where PortInfo is
private class PortInfo
{
public string Port { get; set; }
public string PnPDeviceId { get; set; }
public string ParentDeviceId { get; set; }
}
fill ParentDeviceIds :
private static async void FillParentIds(IReadOnlyCollection<PortInfo> ports)
{
var propertiesToQuery = new List<string> {
"System.Devices.DeviceInstanceId",
"System.Devices.Parent"
};
var aqs = string.Join(" OR ", ports.Select(p => $"System.Devices.DeviceInstanceId:={p.PnPDeviceId}"));
var pnpDevices = await PnpObject.FindAllAsync(PnpObjectType.Device, propertiesToQuery, aqs);
foreach (var pnpDevice in pnpDevices)
{
var port = ports.FirstOrDefault(p => string.Compare(p.PnPDeviceId, pnpDevice.Id, StringComparison.InvariantCultureIgnoreCase) == 0);
if (port != null && pnpDevice.Properties.TryGetValue("System.Devices.Parent", out var parentId))
{
port.ParentDeviceId = parentId?.ToString();
}
}
}
ParentDeviceId will be that string you are looking for.

Related

IOS contact postal address in Xamarin.Forms

I am writing a C# app in a Xamarin.Forms project that displays a contact name, and street address. I am having trouble pulling the address from the CNContact and assigning the contacts address to a string.
Its going to be something obvious, but i'm stuck!
public List<Contact> GetContacts()
{
contactList = new List<Contact>();
var store = new Contacts.CNContactStore();
var ContainerId = new CNContactStore().DefaultContainerIdentifier;
var predicate = CNContact.GetPredicateForContactsInContainer(ContainerId);
var fetchKeys = new NSString[] { CNContactKey.Identifier, CNContactKey.GivenName, CNContactKey.FamilyName, CNContactKey.Birthday, CNContactKey.PostalAddresses, CNContactKey.ImageData };
NSError error;
var IPhoneContacts = store.GetUnifiedContacts(predicate, fetchKeys, out error);
foreach(var c in IPhoneContacts)
{
var contact = new Contact();
contact.FirstName = c.GivenName;
contact.FamilyName = c.FamilyName;
if(c.PostalAddresses.Length !=0)
{
contact.StreetAddress = CNPostalAddressFormatter.GetStringFrom(c.PostalAddresses, CNPostalAddressFormatterStyle.MailingAddress);
};
contactList.Add(contact);
}
return contactList;
}
The problem is that CNPostalAddressFormatter.GetStringFrom() method expects a single CNPostalAddress object as a parameter but you're passing all addresses of a single contact since the PostalAddresses property is an array of CNLabeledValue<ValueType> objects.
What you should do is iterate over all addresses, or perhaps just take the first one by default. Really depends on what you want to achieve.
For example, this would get the first CNPostalAddress:
contact.StreetAddress = CNPostalAddressFormatter.GetStringFrom(c.PostalAddresses[0].Value, CNPostalAddressFormatterStyle.MailingAddress);
Also, if you want to know the label of the address (Home, Work etc), you can get it like this:
c.PostalAddresses[0].Label
Then the actual CNPostalAddress object is again this:
c.PostalAddresses[0].Value
Fetching Existing Contacts in iOS :
First , you need to add follow permission in Info.plist :
<key>NSContactsUsageDescription</key>
<string>This app requires contacts access to function properly.</string>
Second , you can create a model contains of needs contact info as follow :
public class ContactModel
{
public IList PhoneNumbers { get; set; }
public string GivenName { get; set; }
public string FamilyName { get; set; }
}
Third , create a func to fetch info :
public List<ContactModel> ReadContacts()
{
var response = new List<ContactModel>();
try
{
//We can specify the properties that we need to fetch from contacts
var keysToFetch = new[] {
CNContactKey.PhoneNumbers, CNContactKey.GivenName, CNContactKey.FamilyName,CNContactKey.PostalAddresses,CNContactKey.PhoneNumbers
};
//Get the collections of containers
var containerId = new CNContactStore().DefaultContainerIdentifier;
//Fetch the contacts from containers
using (var predicate = CNContact.GetPredicateForContactsInContainer(containerId))
{
CNContact[] contactList;
using (var store = new CNContactStore())
{
contactList = store.GetUnifiedContacts(predicate, keysToFetch, out
var error);
}
//Assign the contact details to our view model objects
response.AddRange(from item in contactList
where item?.EmailAddresses != null
select new ContactModel
{
PhoneNumbers = item.PhoneNumbers,
PostalAddresses = CNPostalAddressFormatter.GetStringFrom(item.PostalAddresses[0].Value, CNPostalAddressFormatterStyle.MailingAddress),
GivenName = item.GivenName,
FamilyName = item.FamilyName
});
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
return response;
}
Fourth , invoke func :
List<ContactModel> contacts = ReadContacts();
ContactModel contactVm;
for (int i = 0; i < contacts.Count; i++)
{
contactVm = contacts[i];
Console.WriteLine("Contact is : " + contactVm.FamilyName);
Console.WriteLine("Contact is : " + contactVm.GivenName);
Console.WriteLine("Contact is : " + contactVm.PostalAddresses);
}
...
Contact is : Taylor
Contact is : David
Contact is : 1747 Steuart Street
Tiburon CA 94920
USA
Fifth , the screenshot as follow :
===================================Udate=====================================
Your code should be modified as follow :
public List<Contact> GetContacts()
{
contactList = new List<Contact>();
var store = new Contacts.CNContactStore();
var ContainerId = new CNContactStore().DefaultContainerIdentifier;
var predicate = CNContact.GetPredicateForContactsInContainer(ContainerId);
var fetchKeys = new NSString[] { CNContactKey.Identifier, CNContactKey.GivenName, CNContactKey.FamilyName, CNContactKey.Birthday, CNContactKey.PostalAddresses, CNContactKey.ImageData };
NSError error;
var IPhoneContacts = store.GetUnifiedContacts(predicate, fetchKeys, out error);
foreach(var c in IPhoneContacts)
{
var contact = new Contact();
contact.FirstName = c.GivenName;
contact.FamilyName = c.FamilyName;
if(c.PostalAddresses.Length !=0)
{
contact.StreetAddress = CNPostalAddressFormatter.GetStringFrom(c.PostalAddresses[0].Value, CNPostalAddressFormatterStyle.MailingAddress);
};
contactList.Add(contact);
}
return contactList;
}
The property postalAddress of Method CNPostalAddressFormatter.GetStringFrom
is a type of object(Contacts.CNPostalAddress) , however c.PostalAddresses is a type of Array.
public static string GetStringFrom (Contacts.CNPostalAddress postalAddress, Contacts.CNPostalAddressFormatterStyle style);

C# class and object : Object contains a single vaue

I am sorry if the title for my question is not apt.
I am a newbie to the programming side and trying to write a console app for getting all the installed apps on the computer from registry.
Here is my code.
class Program
{
static void Main(string[] args)
{
Console.Title = "Windows App Finder - Finds all the installed apps on the station";
List<AppDetails> apps = new List<AppDetails>();
apps = GetInstalledApps();
ListAllApps(apps);
Console.WriteLine("\nPress any key to exit.");
Console.ReadLine();
}
private static List<AppDetails> GetInstalledApps()
{
string registry_key = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
AppDetails appInfo = new AppDetails();
List<AppDetails> apps = new List<AppDetails>();
using (Microsoft.Win32.RegistryKey key = Registry.LocalMachine.OpenSubKey(registry_key))
{
foreach (string subkey_name in key.GetSubKeyNames())
{
using (RegistryKey subkey = key.OpenSubKey(subkey_name))
{
appInfo.appName = (string)subkey.GetValue("DisplayName");
appInfo.publisher = (string)subkey.GetValue("Publisher");
appInfo.appVersion = (string)subkey.GetValue("DisplayVersion");
if (appInfo.appName != null )
{
apps.Add(appInfo);
}
}
}
}
return apps;
}
private static void ListAllApps(List<AppDetails> appDetails)
{
int i = 0;
foreach (AppDetails appDetail in appDetails)
{
Console.WriteLine(i.ToString() + ". Name: " + appDetail.appName + " Version: " + appDetail.appVersion + " Publisher: " + appDetail.publisher);
i++;
}
}
}
public class AppDetails
{
public string appName { get; set; }
public string appVersion {get; set;}
public string publisher {get;set;}
public DateTime installDate { get; set; }
}
}
This code returns http://i.stack.imgur.com/tKtNr.png
Single app name repeated multiple times. What is wrong with this piece of code.
Thanks in advance
You have to instantiate AppDetails appInfo = new AppDetails(); inside your foreach loop, otherwise you will end with same object getting modified and added to the List again and again.
Just move the instantiation to inside your loop.
private static List<AppDetails> GetInstalledApps()
{
string registry_key = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
List<AppDetails> apps = new List<AppDetails>();
using (Microsoft.Win32.RegistryKey key = Registry.LocalMachine.OpenSubKey(registry_key))
{
foreach (string subkey_name in key.GetSubKeyNames())
{
using (RegistryKey subkey = key.OpenSubKey(subkey_name))
{
AppDetails appInfo = new AppDetails(); //HERE
appInfo.appName = (string)subkey.GetValue("DisplayName");
appInfo.publisher = (string)subkey.GetValue("Publisher");
appInfo.appVersion = (string)subkey.GetValue("DisplayVersion");
if (appInfo.appName != null)
{
apps.Add(appInfo);
}
}
}
}
return apps;
}
Since you are not instantiating the object inside the loop, It is being added to list multiple times, and all the instance in the list points to same reference. Therefore you see the same values returned multiple times. It would be the last value in your iteration.

Programatically tell windows firewall to use the Private Network

When I run my c# console app the windows firewall pops up requesting access for vshost32 (my app listens for incomming messages over port 1234 using TCP and UDP). I accept the offered suggestion (private network). The console app then works fine.
I dont want the user to deal with this, so I have added the code below. However when I investigate what this has done in Control Panel > Firewall, it seems to have enabled it for the 'public network' rather than the private network. This is no use as far as allowing my app to work.
Is there an adjustment in the code below to force it to the private network?
INetFwOpenPorts ports3;
INetFwOpenPort port3 = (INetFwOpenPort)Activator.CreateInstance(
Type.GetTypeFromProgID("HNetCfg.FWOpenPort"));
port3.Port = 1234;
port3.Name = "vshost32.exe";
port3.Enabled = true;
//**UPDATE** added for suggestion in answer below - still doesnt change anything though
port3.Scope = NetFwTypeLib.NET_FW_SCOPE_.NET_FW_SCOPE_LOCAL_SUBNET;
Type NetFwMgrType = Type.GetTypeFromProgID("HNetCfg.FwMgr", false);
INetFwMgr mgr3 = (INetFwMgr)Activator.CreateInstance(NetFwMgrType);
ports3 = (INetFwOpenPorts)mgr3.LocalPolicy.CurrentProfile.GloballyOpenPorts;
ports3.Add(port3);
INetFwRule firewallRule = (INetFwRule)Activator.CreateInstance(
Type.GetTypeFromProgID("HNetCfg.FWRule"));
INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(
Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
firewallRule.ApplicationName = "<path to your app>";
firewallRule.Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW;
firewallRule.Description = " My Windows Firewall Rule";
firewallRule.Enabled = true;
firewallRule.InterfaceTypes = "All";
firewallRule.Name = "<your rule name>";
// Should really check that rule is not already present before add in
firewallPolicy.Rules.Add(firewallRule);
Refer to my answer to your previous question.
Have a look at the following lines:
private static int Main (string [] args)
{
var application = new NetFwAuthorizedApplication()
{
Name = "MyService",
Enabled = true,
RemoteAddresses = "*",
Scope = NET_FW_SCOPE_.NET_FW_SCOPE_ALL,
IpVersion = NET_FW_IP_VERSION_.NET_FW_IP_VERSION_ANY,
ProcessImageFileName = "ServiceAssemblyName.dll",
};
return (FirewallUtilities.AddApplication(application, out exception) ? 0 : -1);
}
The NET_FW_SCOPE_ enumeration has the following values:
NET_FW_SCOPE_ALL = 0,
NET_FW_SCOPE_LOCAL_SUBNET = 1,
NET_FW_SCOPE_CUSTOM = 2,
NET_FW_SCOPE_MAX = 3,
You can further limit the ports, protocol as well as remote addresses to the rule.
UPDATE:
Here is the missing ReleaseComObject function. Place it whatever namespace and remove the reference to ComUtilities.
public static void ReleaseComObject (object o)
{
try
{
if (o != null)
{
if (Marshal.IsComObject(o))
{
Marshal.ReleaseComObject(o);
}
}
}
finally
{
o = null;
}
}
Here is the NetFwAuthorizedApplication class:
namespace MySolution.Configurator.Firewall
{
using System;
using System.Linq;
using NetFwTypeLib;
public sealed class NetFwAuthorizedApplication:
INetFwAuthorizedApplication
{
public string Name { get; set; }
public bool Enabled { get; set; }
public NET_FW_SCOPE_ Scope { get; set; }
public string RemoteAddresses { get; set; }
public string ProcessImageFileName { get; set; }
public NET_FW_IP_VERSION_ IpVersion { get; set; }
public NetFwAuthorizedApplication ()
{
this.Name = "";
this.Enabled = false;
this.RemoteAddresses = "";
this.ProcessImageFileName = "";
this.Scope = NET_FW_SCOPE_.NET_FW_SCOPE_ALL;
this.IpVersion = NET_FW_IP_VERSION_.NET_FW_IP_VERSION_ANY;
}
public NetFwAuthorizedApplication (string name, bool enabled, string remoteAddresses, NET_FW_SCOPE_ scope, NET_FW_IP_VERSION_ ipVersion, string processImageFileName)
{
this.Name = name;
this.Scope = scope;
this.Enabled = enabled;
this.IpVersion = ipVersion;
this.RemoteAddresses = remoteAddresses;
this.ProcessImageFileName = processImageFileName;
}
public static NetFwAuthorizedApplication FromINetFwAuthorizedApplication (INetFwAuthorizedApplication application)
{
return (new NetFwAuthorizedApplication(application.Name, application.Enabled, application.RemoteAddresses, application.Scope, application.IpVersion, application.ProcessImageFileName));
}
}
}

Replacing a method node using Roslyn

While exploring Roslyn I put together a small app that should include a trace statement as the first statement in every method found in a Visual Studio Solution. My code is buggy and is only updating the first method.
The line that is not working as expected is flagged with a “TODO” comment. Please, advise.
I also welcome style recommendations that would create a more streamlined/readable solution.
Thanks in advance.
...
private void TraceBtn_Click(object sender, RoutedEventArgs e) {
var myWorkSpace = new MyWorkspace("...Visual Studio 2012\Projects\Tests.sln");
myWorkSpace.InjectTrace();
myWorkSpace.ApplyChanges();
}
...
using System;
using System.Linq;
using Roslyn.Compilers;
using Roslyn.Compilers.CSharp;
using Roslyn.Services;
namespace InjectTrace
{
public class MyWorkspace
{
private string solutionFile;
public string SolutionFile {
get { return solutionFile; }
set {
if (string.IsNullOrEmpty(value)) throw new Exception("Invalid Solution File");
solutionFile = value;
}
}
private IWorkspace loadedWorkSpace;
public IWorkspace LoadedWorkSpace { get { return loadedWorkSpace; } }
public ISolution CurrentSolution { get; private set; }
public IProject CurrentProject { get; private set; }
public IDocument CurrentDocument { get; private set; }
public ISolution NewSolution { get; private set; }
public MyWorkspace(string solutionFile) {
this.SolutionFile = solutionFile;
this.loadedWorkSpace = Workspace.LoadSolution(SolutionFile);
}
public void InjectTrace()
{
int projectCtr = 0;
int documentsCtr = 0;
int transformedMembers = 0;
int transformedClasses = 0;
this.CurrentSolution = this.LoadedWorkSpace.CurrentSolution;
this.NewSolution = this.CurrentSolution;
//For Each Project...
foreach (var projectId in LoadedWorkSpace.CurrentSolution.ProjectIds)
{
CurrentProject = NewSolution.GetProject(projectId);
//..for each Document in the Project..
foreach (var docId in CurrentProject.DocumentIds)
{
CurrentDocument = NewSolution.GetDocument(docId);
var docRoot = CurrentDocument.GetSyntaxRoot();
var newDocRoot = docRoot;
var classes = docRoot.DescendantNodes().OfType<ClassDeclarationSyntax>();
IDocument newDocument = null;
//..for each Class in the Document..
foreach (var #class in classes) {
var methods = #class.Members.OfType<MethodDeclarationSyntax>();
//..for each Member in the Class..
foreach (var currMethod in methods) {
//..insert a Trace Statement
var newMethod = InsertTrace(currMethod);
transformedMembers++;
//TODO: PROBLEM IS HERE
newDocRoot = newDocRoot.ReplaceNode(currMethod, newMethod);
}
if (transformedMembers != 0) {
newDocument = CurrentDocument.UpdateSyntaxRoot(newDocRoot);
transformedMembers = 0;
transformedClasses++;
}
}
if (transformedClasses != 0) {
NewSolution = NewSolution.UpdateDocument(newDocument);
transformedClasses = 0;
}
documentsCtr++;
}
projectCtr++;
if (projectCtr > 2) return;
}
}
public MethodDeclarationSyntax InsertTrace(MethodDeclarationSyntax currMethod) {
var traceText =
#"System.Diagnostics.Trace.WriteLine(""Tracing: '" + currMethod.Ancestors().OfType<NamespaceDeclarationSyntax>().Single().Name + "." + currMethod.Identifier.ValueText + "'\");";
var traceStatement = Syntax.ParseStatement(traceText);
var bodyStatementsWithTrace = currMethod.Body.Statements.Insert(0, traceStatement);
var newBody = currMethod.Body.Update(Syntax.Token(SyntaxKind.OpenBraceToken), bodyStatementsWithTrace,
Syntax.Token(SyntaxKind.CloseBraceToken));
var newMethod = currMethod.ReplaceNode(currMethod.Body, newBody);
return newMethod;
}
public void ApplyChanges() {
LoadedWorkSpace.ApplyChanges(CurrentSolution, NewSolution);
}
}
}
The root problem of you code is that newDocRoot = newDocRoot.ReplaceNode(currMethod, newMethod); somehow rebuilds newDocRoot internal representation of code so next currMethod elements won't be find in it and next ReplaceNode calls will do nothing. It is a situation similar to modifying a collection within its foreach loop.
The solution is to gather all necessary changes and apply them at once with ReplaceNodes method. And this in fact naturally leads to simplification of code, because we do not need to trace all those counters. We simply store all needed transformation and apply them for whole document at once.
Working code after changes:
public void InjectTrace()
{
this.CurrentSolution = this.LoadedWorkSpace.CurrentSolution;
this.NewSolution = this.CurrentSolution;
//For Each Project...
foreach (var projectId in LoadedWorkSpace.CurrentSolution.ProjectIds)
{
CurrentProject = NewSolution.GetProject(projectId);
//..for each Document in the Project..
foreach (var docId in CurrentProject.DocumentIds)
{
var dict = new Dictionary<CommonSyntaxNode, CommonSyntaxNode>();
CurrentDocument = NewSolution.GetDocument(docId);
var docRoot = CurrentDocument.GetSyntaxRoot();
var classes = docRoot.DescendantNodes().OfType<ClassDeclarationSyntax>();
//..for each Class in the Document..
foreach (var #class in classes)
{
var methods = #class.Members.OfType<MethodDeclarationSyntax>();
//..for each Member in the Class..
foreach (var currMethod in methods)
{
//..insert a Trace Statement
dict.Add(currMethod, InsertTrace(currMethod));
}
}
if (dict.Any())
{
var newDocRoot = docRoot.ReplaceNodes(dict.Keys, (n1, n2) => dict[n1]);
var newDocument = CurrentDocument.UpdateSyntaxRoot(newDocRoot);
NewSolution = NewSolution.UpdateDocument(newDocument);
}
}
}
}

How to get correct data from Active Directory for authentication

I have a client service solution containing a Winforms client application and a WCF service hosted in IIS.
At the WCF service I can easily extract the current user's name (WindowsIdentity.Name) that is logged on at the client by using a custom IAuthorizationPolicy. This is done by getting the WindowsIdentity from the incoming EvaluationContext in the Evaluate method.
The WindowsIdentity.Name will look something like this : MyCompanyGroup\MyName
To be able to bind to an AD account in my own membership model I need to be able to let the user choose an AD user to bind to on the Winforms client. To extract the AD groups and users for a tree I am using the following code:
public static class ActiveDirectoryHandler
{
public static List<ActiveDirectoryTreeNode> GetGroups()
{
DirectoryEntry objADAM = default(DirectoryEntry);
// Binding object.
DirectoryEntry objGroupEntry = default(DirectoryEntry);
// Group Results.
DirectorySearcher objSearchADAM = default(DirectorySearcher);
// Search object.
SearchResultCollection objSearchResults = default(SearchResultCollection);
// Results collection.
string strPath = null;
// Binding path.
List<ActiveDirectoryTreeNode> result = new List<ActiveDirectoryTreeNode>();
// Construct the binding string.
strPath = "LDAP://stefanserver.stefannet.local";
//Change to your ADserver
// Get the AD LDS object.
try
{
objADAM = new DirectoryEntry();//strPath);
objADAM.RefreshCache();
}
catch (Exception e)
{
throw e;
}
// Get search object, specify filter and scope,
// perform search.
try
{
objSearchADAM = new DirectorySearcher(objADAM);
objSearchADAM.Filter = "(&(objectClass=group))";
objSearchADAM.SearchScope = SearchScope.Subtree;
objSearchResults = objSearchADAM.FindAll();
}
catch (Exception e)
{
throw e;
}
// Enumerate groups
try
{
if (objSearchResults.Count != 0)
{
//SearchResult objResult = default(SearchResult);
foreach (SearchResult objResult in objSearchResults)
{
objGroupEntry = objResult.GetDirectoryEntry();
result.Add(new ActiveDirectoryTreeNode() { Id = objGroupEntry.Guid, ParentId = objGroupEntry.Parent.Guid, Text = objGroupEntry.Name, Type = ActiveDirectoryType.Group, PickableNode = false });
foreach (object child in objGroupEntry.Properties["member"])
result.Add(new ActiveDirectoryTreeNode() { Id= Guid.NewGuid(), ParentId = objGroupEntry.Guid, Text = child.ToString(), Type = ActiveDirectoryType.User, PickableNode = true });
}
}
else
{
throw new Exception("No groups found");
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return result;
}
}
public class ActiveDirectoryTreeNode : ISearchable
{
private Boolean _pickableNode = false;
#region Properties
[GenericTreeColumn(GenericTableDescriptionAttribute.MemberTypeEnum.TextBox, 0, VisibleInListMode = false, Editable = false)]
public Guid Id { get; set; }
[GenericTreeColumn(GenericTableDescriptionAttribute.MemberTypeEnum.TextBox, 1, VisibleInListMode = false, Editable = false)]
public Guid ParentId { get; set; }
[GenericTreeColumn(GenericTableDescriptionAttribute.MemberTypeEnum.TextBox, 2, Editable = false)]
public string Text { get; set; }
public ActiveDirectoryType Type { get; set; }
#endregion
#region ISearchable
public string SearchString
{
get { return Text.ToLower(); }
}
public bool PickableNode
{
get { return _pickableNode; }
set { _pickableNode = value; }
}
#endregion
}
public enum ActiveDirectoryType
{
Group,
User
}
The tree could look something like this :
CN=Users*
- CN=Domain Guests,CN=Users,DC=MyCompany,DC=local
- CN=5-1-5-11,CN=ForeignSecurityPrinipals,DC=MyCompany,DC=local
...
CN=Domain Admins
- CN=MyName,CN=Users,DC=MyCompany,DC=local
...
(* = Group)
The name is of a different format and I don't see how this could be compared to the name on the service.
So how do I extract proper Active Directory data for the tree?
I cannot claim to understand what it is that you are asking but here is some information that I hope you will find helpful.
The log in name that you see on your service (i.e. "MyName") corresponds to a property in the AD called sAMAccountName. You can pull sAMAccountName from DirectoryEntry through the Properties collection. For example if you want to show the sAMAccountName for each member of your group you can do the following:
var objSearchADAM = new DirectorySearcher();
objSearchADAM.Filter = "(&(objectClass=group))";
objSearchADAM.SearchScope = SearchScope.Subtree;
var objSearchResults = objSearchADAM.FindAll();
foreach (SearchResult objResult in objSearchResults)
{
using (var objGroupEntry = objResult.GetDirectoryEntry())
{
foreach (string child in objGroupEntry.Properties["member"])
{
var path = "LDAP://" + child.Replace("/", "\\/");
using (var memberEntry = new DirectoryEntry(path))
{
if (memberEntry.Properties.Contains("sAMAccountName"))
{
// Get sAMAccountName
string sAMAccountName = memberEntry.Properties["sAMAccountName"][0].ToString();
Console.WriteLine(sAMAccountName);
}
if (memberEntry.Properties.Contains("objectSid"))
{
// Get objectSid
byte[] sidBytes = (byte[]) memberEntry.Properties["objectSid"][0];
var sid = new System.Security.Principal.SecurityIdentifier(sidBytes, 0);
Console.WriteLine(sid.ToString());
}
}
}
}
}
You might also find UserPrincipal interesting. With this class you can very easily connect to a user object in your AD with the FindByIdentity method as shown below:
var ctx = new PrincipalContext(ContextType.Domain, null);
using (var up = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "MyName"))
{
Console.WriteLine(up.DistinguishedName);
Console.WriteLine(up.SamAccountName);
// Print groups that this user is a member of
foreach (var group in up.GetGroups())
{
Console.WriteLine(group.SamAccountName);
}
}

Categories

Resources