Listing windows user accounts using C# - c#

I have to list all users (both local system and domain). I tried using WQL but it takes a lot of time for the program to run. Is there any other way to get it from registry? Any help would be appreciated.

using System;
using System.Collections.Generic;
using System.DirectoryServices;
namespace ListADUsers.ConsoleApp
{
class Program
{
static void Main(string[] args)
{
Console.Clear();
IList<String> userList = new List<String>();
int badEntries = 0;
string domainName = String.Empty;
if (args.Length > 0)
domainName = args[0];
else
{
Console.Write("\nPlease enter your Active Directory domain name: ");
domainName = Console.ReadLine();
}
Console.Write(String.Format("\nAttempting to build user list for {0} ...\n\n", domainName));
try
{
if (!String.IsNullOrEmpty(domainName))
{
DirectoryEntry myDirectoryEntry = new DirectoryEntry(String.Format("LDAP://{0}", domainName));
DirectorySearcher mySearcher = new DirectorySearcher(myDirectoryEntry);
SortOption mySort = new SortOption("sn", SortDirection.Ascending);
mySearcher.Filter = ("(objectCategory=person)");
mySearcher.Sort = mySort;
foreach (SearchResult resEnt in mySearcher.FindAll())
{
try
{
if (!String.IsNullOrEmpty(resEnt.Properties["Mail"][0].ToString())
&& System.Text.RegularExpressions.Regex.IsMatch(resEnt.Properties["DisplayName"][0].ToString(), " |admin|test|service|system|[$]", System.Text.RegularExpressions.RegexOptions.IgnoreCase)
)
{
int space = resEnt.Properties["DisplayName"][0].ToString().IndexOf(" ");
string formattedName = String.Format("{0}{1}{2}",
resEnt.Properties["DisplayName"][0].ToString().Substring(space).PadRight(25),
resEnt.Properties["DisplayName"][0].ToString().Substring(0, space).PadRight(15),
resEnt.Properties["Mail"][0].ToString()
);
userList.Add(formattedName);
}
}
catch
{
badEntries++;
}
}
if (userList.Count > 0)
{
Console.WriteLine(String.Format("=========== Listing of users in the {0} domain\n", domainName));
Console.WriteLine(String.Format("{0}{1}{2}", "Surname".PadRight(25), "First Name".PadRight(15), "Email Address\n"));
for (int i = 0; i < userList.Count - 1; i++)
Console.WriteLine(userList[i].ToString());
Console.WriteLine(String.Format("\n=========== {0} users found in the {1} domain", userList.Count.ToString(), domainName));
}
else
Console.WriteLine(String.Format("\n=========== 0 users found in the {0} domain", userList.Count.ToString()));
Console.WriteLine(String.Format("=========== {0} objects could not be read", badEntries.ToString()));
Console.WriteLine("=========== End of Listing");
}
else
{
Console.WriteLine("Please enter a domain name next time!");
}
}
catch (Exception ex)
{
// in a production app you wouldn't show the user the exception details
Console.Write(String.Format("A critical error occurred.\nDetails: {0}", ex.Message.ToString()));
}
}
}
}
Download sample application : Sample Application to List AD Users
Source : Follow Up – List active directory users – This time in C#

Related

RAVENDB The name "Store" doesn't exist in the current context

