Powershell中的多线程问题

时间:2018-10-24 13:46:27

标签: c# multithreading powershell add-type

[edit 10/29/18]-(基于日志记录)似乎parallel.foreach函数没有等待返回值信息

下面是我用来具有多线程Powershell函数的代码。我利用powershell中的add-type函数在Parallel.ForEach的powershell代码中使用c#。我遇到的问题是,有时此功能没有在dag中列出所有服务器,而其他时候却列出。 (它应该始终为每个服务器返回1值)。

我已通过将所有服务器传递到Parallel.ForEach函数之前将它们写入控制台来验证是否已将所有服务器馈入Parallel.ForEach,并且我还验证了它们不会作为ae.InnerExceptions返回。缺少服务器,但是我不知道如何解决它。我找不到关于为什么发生这种情况的任何一致性或模式,并且正在寻找有关解决方法或对此进行故障排除的想法?

Write-host "2. Get-MailboxDatabaseCopyStatus health (copyqueue < 6 and replayqueue < 100 for Ap's 1, 2 and 3) for " $dagName -ForegroundColor Yellow -BackgroundColor Black;
Write-Host "";

$queueLengths = 
@'

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Management.Automation;
    using System.Management.Automation.Runspaces;
    using System.Security;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Threading;
    using System.Collections.Concurrent;
    using System.Diagnostics;
    using System.Security.Principal;    


    namespace MultiThreading
    {
        public class queues
        {
            public string uri = "http://xxxx/powershell";


            public AuthenticationMechanism auth = AuthenticationMechanism.Kerberos;
            //public AuthenticationMechanism auth = AuthenticationMechanism.Negotiate;

            public List<string> get(string dag)
            {
                var response = new ConcurrentBag<List<string>>();
                var exceptions = new ConcurrentQueue<Exception>();

                string[] serversUnsorted = getDagMembers(dag);
                var servers = from s in serversUnsorted orderby s select s;

                try
                {
                    Parallel.ForEach(servers, server =>
                    {
                        response.Add(runPowerShellScriptGetDbCopyStatusHealth(server));
                    });
                }
                catch (AggregateException ae)
                {
                    foreach (var aex in ae.InnerExceptions)
                    {
                        exceptions.Enqueue(aex);
                    }
                }

                List<string> returnValues = new List<string>();

                foreach (var item in response)
                {
                    for (int i = 0; i < item.Count; i++)
                    {
                        returnValues.Add(item[i].ToString());
                    }
                }
                returnValues.Sort();

                return returnValues;
            }

            private List<string> runPowerShellScriptGetDbCopyStatusHealth(object server)
            {
                Collection<PSObject> psobjs = new Collection<PSObject>();
                List<string> returnValue = new List<string>();
                string serverName = server.ToString();


                WSManConnectionInfo wmc = new WSManConnectionInfo(new Uri(uri));

                wmc.AuthenticationMechanism = auth;
                wmc.ShellUri = "http://schemas.microsoft.com/powershell/Microsoft.Exchange";

                using (Runspace runspace = RunspaceFactory.CreateRunspace(wmc))
                {
                    PowerShell powershell = PowerShell.Create();

                    if (runspace.RunspaceStateInfo.State == RunspaceState.Opened)
                    {
                        // do nothing
                    }
                    else
                    {
                        runspace.Open();
                        powershell.Runspace = runspace;
                    }

                    try
                    {
                        PSCommand command = new PSCommand();                    
                        command.AddScript("Get-MailboxDatabase -Server " + serverName);// + " | Where {$_.Recovery -eq $False}  | Sort Name | Get-MailboxDatabaseCopyStatus");
                        powershell.Commands = command;
                        psobjs = powershell.Invoke();                    

                        if (powershell.HadErrors == true)
                        {
                            returnValue.Add(serverName +  " failed - " + powershell.Streams.Error[0].ToString());
                        }

                        List<string> nonRecoveryDbs = parseDatabaseResults(psobjs);

                        returnValue = getCopyQueueLength(serverName, nonRecoveryDbs);
                    }
                    catch (Exception ex)
                    {
                        string fail = ex.Message;
                    }
                }

                return returnValue;
            }

            private List<string> parseDatabaseResults(Collection<PSObject> objs)
            {
                List<string> returnValue = new List<string>();

                foreach (PSObject obj in objs)
                {
                    if (obj != null)
                    {
                        object o = obj.Members["Recovery"].Value;

                        string asdf = o.ToString();
                        if (o.ToString().ToLower() == "false")
                        {
                            returnValue.Add(obj.Members["Identity"].Value.ToString());
                        }
                    }
                }

                return returnValue;
            }

            private List<string> getCopyQueueLength(string server, List<string> databases)
            {
                Collection<PSObject> psobjs = new Collection<PSObject>();
                List<string> returnValue = new List<string>();


                WSManConnectionInfo wmc = new WSManConnectionInfo(new Uri(uri));

                wmc.AuthenticationMechanism = auth;
                wmc.ShellUri = "http://schemas.microsoft.com/powershell/Microsoft.Exchange";

                using (Runspace runspace = RunspaceFactory.CreateRunspace(wmc))
                {
                    PowerShell powershell = PowerShell.Create();

                    if (runspace.RunspaceStateInfo.State == RunspaceState.Opened)
                    {
                        // do nothing
                    }
                    else
                    {
                        runspace.Open();
                        powershell.Runspace = runspace;
                    }

                    foreach (string database in databases)
                    {
                        try
                        {
                            PSCommand command = new PSCommand();
                            command.AddScript("Get-MailboxDatabaseCopyStatus -verbose -Identity " + database);
                            powershell.Commands = command;
                            psobjs = powershell.Invoke();

                            if (powershell.HadErrors == true)
                            {
                                returnValue.Add(server + " - " + database + " failed - " + powershell.Streams.Error[0].ToString());
                            }

                            foreach (PSObject psobj in psobjs)
                            {
                                if (psobj != null)
                                {
                                    object ap = psobj.Members["ActivationPreference"].Value;
                                    object queueLength = psobj.Members["CopyQueueLength"].Value;
                                    object replayQueueLength = psobj.Members["ReplayQueueLength"].Value;

                                    if (ap.ToString() == "4")
                                    {
                                        if (Convert.ToInt32(queueLength) > 5)
                                        {
                                            returnValue.Add(server + " - " + database + " - queue count: " + queueLength);
                                        }
                                    }
                                    else
                                    {
                                        if ((Convert.ToInt32(queueLength) > 5) || (Convert.ToInt32(replayQueueLength) > 100))
                                        {
                                            returnValue.Add(server + " - " + database + " - queue count: " + queueLength + " - replay queue count: " + replayQueueLength);
                                        }
                                    }                                   
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            string fail = ex.Message;
                            if (fail.Contains("xmlsoap"))
                            {
                                returnValue.Add(server + " - xmlsoap failure");
                            }
                            else
                            {
                                returnValue.Add(server + " - " + fail);
                            }
                        }
                    }
                }

                if (returnValue.Count == 0)
                {
                    returnValue.Add(server + ", queue count less than 6 and replay count less than 100");
                }

                return returnValue;
            }

            private string[] getDagMembers(string dagName)
            {
                Collection<PSObject> psobjs = new Collection<PSObject>();
                string result = "";
                string[] servers = null;


                WSManConnectionInfo wmc = new WSManConnectionInfo(new Uri(uri));
                wmc.AuthenticationMechanism = auth;

                wmc.ShellUri = "http://schemas.microsoft.com/powershell/Microsoft.Exchange";               

                using (Runspace runspace = RunspaceFactory.CreateRunspace(wmc))
                {
                    PowerShell powershell = PowerShell.Create();

                    if (runspace.RunspaceStateInfo.State == RunspaceState.Opened)
                    {
                        // do nothing
                    }
                    else
                    {
                        runspace.Open();
                        powershell.Runspace = runspace;
                    }

                    try
                    {
                        PSCommand command = new PSCommand();
                        command.AddScript("Get-DatabaseAvailabilityGroup -Identity " + dagName);
                        powershell.Commands = command;
                        psobjs = powershell.Invoke();

                        if (powershell.HadErrors == true)
                        {
                            result = "Failed - " + powershell.Streams.Error[0].ToString();
                            result = result.Replace("\"", "*");
                        }

                        PSPropertyInfo serversTemp = null;
                        foreach (PSObject psobj in psobjs)
                        {
                            serversTemp = psobj.Properties["servers"];
                        }

                        string s_servers = serversTemp.Value.ToString();
                        servers = s_servers.Split(' ');

                    }
                    catch (Exception ex)
                    {
                        string fail = ex.Message;
                    }
                }            

                return servers;
            }
        }
    }
'@

try
{
    $queueLengthCheck = New-Object MultiThreading.queues;
}
catch
{
    Add-Type -TypeDefinition $queueLengths -ReferencedAssemblies System.Collections, System.ComponentModel, System.Data, System.Drawing, System.Linq, System.Management.Automation, System.Security, System.Threading.Tasks, System.Windows.Forms, System.Threading, System.Collections.Concurrent, System.Security.Principal
    $queueLengthCheck = New-Object MultiThreading.queues;
}

$queues = $queueLengthCheck.get($dagName);
Write-Host "Queues server count -" $queues.Count;
foreach($queue in $queues)
{
    if ($queue -match "queue count less than 6 and replay count less than 100")
    {
        Write-Host "     " $queue -ForegroundColor Green;
    }
    else
    {
        Write-Host "     " $queue -ForegroundColor Red;
    }

}

0 个答案:

没有答案