c# - 使用某些字符串时关闭 TextWriter 异常

标签 c# .net powershell

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

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

PrintADInfo_displayresults.InnerHtml = html_results;

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

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

错误文本

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;
}

最佳答案

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

关于c# - 使用某些字符串时关闭 TextWriter 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46610211/

相关文章:

C# - 使用属性的替代方法

c# - 构建后的 powershell 脚本

c# - 在 SQLite 中使用 SELECT 命令列出附加数据库

c# - 使用嵌套选择 LINQ 循环数组

c# - 延迟时间密码的最佳方法?

c# - InternalsVisibleTo 属性不起作用

c# - 对象没有值(value)

.net - Windows 服务问题 - LocalSystem 帐户无法读取文件

powershell - 使用 Powershell 操纵 IIsWebVirtualDir 上的 IP 限制

powershell - 是否可以使用 Powershell 命令 get-counter 获取性能计数器描述?