I've been working on getting this to work all day, and haven't had any success. I want to clean up my code and separate different chunks of code into different classes and functions. Here is a chunk of code that refuses to run.
using System;
using Raven.Client.Documents;
namespace RavendbTest
{
class Program
{
static void Main(string[] args)
{
var store = new DocumentStore
{
Urls = new[] { "http://localhost:8080" },
Database = "Tasks"
};
store.Initialize();
}
static void Checking()
{
Console.WriteLine("Login or Sign Up? (L/S)");
string userInput = Console.ReadLine();
if (userInput.ToLower() == "l")
{
Console.WriteLine("Logging you in");
}
else if (userInput.ToLower() == "s")
{
Console.WriteLine("Signing you up\n");
Console.Write("First Name: ");
string firstName = Console.ReadLine();
char firstNameInitial = firstName.ToLower()[0];
Console.WriteLine(firstNameInitial);
Console.Write("Last Name: ");
string lastName = Console.ReadLine();
char lastNameInitial = lastName.ToLower()[0];
Console.WriteLine(lastNameInitial);
Console.Write("Email: ");
string email = Console.ReadLine();
string combinedInitial = firstNameInitial.ToString() + lastNameInitial.ToString();
Console.WriteLine(combinedInitial);
// Checking if email has a '#' symbol in it. Determine validity
bool isVerified = false;
for (int i = 0; email.Length > i; i++)
{
if (email[i] != '#')
{
continue;
}
else if (email[i] == '#')
{
isVerified = true;
}
}
if (isVerified == true)
{
using (var session = Store.OpenSession())
{
var task = session.Load<Entity>(combinedInitial + email);
if (task == null)
{
Console.WriteLine("Creating your account");
var newUser = new Entity
{
Id = combinedInitial + email,
FirstName = firstName,
LastName = lastName,
Email = email
};
session.Store(newUser);
session.SaveChanges();
}
else
{
Console.WriteLine("This email is already in use... Would you like to login? (Y/N)");
string changeChoice = Console.ReadLine();
if (changeChoice.ToLower()[0] == 'y')
{
}
else
{
Console.WriteLine("Exiting Program");
}
}
using (var session = store.OpenSession())
{
var task = session.Load<Entity>(combinedInitial + email);
}
}
}
else
{
Console.WriteLine("Please enter a valid email address");
Console.WriteLine("Exiting Program");
}
}
else
{
Console.WriteLine("Error");
}
}
}
}
I thinking that I'm getting errors because my function checking can't see that I've already initialize a DocumentStore. Any help is greatly appreciated

C# - connecting to SQL Server

