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