I am trying to perform a query to Active Directory to obtain all the first names of every user. So I have created a new console application and in my main method have the following code:
try
{
DirectoryEntry myLdapConnection =new DirectoryEntry("virtual.local");
myLdapConnection.Path = "LDAP://DC=virtual,DC=local";
DirectorySearcher search = new DirectorySearcher(myLdapConnection);
search.PropertiesToLoad.Add("cn");
SearchResultCollection allUsers = search.FindAll();
I have added some code to check that the connection is being made and that the path can be found. I also ensure that the Collection is not empty.
//For Debugging
if(DirectoryEntry.Exists(myLdapConnection.Path())
{
Console.WriteLine("Found");
}
else Console.WriteLine("Could Not Find LDAP Connection");
//In my case prints 230
Console.WriteLine("Total Count: " + allUsers.Count);
foreach(SearchResult result in allUsers)
{
//This prints out 0 then 1
Console.WriteLine("Count: " + result.Properties["cn'].Count);
if (result.Properties["cn"].Count > 0) //Skips the first value
{
Console.WriteLine(String.Format("{0,-20} : {1}",
result.Properties["cn"][0].ToString())); //Always fails
}
}
}
catch (Exception e)
{
Console.WriteLine("Exception caught:\n\n" + e.ToString());
}
I have specified in the code, where it prints out the properties, that it always fails. I get a System.FormatException being caught here that states the Index must be greater than zero and less than the size of the argument list.
So in the end I'm not really sure how "result.Properties" works and was wondering if you had any advise on how to fix or troubleshoot the problem.
You are defining two format specifiers {0} and {1} but only specifying one argument.
Related
I tried to get the element like Identifier, Location, Period, ... But not working. How can I get it?
My code follow:
static void Main(string[] args)
{
//The fhir server end point address
string ServiceRootUrl = "http://stu3.test.pyrohealth.net/fhir";
//Create a client to send to the server at a given endpoint.
var FhirClient = new Hl7.Fhir.Rest.FhirClient(ServiceRootUrl);
// increase timeouts since the server might be powered down
FhirClient.Timeout = (60 * 1000);
Console.WriteLine("Press any key to send to server: " + ServiceRootUrl);
Console.WriteLine();
Console.ReadKey();
try
{
//Attempt to send the resource to the server endpoint
Hl7.Fhir.Model.Bundle ReturnedSearchBundle = FhirClient.Search<Hl7.Fhir.Model.Patient>(new string[] { "status=planned" });
Console.WriteLine(string.Format("Found: {0} Fhirman patients.", ReturnedSearchBundle.Total.ToString()));
Console.WriteLine("Their logical IDs are:");
foreach (var Entry in ReturnedSearchBundle.Entry)
{
Console.WriteLine("ID: " + Entry.Resource.Id);
Console.WriteLine("ID2: " + Entry.Identifier);
}
Console.WriteLine();
}
catch (Hl7.Fhir.Rest.FhirOperationException FhirOpExec)
{
//Process any Fhir Errors returned as OperationOutcome resource
Console.WriteLine();
Console.WriteLine("An error message: " + FhirOpExec.Message);
Console.WriteLine();
string xml = Hl7.Fhir.Serialization.FhirSerializer.SerializeResourceToXml(FhirOpExec.Outcome);
XDocument xDoc = XDocument.Parse(xml);
Console.WriteLine(xDoc.ToString());
}
catch (Exception GeneralException)
{
Console.WriteLine();
Console.WriteLine("An error message: " + GeneralException.Message);
Console.WriteLine();
}
Console.WriteLine("Press any key to end.");
Console.ReadKey();
}
The result is System.Collections.Generic.List`1[Hl7.Fhir.Model.Identifier]
Your search is for a Patient, which does not have a 'status' search parameter nor field. The server you use eliminates the parameter for the search, and sends back a Bundle with Patients in the entries - this is according to the FHIR specification.
The first line in your foreach (Console.WriteLine("ID: " + Entry.Resource.Id);) will output the technical id of the resource. Since there is no Identifier field on the Entry, I assume your second one actually reads Entry.Resource.Identifier.
The Patient.identifier field is a 0..* list of Identifiers, so you would have to take one of them. The Identifier datatype in turn is a complex datatype, with usually a system and value field filled in. So, you could do something like this - assuming the Identifier list contains an item:
var patient = (Patient)Entry.Resource;
Console.WriteLine($"Patient identifier: {patient.Identifier[0].System} {patient.Identifier[0].Value}");
I hope there may be some insight and maybe help in relation to my query.
I am trying to write the last module to a customised Windows Recovery environment, based on WinPE for Windows 10.
The solution currently utilises DiskPart to create the Disk Partitions (inline with Microsoft advice here), with the change of not providing for the WinRE partition.
After a fair amount of research and tinkering with a project found on MSDN, I managed to get a working project that would clear/partition and format a disk using WMI (MSFT_Disk,MSFT_Partition & MSFT_Volume). That is fully working within Windows 10 on a virtual disk of 15 GiB size.
When I tried it in WinPE (as this will be the OS that it will be used on), it failed on multiple elements, even though the Methods were reported as there). (MSFT_Disk::Clear, MSFT_Volume::Format).
On inspecting the result of my work in DiskPart, I noticed that even though MSFT_Volume::Format had a return value of 2 "Unknown Error" it had actually formatted the data partition (NTFS, ClusterSize 4096). However, when when the Format method is applied to the ESP (FAT32, cluster size 512/1024/4096)it fails fully, with the FileSystem still being reported as RAW, but will apply an AccessPath. "ExtendedStatus" only returns Error 2 (unless I am not accessing it correctly).
Has anyone else had this problem and managed to rectify the problem? Multiple Google searches have thrown out the idea that there maybe a WMI error, but within PowerShell, not as coded in C#/C++. Below are some code snippets and screen shots:
Creating the Partition:
try
{
parameters = disk.GetMethodParameters("CreatePartition");
}
catch (Exception e)
{
Console.WriteLine("Exception in Line 88: " + e.Message);
}
if (PartitionType != "PRIMARY")
{
FillInvocationParameters(parameters, new Dictionary<string, object> { { "Size", _partitionSize.ToString() },
{ "AssignDriveLetter", false },
{ "GpTType", _partitionType} });
}
else
{
FillInvocationParameters(parameters, new Dictionary<string, object> { { "UseMaximumSize", true },
{ "AssignDriveLetter", false },
{ "GpTType", _partitionType} });
}
try
{
res = disk.InvokeMethod("CreatePartition", parameters, null);
objresult = res["ReturnValue"]; //write error handliong routine for the objResult.
Int32.TryParse(objresult.ToString(), out intRes);
}
catch (Exception e)
{
Console.WriteLine("Exception in Line 146: " + e.Message);
ErrorID = Marshal.GetLastWin32Error();
return false;
}
if (intRes != 0)
{
Console.Write("CreatePartition {0} failed with the result: {1} Line 111.", PartitionType, objresult.ToString());
Console.ReadKey();
ErrorID = Marshal.GetLastWin32Error();
return false;
}
//this is the format point for EFI System Disk.. MSFTPARTITIONtoVOLUME MSFT VOLUME::FORMAT
Console.Write($"{PartitionType} Partition has been created\r\n");
string partition = ((ManagementBaseObject)res["CreatedPartition"])["__PATH"] as string;
var MSFT_Partition = new ManagementObject(#"root\Microsoft\Windows\Storage", partition, null);
var partitionIndex = partition.IndexOf(#"ObjectId=\");
partition = partition.Substring(partitionIndex);
partitionIndex = partition.IndexOf(#"}\\");
partitionIndex = partitionIndex + 1;
partition = partition.Substring(0, partitionIndex);
var strMSFTPartition = partition;
partition = partition.Replace("root", "ROOT");
var partitionGuid = MSFT_Partition["Guid"] as string;
Console.WriteLine("Line 138: New Partition GUID: " + partitionGuid);
Parameters is declared as:
ManagementBaseObject parameters = null;
FillInvokationParamters:
private static void FillInvocationParameters(ManagementBaseObject InvocationParameters, IDictionary<string, object> parameters)
{
foreach (var pair in parameters)
{
string stringParamValue;
var managementObjectParam = pair.Value as ManagementObject;
var arrayParam = pair.Value as string;
if (managementObjectParam != null)
{
stringParamValue = managementObjectParam.GetText(TextFormat.CimDtd20);
InvocationParameters[pair.Key] = stringParamValue;
}
else if (arrayParam != null)
InvocationParameters[pair.Key] = arrayParam;
else if (pair.Value != null)
{
stringParamValue = pair.Value.ToString();
InvocationParameters[pair.Key] = stringParamValue;
}
}
}
And the Format Method call:
try
{
Console.Write("Line 174: Attempting to Format with MSFT_Volume::Format FileSystem {0}, Label: {1}, ClusterSize: {2}\r\n", _FileSystem, _VolumeLable, _allocationUnit.ToString());
parameters = MSFTVolume.GetMethodParameters("Format");
FillInvocationParameters(parameters, new Dictionary<string, object>{ { "FileSystem", _FileSystem },
{ "AllocationUnitSize", _allocationUnit },
{ "FileSystemLabel", _VolumeLable },
{ "Full", false} });
res = MSFTVolume.InvokeMethod("Format", parameters, null);
objresult = res["ReturnValue"];
Int32.TryParse(objresult.ToString(), out intReslt);
}
catch (Exception e)
{
Console.WriteLine("Line: 189 The Following error occured while attmpeting to Format the Volume: " + e.Message);
ErrorID = Marshal.GetLastWin32Error();
return false;
}
For the ESP the following applies:
switch(PartitionType)
{
case "EFI":
{
_partitionType = "{c12a7328-f81f-11d2-ba4b-00a0c93ec93b}";
_partitionSize = 260 /*bytes*/ *1024 /*Kilobytes*/ *1024 /*Megabytes*/;
_FileSystem = "FAT32";
_allocationUnit = 1024;
_VolumeLable = "System";
break;
}
}
Screenshots of my console app and diskpart results:
Format Disk Console output
DiskPart Results
Any help/insights will be gratefully appreciated.
Regards
Richie
Note that there are several builds of the ADK for newer builds of Windows 10...be sure to use the latest and greatest. We had issues similar to yours with both dism.exe and diskpart.exe. At one point, (on early win 10 adks) we got dism.exe and diskpart.exe from an 8.1 adk. Hacky as heck, but you gotta do what you gotta do :-)
Update:
Checked with the support group...turns out, I got the versions mixed up. The very first win 10 adk had a working dism and diskpart (adk for windows 10 1503)...and we've been unable to use newer ones from within PE since...and so we're still deploying a new winpe from new ADK - but copying in the diskpart and dism saved off from the 1503 adk. We never deployed 8.1 versions - my bad. Still - hacky as all git out.
Best we can recollect, it only presented a problem in one side of the house...either BIOS+MBR or UEFI+GPT...but none of us remember which.
I am making a research of users in Active Directory using an asp.NET MVC5 website. When I make an invalid search (eg. '"éééézztaaz'), an ArgumentException keeps getting thrown, but I do not understand it. Here is my method to search :
public List<ADProperties> SearchUserByName(string name)
{
//ADProperties is a POCO to store values retrieved
try
{
List<ADProperties> theListIWant = new List<ADProperties>();
//createDirectoryEntry() is a method to establish a connection to Active Directory
DirectoryEntry ldapConnection = createDirectoryEntry();
DirectorySearcher search = new DirectorySearcher(ldapConnection);
//Search filter to find users
search.Filter = "(&(objectClass=user)(anr=" + name + "))";
///Properties to load
search.PropertiesToLoad.Add("objectSID");
search.PropertiesToLoad.Add("displayName");
search.PropertiesToLoad.Add("distinguishedName");
resultCollection = search.FindAll();
//ArgumentException at if statement
//I put this to AVOID exceptions, then in my controller, if value is null
//I return a different view
if (resultCollection==null ||resultCollection.Count==0)
{
return null;
}
}
else
{ //Do stuff and return
return theListIWant;
}catch(ActiveDirectoryOperationException e)
{
Console.WriteLine("Active Directory Operation Exception caught: " + e.ToString());
}
return null;
}
The exact exception is:
The search filter (&(objectClass=user)(anr=)) isn't valid
(Translated from french)
So I don't get it. I added the condition to avoid throwing exceptions but apparently it doesn't help.
I would suggest changing:
if (resultCollection==null ||resultCollection.Count==0)
{
return null;
}
to:
try
{
if (resultCollection == null || resultCollection.Count == 0)
{
return null;
}
}
catch (ArgumentException)
{
return null;
}
This will ensure that if ArgumentException is thrown, it will be treated the same way as if resultCollection is null.
I am having a problem updating user information in an Active Directory DB...
When I run the following code I get this error:
The specified directory service attribute or value does not exist
The problem is the path it is using to save the information is this:
CN=AD Test,OU=Container Name,DC=us,DC=flg,DC=int
Ad Test is the username in AD that I am trying to update.
and I believe it should be:
CN=Ad Test,OU=Container Name, OU=Server Name,DC=us,DC=flg,DC=int
I am new to Directory services so I would greatly appreciate any help in finding out why I cannot update... Thank you in advance
public bool UpdateActiveDirectory(string LdapServerName, string CustId, Employee SQLresult)
{
try
{
DirectoryEntry rootEntry = new DirectoryEntry("LDAP://" + LdapServerName, "usrename", "password", AuthenticationTypes.Secure);
DirectorySearcher searcher = new DirectorySearcher(rootEntry);
searcher.Filter = "(sAMAccountName=" + SQLresult.LogonNT + ")";
searcher.PropertiesToLoad.Add("title");
searcher.PropertiesToLoad.Add("street");
searcher.PropertiesToLoad.Add("1");
searcher.PropertiesToLoad.Add("st");
searcher.PropertiesToLoad.Add("postalCode");
searcher.PropertiesToLoad.Add("department");
searcher.PropertiesToLoad.Add("mail");
searcher.PropertiesToLoad.Add("manager");
searcher.PropertiesToLoad.Add("telephoneNumber");
SearchResult result = searcher.FindOne();
if (result != null)
{
// create new object from search result
DirectoryEntry entryToUpdate = result.GetDirectoryEntry();
entryToUpdate.Properties["title"].Value = SQLresult.Title;
entryToUpdate.Properties["street"].Value = SQLresult.Address;
entryToUpdate.Properties["1"].Value = SQLresult.City;
entryToUpdate.Properties["st"].Value = SQLresult.State;
entryToUpdate.Properties["postalCode"].Value = SQLresult.ZipCode;
entryToUpdate.Properties["department"].Value = SQLresult.Department;
entryToUpdate.Properties["mail"].Value = SQLresult.EMailID;
entryToUpdate.Properties["manager"].Value = SQLresult.ManagerName;
entryToUpdate.Properties["telephoneNumber"].Value = SQLresult.Phone;
entryToUpdate.CommitChanges();
Console.WriteLine("User Updated");
}
else
{
Console.WriteLine("User not found!");
}
}
catch (Exception e)
{
Console.WriteLine("Exception caught:\n\n" + e.ToString());
}
return true;
}
Maybe just a typo?
The third property you're trying to update:
entryToUpdate.Properties["1"].Value = SQLresult.City;
is that a one (1) in there? It should be a small L (l) instead.
Also: the manager's name must be the Distinguished Name of the manager - the whole
CN=Manager,CN=Ad Test,OU=Container Name, OU=Server Name,DC=us,DC=flg,DC=int
thing - not just the name itself.
If that doesn't help anything - just go back to old-school debugging technique:
update just a single property; if it fails --> that's your problem case - figure out why it's a problem.
If it works: uncomment a second property and run again
-> repeat over and over again, until you find your culprit
I got some code of a tool which does many security checks on client machines and I'm trying to understand some bug and solve it - need your help.
There is a test which checks if the user password is set to "never expire". I tried this test offline and in 3 different networks and it seems to be working. There is some WIFI guest network in my company which return exception while executing the code.
Here is the exception I'm getting:
The network path was not found.
at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
at System.DirectoryServices.DirectoryEntry.Bind()
at System.DirectoryServices.DirectoryEntry.get_NativeObject()
at System.DirectoryServices.DirectoryEntry.InvokeGet(String propertyName)
at Intel.HostCheck.Engine.Checks.PasswordAge.CheckPasswordNeverExpired()
See the the following code for understanding the test implementation:
private CheckResult CheckPasswordNeverExpired()
{
try
{
DirectoryEntry de;
Logger.Debug("Password Age: isCurrentUserLocalUser - " + HelpFunction.isCurrentUserLocalUser());
if (HelpFunction.isCurrentUserLocalUser())
de = new DirectoryEntry("WinNT://" + Environment.MachineName + "/" + Environment.UserName);
else de = new DirectoryEntry("WinNT://" + Environment.UserDomainName + "/" + Environment.UserName);
object currentUser = de.InvokeGet("UserFlags");
if (currentUser != null)
{
Logger.Debug("PasswordAge: " + currentUser);
Logger.Debug("PasswordAge: " + Convert.ToBoolean((int)currentUser & UF_DONT_EXPIRE_PASSWD).ToString());
}
if (Convert.ToBoolean((int)currentUser & UF_DONT_EXPIRE_PASSWD))
{
Logger.Debug("Password Age: check result: fail ");
return CheckResult.Fail;
}
Logger.Debug("Password Age: check result: pass ");
return CheckResult.Pass;
}
catch (Exception ex)
{
Logger.LogException(ex, "Error in PasswordAge->Check()");
return CheckResult.Exception;
}
}
}
public static bool isCurrentUserLocalUser()
{
return Environment.MachineName == Environment.UserDomainName;
}
Just for clarification, it's not my code so I'm not completely sure what the code owner did.
I'm seeing that there are no responses. I will ask different question.
Is there any option to obtain password age or password last set values without be depend on network connection? Is it possible to check it locally?
I know this value also exists under "Local security policy" but I didn't find how to get it by code.