【问题标题】:Closed TextWriter Exception When Using Certain Strings使用某些字符串时关闭 TextWriter 异常
【发布时间】:2017-10-07 04:57:07
【问题描述】:

我正在尝试实现一个在网页上显示一些 ActiveDirectory 信息的功能,但是当我尝试显示某些信息(用户的管理器)时,由于某种原因它开始向我抛出以下错误,但它还没有完成那个过去。谁能解释这里发生了什么或提出修复建议?

在 PowerShell 的 using() 块期间处置后,我没有向 StringBuilder 写入任何内容,所以我不知道为什么当 manager_name 字符串调用 GetManager 函数时突然抛出异常,我知道该函数返回基于 VisualStudio 的调试工具的正确值,当它滚动到第 752 行时显示正确的值

PrintADInfo_displayresults.InnerHtml = html_results;

就在处理所有对象并返回函数外部之前。奇怪的是,当将 manager_name 设置为空字符串或只是“test”时,代码会运行良好,但使用 GetUsersManager 函数会导致异常触发。

您将在下面找到相关方法和错误文本。

错误文本

System.ObjectDisposedException:无法写入已关闭的 TextWriter。 在 System.IO.__Error.WriterClosed() 在 System.IO.StreamWriter.Flush(布尔flushStream,布尔 flushEncoder) 在 System.IO.StreamWriter.Flush() 在 System.Management.Automation.Host.TranscriptionOption.Dispose() 在 System.Management.Automation.Host.PSHostUserInterface.StopAllTranscribing() 在 System.Management.Automation.Runspaces.LocalRunspace.DoCloseHelper() 在 System.Management.Automation.Runspaces.LocalRunspace.CloseHelper(布尔 同步呼叫)在 System.Management.Automation.Runspaces.RunspaceBase.CoreClose(布尔 同步呼叫)在 System.Management.Automation.Runspaces.LocalRunspace.Close() 在 System.Management.Automation.Runspaces.LocalRunspace.Dispose(布尔 处置)在 System.Management.Automation.PowerShell.Dispose(布尔 处置)在 System.Management.Automation.PowerShell.Dispose() 在 _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;
}

【问题讨论】:

  • 如果您从string manager_name = GetUsersManager(username); 开始,在using (Powershell...) 块之外,通过提供示例用户名,它是否有效?例如。将username 设置为有效的用户名,看看是否可以从那里调用它?我认为您的问题可能是您实际上在另一个块中有一个 using Powershell 块。
  • 好像已经搞定了,谢谢!将 GetUsersManager() 调用移动到 try() 内部,但仍然在 using() 块之前似乎已经解决了问题。

标签: c# .net powershell


【解决方案1】:

我认为您需要将对 string manager_name = GetUsersManager(username); 的调用移至 using (PowerShell ps = PowerShell.Create()) {} 块之外。你在 using 中有一个 using,我认为你的对象被过早地处理了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-25
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    • 2014-01-02
    • 1970-01-01
    • 2017-11-08
    • 1970-01-01
    相关资源
    最近更新 更多