At the beginning of my journey with C#, I am developing this simple Flashcard app. It can be used for learning vocabulary in new language.
I have created Flashcard class, also have been able to create functions allowing users to enter new words, revise them and play simple guessing game.
When creating new words, program ask user how many one, would like to create. Then uses object of Flashcard function n times, filling list with them.
After every operation like this, I'd like to insert new words, and its translation into a SQL Server database, although I've encountered first problem.
Flashcard.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FlashCardApp
{
class Flashcard
{
private string Word;
private string Translation;
private string Description;
public bool IsKnownTemporarly;
public Flashcard(string word, string translation, string description)
{
Description = description;
Word = word;
Translation = translation;
IsKnownTemporarly = false;
}
public Flashcard()
{
Description = "Default description";
Translation = "Defualt translation";
Word = "Default word";
IsKnownTemporarly = false;
}
public Flashcard(Flashcard flashcard)
{
Description = flashcard.Description;
Word = flashcard.Word;
Translation = flashcard.Translation;
IsKnownTemporarly = flashcard.IsKnownTemporarly;
}
public string returnWord()
{
return Word;
}
public string returnDescription()
{
return Description;
}
public string returnTranslation()
{
return Translation;
}
public void CreateNewFlashcard()
{
Console.Write ("Word => ");
Word = Console.ReadLine();
Word = Word.ToLower();
Console.Write("Description => ");
Description = Description = Console.ReadLine();
Description = Description.ToLower();
Console.Write("Translation => ");
Translation = Console.ReadLine();
Translation = Translation.ToLower();
IsKnownTemporarly = false;
Console.Clear();
}
public void DisplayFlaschard()
{
Console.WriteLine(Word + " means " + Translation + " [" + Description + "]");
Console.ReadKey();
}
public void GuessWord()
{
Console.WriteLine("Do you remember this one? [" + Word + "]");
string userInput = Console.ReadLine();
if (userInput.ToLower() == Translation)
{
this.IsKnownTemporarly = true;
Console.WriteLine("Indeed, that is correct!");
Console.ReadKey();
Console.Clear();
}
else
{
Console.WriteLine("I'll help you this time, try to memorize!");
Console.WriteLine(Word + " means " + Translation + " [" + Description + "]");
this.IsKnownTemporarly = false;
Console.ReadKey();
Console.Clear();
}
}
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;
namespace FlashCardApp
{
class Program
{
static void Main(string[] args)
{
List<Flashcard> FlashcardsList = new List<Flashcard>();
Flashcard flashcard1 = new Flashcard("Car", "auto" ,"it drives
through streets");
Flashcard flashcard2 = new Flashcard("street", "droga" , "Lead you
around cities");
Flashcard flashcard3 = new Flashcard("screen", "ekran", "It displays
info");
Flashcard flashcard4 = new Flashcard("stapler", "zszywacz",
"costam");
Flashcard flashcard5 = new Flashcard("paper", "papier", "costam");
Flashcard flashcard6 = new Flashcard("pen", "dlugopis", "dligpsfs");
FlashcardsList.Add(flashcard1);
FlashcardsList.Add(flashcard2);
FlashcardsList.Add(flashcard3);
FlashcardsList.Add(flashcard4);
FlashcardsList.Add(flashcard5);
FlashcardsList.Add(flashcard6);
ConnectDB();
}
public static void ConnectDB()
{
string connectionString;
SqlConnection conn;
connectionString = #"Data Source=DESKTOP-RDM63QN\SQLEXPRESS; Initial
Catalog=Fishcards; User ID=MyName ;Password=MyPassword" ;
conn = new SqlConnection(connectionString);
conn.Open();
Console.WriteLine("Done!");
conn.Close();
}
public static void AddNewFlaschards(List<Flashcard> FlashcardsList)
{
Console.WriteLine("ADD NEW FLASCHARDS!");
Console.WriteLine("How many would you like to add?");
int count = Convert.ToInt32(Console.ReadLine());
Console.Clear();
for (int i = 0; i < count; i++)
{
Flashcard flashcard = new Flashcard();
Console.WriteLine("No. " + (i+1));
flashcard.CreateNewFlashcard();
FlashcardsList.Add(new Flashcard(flashcard));
}
Console.Read();
Console.Clear();
}
public static void ReviseFlashcards(List<Flashcard> FlashcardsList)
{
Console.WriteLine("REVISE YOUR SAVED FLASHCARDS!");
FlashcardsList.ForEach(fl => fl.DisplayFlaschard());
Console.Read();
Console.Clear();
}
public static bool IsThereAnyUnknownLeft(List<Flashcard> FlashcardsList)
{
int var = FlashcardsList.Count; // Merging the size of FlashcardList
int i = 0;
int sum = 0;
int[] array = new int[var];
foreach (Flashcard flashcard in FlashcardsList)
{
if(flashcard.IsKnownTemporarly == false)
{
array[i] = 0;
}
else
{
array[i] = 1;
}
i++;
}
for(int a = 0; a<var; a++)
{
sum = sum + array[a];
}
if (sum == var)
return true;
else
return false;
}
public static void PlayGuessingGame(List<Flashcard> FlashcardsList)
{
while(!IsThereAnyUnknownLeft(FlashcardsList))
{
foreach (Flashcard flashcard in FlashcardsList.Where(flashcard
=> flashcard.IsKnownTemporarly == false))
{
flashcard.GuessWord();
}
}
Console.Read();
Console.Clear();
}
}
}
Problem is that Visual Studio returns an error on conn.Open() with this info:
System.Data.SqlClient.SqlException: Cannot open database "Fishcards" requested by the login. The login failed.
Login failed for user 'MyNameisHere'.

SMO Restore Events Never Fire

We have this scripted restore process , i am trying to add some logging for the percent completed so we have an idea of how far some of our long running backups are into the process
I added an event handler to the PercentCompleted event in our Restore handler but it seems that it never fires as we do not receive any output at all from the callback
Anyone have an idea why this is not working
public void Restore(string backupPath)
{
Logger.Log("Restoring database {0} from backup {1}", Name, backupPath);
using (var con = new SqlConnection(Server.GetConnectionString()))
{
var smoConn = new ServerConnection(con);
smoConn.StatementTimeout = 1200; // FMNET-20792. 20 minutes (default was 10 minutes)
var server = new Server(smoConn);
Logger.Log("Killing all processes in {0}", Name);
try
{
server.KillAllProcesses(Name);
}
catch (FailedOperationException e)
{
Logger.Log("Killing all processed failed with error below. Will still attemp to restore the DB");
Logger.Log(e.ToString());
}
var restore = new Restore();
restore.PercentComplete += (sender, args) =>
{
Logger.Log("Percent Complete {0,3}%", args.Percent);
};
restore.Devices.AddDevice(backupPath, DeviceType.File);
restore.Action = RestoreActionType.Database;
restore.Database = Name;
restore.ReplaceDatabase = true;
string serverDataPath = string.IsNullOrEmpty(server.DefaultFile)
? server.Information.MasterDBPath
: server.DefaultFile;
serverDataPath = Path.GetFullPath(serverDataPath);
Logger.Verbose("Server default data path: {0}", serverDataPath);
string serverLogPath = string.IsNullOrEmpty(server.DefaultLog)
? server.Information.MasterDBLogPath
: server.DefaultLog;
serverLogPath = Path.GetFullPath(serverLogPath);
Logger.Verbose("Server default log path: {0}", serverLogPath);
var files = restore.ReadFileList(server);
int dataFileIndex = 0;
int logFileIndex = 0;
foreach (DataRow row in files.Rows)
{
string logicalName = row["LogicalName"].ToString();
string type = row["Type"].ToString();
string newPhysicalPath;
if (type == "D")
{
newPhysicalPath = string.Format("{0}_Data{1}.mdf", Name,
dataFileIndex > 0 ? dataFileIndex.ToString() : string.Empty);
newPhysicalPath = Path.Combine(serverDataPath, newPhysicalPath);
dataFileIndex++;
}
else if (type == "L")
{
newPhysicalPath = string.Format("{0}_Log{1}.ldf", Name,
logFileIndex > 0 ? dataFileIndex.ToString() : string.Empty);
newPhysicalPath = Path.Combine(serverLogPath, newPhysicalPath);
logFileIndex++;
}
else
{
throw new ApplicationException("Unsupported file type: " + type);
}
var relocateFile = new RelocateFile(logicalName, newPhysicalPath);
Logger.Log("Will relocate {0} to {1}", logicalName, newPhysicalPath);
restore.RelocateFiles.Add(relocateFile);
}
restore.SqlRestore(server);
Logger.Log("Restore complete. Renaming logical files");
var db = server.Databases[Name];
foreach (FileGroup fg in db.FileGroups)
{
for (int i = 0; i < fg.Files.Count; i++)
{
string oldName = fg.Files[i].Name;
string newName = string.Format("{0}_Data{1}", Name, i > 0 ? i.ToString() : string.Empty);
if (!oldName.Equals(newName, StringComparison.InvariantCultureIgnoreCase))
{
Logger.Log("Renaming {0} to {1}", oldName, newName);
fg.Files[i].Rename(newName);
}
else
{
Logger.Log("Oldname equals newname ({0}), nothing to do", oldName);
}
}
}
for (int i = 0; i < db.LogFiles.Count; i++)
{
string oldName = db.LogFiles[i].Name;
string newName = string.Format("{0}_Log{1}", Name, i > 0 ? i.ToString() : string.Empty);
if (!oldName.Equals(newName, StringComparison.InvariantCultureIgnoreCase))
{
Logger.Log("Renaming {0} to {1}", oldName, newName);
db.LogFiles[i].Rename(newName);
}
else
{
Logger.Log("Oldname equals newname ({0}), nothing to do", oldName);
}
}
// Ensure FMAccess user exists in DB and is properly mapped
var fmAccessUser = Env.GetUser("FMAccess");
if (fmAccessUser == null)
{
throw new ApplicationException("Credentials with id=\"FMAccess\" don't exist in the specified environment file. FMAccess user is required when restoring a database.");
}
Logger.Log("Ensuring user {0} exists in the database {1}.", fmAccessUser.Login, Name);
// If a user already exists in DB we drop and re-create it because after restore the mapping to an existing SQL login will be lost anyway.
if (db.Users.Contains(fmAccessUser.Login))
{
Logger.Verbose("User already exists in DB, dropping.");
db.Users[fmAccessUser.Login].Drop();
}
Logger.Verbose("Creating user {0}", fmAccessUser.Login);
var u = new User(db, fmAccessUser.Login) { DefaultSchema = "dbo", Login = fmAccessUser.Login };
u.Create();
var dboRole = db.Roles["db_owner"];
dboRole.AddMember(fmAccessUser.Login);
Logger.Verbose("User created successfully");
}
}

Can't remove items from List with remove()

Hi I would like to remove account names by using a foreach in method readInput that sends the accounts to method DisableADUser that would disable the accounts and remove the name from the global List invalidAccounts (whole code line 7) if the operation is successful.
I have tried using the Remove method and placing it in both the if and else condition in the DisableADUser method but it does not work. How should I go about resolving this? Thanks in advance. :)
readInput method (lines 1- 13)
//Read user input
private static string readInput(string Input)
{
string input = string.Empty;
switch (Input)
{
case "disable":
invalidAccount.ForEach(delegate(String samAccountName)
{
Console.WriteLine('\n' + samAccountName);
//disable inactive accounts
DisableADUser(samAccountName);
});
//count number of invalid accounts
int invalidAccounts = invalidAccount.Count;
Console.WriteLine("\nExecution has completed. ");
invalidAccount.Clear();
Console.WriteLine("Press [enter] to continue.\n");
input = Console.ReadLine();
break;
case "query":
Console.WriteLine("\nQuery for expiry has finished.\n");
Console.WriteLine("Press [enter] to continue.\n");
input = Console.ReadLine();
break;
case "exit":
//leave console
Environment.Exit(2);
break;
default:
throw new Exception("Invalid command entered.");
}
return input;
}
disableADUser (lines 1- 15)
//disable invalid accounts
private static void DisableADUser(string samAccountName)
{
try
{
PrincipalContext principalContext = new PrincipalContext(ContextType.Domain);
UserPrincipal userPrincipal = UserPrincipal.FindByIdentity
(principalContext, samAccountName);
userPrincipal.Enabled = false;
userPrincipal.Save();
if (userPrincipal.Enabled != true)
{
Console.WriteLine("Account has been disabled successfully");
//remove from list invalidAccounts
invalidAccount.Remove(samAccountName);
}
else
{
Console.Write("Unable to disable account");
//invalidAccount.Remove(samAccountName);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
If needed, I've included my entire code as well.
namespace ConsoleApplication2
{
class Program
{
const int UF_LOCKOUT = 0x0010;
const int UF_PASSWORD_EXPIRED = 0x800000;
private static List<string> invalidAccount = new List<string>();
static void Main(string[] args)
{
string line;
Console.WriteLine("Welcome to account validator V1.1.\n");
do
{
Console.WriteLine("Please enter service account username, password \nand desired ldap address to proceed.\n\n");
//pass username to GetInput method
String serviceAccountUserName = GetInput("Username");
//pass password to GetInput method
String serviceAccountPassword = GetInput("Password");
//pass ldap address to GetInput method
String ldapAddress = GetInput("Ldap address");
try
{
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, ldapAddress))
{
bool isValid = false;
// validate the credentials
isValid = pc.ValidateCredentials(serviceAccountUserName, serviceAccountPassword);
if (isValid)
{
Console.WriteLine("\nQuerying for users from domain " + ldapAddress + " now.\n\n");
//pass login details to GetSAM method
GetSAM(ldapAddress, serviceAccountUserName, serviceAccountPassword);
Console.WriteLine("\nEnter exit to leave.\n");
Console.WriteLine("Enter disable to disable the invalid accounts.\n");
Console.WriteLine("Enter query to find the expiry date of valid accounts.\n");
string Input = Console.ReadLine();
//pass input to readInput method
readInput(Input);
Console.WriteLine("\nEnter exit to leave.");
Console.WriteLine("Press [enter] to query database.");
}//end of if statement for validate credentials
else
{
Console.WriteLine("\nInvalid login credentials.\n");
Console.WriteLine("Press [enter] and enter exit to leave.");
Console.WriteLine("\nPress [enter] [enter] to try again.\n");
Console.ReadLine();
}//end of else statement for validate credentials
}//end of using
}//end of try
catch (Exception e)
{
Console.WriteLine("\nlogin attempt has failed. See exception for more information. ");
throw new Exception("Log in attempt has failed." + " Exception caught:\n\n" + e.ToString());
}//end of catch
}//end of do
while ((line = Console.ReadLine()) != "exit");
//Thread.Sleep(60000);
} //end of main
//Read user input
private static string readInput(string Input)
{
string input = string.Empty;
switch (Input)
{
case "disable":
invalidAccount.ForEach(delegate(String samAccountName)
{
Console.WriteLine('\n' + samAccountName);
//disable inactive accounts
DisableADUser(samAccountName);
});
//count number of invalid accounts
int invalidAccounts = invalidAccount.Count;
Console.WriteLine("\nExecution has completed. " + invalidAccounts + " invalid accounts have been disabled.");
invalidAccount.Clear();
Console.WriteLine("Press [enter] to continue.\n");
input = Console.ReadLine();
break;
case "query":
Console.WriteLine("\nQuery for expiry has finished.\n");
Console.WriteLine("Press [enter] to continue.\n");
input = Console.ReadLine();
break;
case "exit":
//leave console
Environment.Exit(2);
break;
default:
throw new Exception("Invalid command entered. Please enter command again.");
}
return input;
}
// find password expiry date
//Get SAMAccount
private static string GetSAM(string ldapAddress, string serviceAccountUserName, string serviceAccountPassword)
{
string readOutput;
int countAll = 0;
string ldapPath = "LDAP://" + ldapAddress;
string ldapFilter = "(&(objectclass=user)(objectcategory=person))";
DirectoryEntry directoryEntry = new DirectoryEntry(ldapPath, serviceAccountUserName, serviceAccountPassword);
using (DirectorySearcher directorySearcher = new DirectorySearcher(directoryEntry))
{
string samAccountName;
directorySearcher.Filter = ldapFilter;
directorySearcher.SearchScope = SearchScope.Subtree;
directorySearcher.PageSize = 1000;
using (SearchResultCollection searchResultCollection = directorySearcher.FindAll())
{
foreach (SearchResult result in searchResultCollection)
{
samAccountName = result.Properties["sAMAccountName"][0].ToString();
//validate accounts by passing details into valSAM method
if (valSAM(samAccountName, ldapAddress, serviceAccountUserName, serviceAccountPassword) != true)
{
//add invalid account to list invalidAccount
invalidAccount.Add(samAccountName);
}
//count all accounts
countAll++;
} //end of foreach
// Count all invalid accounts
int invalidAccounts = invalidAccount.Count;
Console.WriteLine("\nFound " + invalidAccounts + " invalid accounts out of " + countAll + " user accounts.\n");
Console.WriteLine("Query in " + ldapAddress + " has finished.");
Console.WriteLine("Press [enter] to continue.\n");
readOutput = Console.ReadLine();
}//SearchResultCollection will be disposed here
}
return readOutput;
}
//Validate SAMAccount
private static bool valSAM(string samAccountName, string ldapAddress, string serviceAccountUserName, string serviceAccountPassword)
{
string ldapPath = "LDAP://" + ldapAddress;
DirectoryEntry directoryEntry = new DirectoryEntry(ldapPath, serviceAccountUserName, serviceAccountPassword);
StringBuilder builder = new StringBuilder();
bool accountValidation = false;
//create instance fo the directory searcher
DirectorySearcher desearch = new DirectorySearcher(directoryEntry);
//set the search filter
desearch.Filter = "(&(sAMAccountName=" + samAccountName + ")(objectcategory=user))";
//find the first instance
SearchResult results = desearch.FindOne();
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, ldapAddress))
{
//if users are present in database
if (results != null)
{
//Check if account is activated
bool isAccountActived = IsActive(results.GetDirectoryEntry());
//Check if account is expired or locked
bool isAccountLocked = IsAccountLockOrExpired(results.GetDirectoryEntry());
accountValidation = ((isAccountActived != true) || (isAccountLocked));
//account is invalid
if (accountValidation)
{
builder.Append("User account " + samAccountName + " is invalid. ");
if ((isAccountActived != true) && (isAccountLocked))
{
builder.AppendLine("Account is inactive and locked or expired.");
} else if (isAccountActived != true)
{
builder.AppendLine("Account is inactive.");
}
else if (isAccountLocked)
{
builder.AppendLine("Account is locked or has expired.") ;
}
else
{
builder.AppendLine("Unknown reason. Contact admin for help.");
}
accountValidation = false;
}
//account is valid
if ((isAccountActived) && (isAccountLocked != true))
{
builder.AppendLine("User account " + samAccountName + " is valid.");
accountValidation = true;
}
}
else Console.WriteLine("No users found.");
//print only invalid accounts
if (!accountValidation)
{
//prevent printing of empty lines
if (builder.Length > 0)
{
Console.WriteLine(builder);
}
}
}//end of using
return accountValidation;
}
//Prevent empty user input
private static string GetInput(string Prompt)
{
string Result = string.Empty;
do
{
Console.Write(Prompt + ": ");
Result = Console.ReadLine();
if (string.IsNullOrEmpty(Result)) Console.WriteLine("Empty input, please try again.\n");
}
while (!(!string.IsNullOrEmpty(Result)));
return Result;
}
//check if account is active
static private bool IsActive(DirectoryEntry de)
{
if (de.NativeGuid == null) return false;
int flags = (int)de.Properties["userAccountControl"].Value;
return !Convert.ToBoolean(flags & 0x0002);
}
//check if account is locked or expired
static private bool IsAccountLockOrExpired(DirectoryEntry de)
{
string attribName = "msDS-User-Account-Control-Computed";
de.RefreshCache(new string[] { attribName });
int userFlags = (int)de.Properties[attribName].Value;
return userFlags == UF_LOCKOUT || userFlags == UF_PASSWORD_EXPIRED;
}
//disable invalid accounts
private static void DisableADUser(string samAccountName)
{
try
{
PrincipalContext principalContext = new PrincipalContext(ContextType.Domain);
UserPrincipal userPrincipal = UserPrincipal.FindByIdentity
(principalContext, samAccountName);
userPrincipal.Enabled = false;
userPrincipal.Save();
if (userPrincipal.Enabled != true)
{
Console.WriteLine("User " + samAccountName + "'s account has been disabled successfully");
//remove from list invalidAccounts
invalidAccount.Remove(samAccountName);
}
else
{
Console.Write("Unable to disable account");
//invalidAccount.Remove(samAccountName);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
You can't Remove items from the list you are iterating. It messes with the enumerator to delete things out from under it. You need to copy the items you want to keep to another list instead, and then copy it back if necessary; or create a list of items you want to remove, and remove them all at once at the end.
This has a discussion of various methods: Intelligent way of removing items from a List<T> while enumerating in C#

Find all subfolders of the Inbox folder using EWS

I have the following Inbox folder structure:
Inbox
--ABC
----ABC 2
----ABC 3
--XYZ
----XYZ 2
--123
----123 A
----123 B
----123 C
I am using Exchange Web Services and the following code to find the child folders of the Inbox folder:
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010);
service.AutodiscoverUrl("MyName#MyDomain.com");
Mailbox mb = new Mailbox("MyName#MyDomain.com");
FindFoldersResults findResults = service.FindFolders(
WellKnownFolderName.Inbox,
new FolderView(int.MaxValue));
foreach (Folder folder in findResults.Folders)
{
Console.WriteLine(folder.DisplayName);
}
This partly works because it returns the ABC, XYZ, and 123 folders; unfortunately, it does not return the folders inside each of those folders (ABC 2, ABC 3, XYZ 2, 123 A, 123 B, 123 C).
Also, it is possible that a folder could have more than one level of subfolders inside it.
How can I write this code so that it will return all subfolders regardless of how deeply nested they may be?
You can tell EWS to do a deep traversal when searching the folders. You can do this using the FolderView.Traversal property. Your code would then be changed to something similar to the following:
FindFoldersResults findResults = service.FindFolders(
WellKnownFolderName.Inbox,
new FolderView(int.MaxValue) { Traversal = FolderTraversal.Deep });
You can page your requests and get the entire folder hierarchy from the server in just a few calls. The key is the FolderView.Traversal property, as Jacob indicates.
For example, for an Exchange mailbox with ~1,300 folders the code below only makes 2 requests. You can set your page size to whatever you like, as long as you stay at or below the server limit.
FYI: Exchange Online (Office365) caps at a maximum of 1,000 items in a response. I haven't tested, so I can't speak for any similar limits when querying an on-premises Exchange Server.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security;
using Exchange = Microsoft.Exchange.WebServices.Data; // from nuget package "Microsoft.Exchange.WebServices"
namespace FolderViewTraversal
{
class Program
{
public static void Main()
{
Exchange.ExchangeService oService;
Dictionary<string, User> oUsers;
oUsers = new Dictionary<string, User>
{
{ "User1", new User("write.to.me1#my.address.com", "Some-Fancy-Password1") },
{ "User2", new User("write.to.me2#my.address.com", "Some-Fancy-Password2") }
};
foreach (KeyValuePair<string, User> Credential in oUsers)
{
File.Delete(String.Format(LOG_FILE_PATH, Credential.Key));
}
foreach (KeyValuePair<string, User> Credential in oUsers)
{
LogFileName = Credential.Key;
Console.WriteLine("Getting message counts for mailbox [{0}]...", LogFileName);
Console.WriteLine();
oService = Service.ConnectToService(Credential.Value);
GetAllFolders(oService, String.Format(LOG_FILE_PATH, Credential.Key));
Console.Clear();
};
Console.WriteLine();
Console.Write("Press any key to exit...");
Console.ReadKey();
}
private static void GetAllFolders(Exchange.ExchangeService Service, string LogFilePath)
{
Exchange.ExtendedPropertyDefinition oIsHidden = default;
List<Exchange.Folder> oFolders = default;
Exchange.FindFoldersResults oResults = default;
bool lHasMore = false;
Exchange.Folder oChild = default;
Exchange.FolderView oView = default;
short nPageSize = 0;
short nOffSet = 0;
List<string> oPaths = default;
List<string> oPath = default;
oIsHidden = new Exchange.ExtendedPropertyDefinition(0x10f4, Exchange.MapiPropertyType.Boolean);
nPageSize = 1000;
oFolders = new List<Exchange.Folder>();
lHasMore = true;
nOffSet = 0;
while (lHasMore)
{
oView = new Exchange.FolderView(nPageSize, nOffSet, Exchange.OffsetBasePoint.Beginning)
{
PropertySet = new Exchange.PropertySet(Exchange.BasePropertySet.IdOnly)
};
oView.PropertySet.Add(oIsHidden);
oView.PropertySet.Add(Exchange.FolderSchema.ParentFolderId);
oView.PropertySet.Add(Exchange.FolderSchema.DisplayName);
oView.PropertySet.Add(Exchange.FolderSchema.FolderClass);
oView.PropertySet.Add(Exchange.FolderSchema.TotalCount);
oView.Traversal = Exchange.FolderTraversal.Deep;
oResults = Service.FindFolders(Exchange.WellKnownFolderName.MsgFolderRoot, oView);
oFolders.AddRange(oResults.Folders);
lHasMore = oResults.MoreAvailable;
if (lHasMore)
{
nOffSet += nPageSize;
}
}
oFolders.RemoveAll(Folder => (bool)Folder.ExtendedProperties[0].Value == true);
oFolders.RemoveAll(Folder => Folder.FolderClass != "IPF.Note");
oPaths = new List<string>();
oFolders.ForEach(Folder =>
{
oChild = Folder;
oPath = new List<string>();
do
{
oPath.Add(oChild.DisplayName);
oChild = oFolders.SingleOrDefault(Parent => Parent.Id.UniqueId == oChild.ParentFolderId.UniqueId);
} while (oChild != null);
oPath.Reverse();
oPaths.Add(String.Format("{0}{1}{2}", String.Join(DELIMITER, oPath), '\t', Folder.TotalCount));
});
oPaths.RemoveAll(Path => Path.StartsWith("Sync Issues"));
File.WriteAllText(LogFilePath, String.Join(Environment.NewLine, oPaths));
}
private static string LogFileName;
private const string LOG_FILE_PATH = "D:\\Emails\\Remote{0}.txt";
private const string DELIMITER = "\\";
}
internal class Service
{
public static Exchange.ExchangeService ConnectToService(User User)
{
return Service.ConnectToService(User, null);
}
public static Exchange.ExchangeService ConnectToService(User User, Exchange.ITraceListener Listener)
{
Exchange.ExchangeService oService = default;
oService = new Exchange.ExchangeService(Exchange.ExchangeVersion.Exchange2013_SP1)
{
Credentials = new NetworkCredential(User.EmailAddress, User.Password)
};
oService.AutodiscoverUrl(User.EmailAddress, RedirectionUrlValidationCallback);
if (Listener != null)
{
oService.TraceListener = Listener;
oService.TraceEnabled = true;
oService.TraceFlags = Exchange.TraceFlags.All;
}
return oService;
}
private static bool RedirectionUrlValidationCallback(string RedirectionUrl)
{
var _with1 = new Uri(RedirectionUrl);
return _with1.Scheme.ToLower() == "https";
}
}
internal class User
{
public string EmailAddress { get; }
public SecureString Password { get; }
public User(string EmailAddress)
{
this.EmailAddress = EmailAddress;
this.Password = new SecureString();
}
public User(string EmailAddress, string Password)
{
this.EmailAddress = EmailAddress;
this.Password = new SecureString();
foreach(char Chr in Password) { this.Password.AppendChar(Chr); };
this.Password.MakeReadOnly();
}
public static User GetUser()
{
Console.Write("Enter email address: ");
string sEmailAddress = Console.ReadLine();
Console.Write("Enter password: ");
User functionReturnValue = new User(sEmailAddress);
while (true)
{
ConsoleKeyInfo oUserInput = Console.ReadKey(true);
if (oUserInput.Key == ConsoleKey.Enter)
{
break; // TODO: might not be correct. Was : Exit While
}
else if (oUserInput.Key == ConsoleKey.Escape)
{
functionReturnValue.Password.Clear();
}
else if (oUserInput.Key == ConsoleKey.Backspace)
{
if (functionReturnValue.Password.Length != 0)
{
functionReturnValue.Password.RemoveAt(functionReturnValue.Password.Length - 1);
}
}
else
{
functionReturnValue.Password.AppendChar(oUserInput.KeyChar);
Console.Write("*");
}
}
if (functionReturnValue.Password.Length == 0)
{
functionReturnValue = null;
}
else
{
functionReturnValue.Password.MakeReadOnly();
Console.WriteLine();
}
return functionReturnValue;
}
}
internal class TraceListener : Exchange.ITraceListener
{
public void Trace(string TraceType, string TraceMessage)
{
File.AppendAllText(String.Format("{0}.txt", Path.Combine("D:\\Emails\\TraceOutput", Guid.NewGuid().ToString("D"))), TraceMessage);
}
}
}

Categories