Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Accessing Active Directory

Status
Not open for further replies.

IT4EVR

Programmer
Feb 15, 2006
462
US
I have been tasked to create a component that will access the Active Directory and obtain certain information from it, namely the password expiration date.

I have already created a simple loop that iterates through all the users on the AD domain and prints out certain properties of the Directory Entry. However, I am not able to access many of the other properties even though I am calling them in my procedure. I don't get any error messages, they just don't display.

I'm assuming this is because I would need to become a domain-wide admin to access these properties?
 
I have been able to create the programming that accesses Active Directory.

Now the question is, should I make this a regular console type exe or a windows service app?

The nature of the application is an automated email program that would loop through an Active Directory domain and then send various emails based on certain conditions.

This only needs to run once per day, so I couldn't see the reasoning behind making this a Windows service. I would think a Windows service would apply more to a program that you want running for long periods of time.

Would a Windows service application be of use here?

Thanks
 
i would go with the windows service

why: its always running, if it crashes windows will auto restart also on computer boot

you cna simple add a timer to the sevice saying hety its "x" o clock perofomr the action.

it doesnt really matter actually
you can also make a console app and let a windows task manager or whatave run it daily.

but again the service is more reliable (that task crap in window or schedule what is it i hate it)

so if you ask me go with the service
 
Thanks for the info, so if I create it as a windows service, can I then set it so it runs at a certain time every day? And I could use a timer to shut down the service after it runs successfully?

Because if I am running this on a server, it's not, or shouldn't be rebooting. I don't see anything in my services where I can set it to run a certain time.
 
Ok, it looks like I am going to have to create a Windows Service project. Basically I am going to have to run this .exe under a specific account different from the account logged on my local machine.

I'm assuming a Windows Service is the best bet for this?

Or could I just run a Console app that spawns a thread running under this account?

I've looked for some code examples online but haven't found anything satisfactory.

 
Also I should let you know that I am running .NET 1.1. I understand the 2.0 version provides a signature off of the process.start method that allows you to specify a username, password and domain. I don't think 1.1 provides that functionality.
 
I saw a code sample using PInvoke with personalization so I am going to give this a whirl.

I guess this is another reason to convert to 2.0.
 
IT4EVR - would you consider posting your code for searching through Active Directory?

I am going to be doing some work which requires some information from AD to be utilised and don't really know where to start - any code that you have would be a help.

Thanks,

Mark.
 
I'll put something up this afternoon...
 
This is a very simplified version of the code I worked on but may give you a few clues about how to do things. You will have to substitute your domain name in the code. Generally the server that your active directory is on has an address such as myserver.mycompany.com or to that effect.

Below I am not accessing a lot of properties. There are a lot more out there. The ones I am accessing here are UserName, SAMAccountName, Password Last Changed Date, etc.

The GetInt64FromLargeInteger method is necessary because some dates from ActiveDirectory are in the format of a 19-digit large integer. This number actually represents the number of nanoseconds since December 31, 1600.

Since you are using COM here, you absolutely must account for COM exceptions in your code.

If you have any questions, please let me know.

Code:
using System;
using System.DirectoryServices;
using System.Runtime.InteropServices;

namespace Pass_Expire
{
	/// <summary>
	/// Summary description for AD_Test.
	/// </summary>
	public class AD_Test
	{
		static DirectorySearcher mySearcher;
		static ActiveDs.IADsUser iuser;
		static DateTime lastChangedDate;
		const Int64 iSeconds = 864000000000;
		
		public AD_Test()
		{
			//Default constructor
		}
		[STAThread]
		static void Main(string[] args)
		{
			
			getDomainUsers();	
			

		}
		static void getDomainUsers()
		{
			
			using(DirectoryEntry entry = new DirectoryEntry("LDAP://<domainName>"))
			{
						
				//Determine the number of Max Password Aging scheme (days) of the domain
				Int64 i = Math.Abs(GetInt64FromLargeInteger(entry.Properties["maxPwdAge"].Value)/iSeconds);
				Console.WriteLine("Max Password Age: " + i.ToString() + " days");
				//Set the directory path to point only to the authorized software installers OU
				entry.Path="LDAP://<domainName>/OU=Authorized Software Installers,OU=Users OU,DC=<domainName>,DC=yourCompany,DC=com";
				
						
				//Use the directory searcher to look for only class of users
				mySearcher = new DirectorySearcher(entry);
				mySearcher.Filter = ("(objectClass=user)");
				//Console.WriteLine("========================================");    
			}
			//Loop through each user in the domain and write out properties
			//to the console
			foreach(SearchResult sr in mySearcher.FindAll())
			{
				//Enumerate through various user properties
				try
				{
					using(DirectoryEntry de=sr.GetDirectoryEntry())
					{
						//Write out the user properties to the screen
						Console.WriteLine("Display Name  : " + de.Properties["DisplayName"].Value.ToString());
						Console.WriteLine("User Name     : " + de.Properties["sAMAccountName"].Value.ToString());
						/* Convert the directory entry user object into the IADs user object
						 * this allows easier access to user properties */						
						iuser=(ActiveDs.IADsUser)de.NativeObject;	
					
						Int64  z = GetInt64FromLargeInteger(de.Properties["pwdLastSet"].Value);
						//If PwdLastSet <> 0 then we have an active user
						if(z != 0)
						{
							lastChangedDate = iuser.PasswordLastChanged;
							Console.WriteLine("Date Password Changed:   " +
								lastChangedDate.ToShortDateString()); 
						}
					}		
					Console.WriteLine();					
				}
					
				catch(COMException ex)
				{
					//Alert the user that an error occurred
					Console.WriteLine("COM ERROR: " + ex.Message);
				}
				catch(Exception ex)
				{
					//Alert the user that an error occurred
					Console.WriteLine("GENERIC ERROR: " + ex.Message);
				}
				finally
				{
					
					iuser = null;
					
				}				
				                         
				
			}
			
			
		}

		private static Int64 GetInt64FromLargeInteger(object largeInteger)
		{				   
			//Declarations
			Int32 low;
			Int32 high;
			byte[] valBytes = new byte[70];			
			
			try
			{
				ActiveDs.IADsLargeInteger longInt = (ActiveDs.IADsLargeInteger)largeInteger;
				low = longInt.LowPart;
				high = longInt.HighPart;
			
			
				BitConverter.GetBytes(low).CopyTo(valBytes, 0);
				BitConverter.GetBytes(high).CopyTo(valBytes, 4);
			}
			catch(COMException ex)
			{
				Console.WriteLine(ex.Message + "\n" + ex.Source);
				return 0;
			}
			catch(Exception ex)
			{
				Console.WriteLine(ex.Message + "\n" + ex.Source);
				return 0;
			}
			finally
			{
				
			}
			
			return BitConverter.ToInt64(valBytes, 0);			
			
		}



	}//end of class
}//end of namespace
 
This looks great - I'll have a play with it as soon as I can.

Thanks for posting.

Mark.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top