I'm trying to implement a function that displays some ActiveDirectory information onto a webpage, however when I try to display certain information (the user's manager) for some reason it started throwing the below error at me when it hadn't done that in the past. Can anyone explain what's going on here or suggest a fix?
I'm not writing anything to the StringBuilder after disposal during the using() block for the PowerShell, so I have no idea why this is suddenly throwing the exception when the manager_name string is calling the GetManager function, which I know returns the correct value based on VisualStudio's debugging tool showing the proper value when it rolls into line 752
PrintADInfo_displayresults.InnerHtml = html_results;
which is just prior to the disposal of all the objects and return outside the function. What is bizarre is that when setting manager_name to the empty string or just "test", the code will run fine but using the GetUsersManager function will cause the exception to fire.
Below you'll find the methods in question and the error text.
Error Text
System.ObjectDisposedException: Cannot write to a closed TextWriter. at System.IO.__Error.WriterClosed() at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder) at System.IO.StreamWriter.Flush() at System.Management.Automation.Host.TranscriptionOption.Dispose() at System.Management.Automation.Host.PSHostUserInterface.StopAllTranscribing() at System.Management.Automation.Runspaces.LocalRunspace.DoCloseHelper() at System.Management.Automation.Runspaces.LocalRunspace.CloseHelper(Boolean syncCall) at System.Management.Automation.Runspaces.RunspaceBase.CoreClose(Boolean syncCall) at System.Management.Automation.Runspaces.LocalRunspace.Close() at System.Management.Automation.Runspaces.LocalRunspace.Dispose(Boolean disposing) at System.Management.Automation.PowerShell.Dispose(Boolean disposing) at System.Management.Automation.PowerShell.Dispose() at _Default.PrintADInfo(String username) in h:\Visual Studio 2015\WebSites\WebSite2\Default.aspx.cs:line 753
private void PrintADInfo(string username)
{
//Print AD information for given username
AD_PrintADInfoDiv.Attributes["style"] = "display:block"; //Move to the account display
try
{
using (PowerShell ps = PowerShell.Create())
{
var sb = new StringBuilder();
sb.Append("Grabbing AD info for " + username.ToUpper() + " ...");
//Run command Get-ADUser to get user information from AD
//Command Information -> https://technet.microsoft.com/en-us/library/hh852208(v=wps.630).aspx
// Use -Properties to get specific proprties we want, then use Select to ignore some additional ones
ps.AddScript("Get-ADUser -Properties SamAccountName, CN, EmailAddress, Title, Department, Manager, OfficePhone, Mobile, PasswordLastSet, EmployeeID, co, physicalDeliveryOfficeName " + username + " | select SamAccountName, CN, Title, Department, EmailAddress, Manager, OfficePhone, Mobile, PasswordLastSet, EmployeeID, co, physicalDeliveryOfficeName | ConvertTo-Html");
Collection<PSObject> psOutput = ps.Invoke();
//Add user informtion to StringBuilder for output
foreach (PSObject p in psOutput)
{
sb.Append(p.ToString());
}
//Evil regex hacking
//Quotes are doubled to account for C# literals
//https://stackoverflow.com/questions/9289357/javascript-regular-expression-for-dn
string pattern = @"(?:[A-Za-z][\w-]*|\d+(?:\.\d+)*)=(?:#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\""]|\\[,=\+<>#;\\""]|\\[\dA-Fa-f]{2})*|""(?:[^\\""]|\\[,=\+<>#;\\""]|\\[\dA-Fa-f]{2})*"")(?:\+(?:[A-Za-z][\w-]*|\d+(?:\.\d+)*)=(?:#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\""]|\\[,=\+<>#;\\""]|\\[\dA-Fa-f]{2})*|""(?:[^\\""]|\\[,=\+<>#;\\""]|\\[\dA-Fa-f]{2})*""))*(?:,(?:[A-Za-z][\w-]*|\d+(?:\.\d+)*)=(?:#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\""]|\\[,=\+<>#;\\""]|\\[\dA-Fa-f]{2})*|""(?:[^\\""]|\\[,=\+<>#;\\""]|\\[\dA-Fa-f]{2})*"")(?:\+(?:[A-Za-z][\w-]*|\d+(?:\.\d+)*)=(?:#(?:[\dA-Fa-f]{2})+|(?:[^,=\+<>#;\\""]|\\[,=\+<>#;\\""]|\\[\dA-Fa-f]{2})*|""(?:[^\\""]|\\[,=\+<>#;\\""]|\\[\dA-Fa-f]{2})*""))*)*";
Regex rgx = new Regex(pattern);
//Replace the user's manager field that's normally in CN format to NTID
string manager_name = GetUsersManager(username);
//string manager_name = ""; // <-- Making the manager blank runs fine
string html_results = rgx.Replace(sb.ToString(), manager_name);
PrintADInfo_displayresults.InnerHtml = html_results;
return; // <--- Error gets thrown here
}
}
catch (Exception e)
{
PrintADInfo_displayresults.InnerHtml = "Exception caught:" + e;
return;
}
}
private string GetUsersManager(string username)
{
//Returns the NTID of the user's manager, instead of the CN
string manager_name = "";
using (PowerShell ps = PowerShell.Create())
{
ps.AddScript("(Get-ADUser (Get-ADUser " + username + " -Properties manager).manager).samaccountName");
Collection<PSObject> psOutput = ps.Invoke();
foreach (PSObject p in psOutput)
{
manager_name = manager_name + p.ToString();
}
}
return manager_name;
}