Я думал, что принятый ответ будет правильным, основываясь на том, что я читал в smarthelp для метода Except: «Производит заданное различие двух последовательностей, используя сопоставитель равенства по умолчанию для сравнения значений». Но я обнаружил, что это не очень хороший ответ.
Рассмотрим этот код:
Словарь & lt; string, List & lt; string & gt; & gt; oldDict = новый словарь & lt; string, List & lt; string & gt; & gt; () {{"001A", новый список & lt; string & gt; {"John", "Doe"}}, {"002B", новый List & lt; string & gt; {«Франк», «Abignale»}}, {"003C", новый List & lt; string & gt; {«Doe», «Jane»}}}; Словарь & lt; string, List & lt; string & gt; & gt; & gt; newDict = новый словарь & lt; string, List & lt; string & gt; & gt; () {{"001A", новый список & lt; string & gt; {"John", "Doe"}}, {"002B", новый List & lt; string & gt; {«Франк», «Abignale»}}, {"003C", новый List & lt; string & gt; {«Doe», «Jane»}}}; bool equal = oldDict.Count.Equals (newDict.Count) & amp; & amp; & amp; ! OldDict.Except (newDict) .Any (); Console.WriteLine (string.Format ("oldDict {0} newDict", равно? "Равно": "не равно")); equal = oldDict.SequenceEqual (newDict); Console.WriteLine (string.Format ("oldDict {0} newDict", равно? "Равно": "не равно")); Console.WriteLine (string.Format ("[{0}]", string.Join (",", oldDict.Except (newDict) .Select (k = & gt; string.Format ("{0} = [{1} ] ", k.Key, string.Join (", ", k.Value))))));
Это приводит к следующему:
oldDict не соответствует newDict oldDict не равен newDict [001A = [John, Doe], 002B = [Frank , Abignale], 003C = [Doe, Jane]]
Как вы можете видеть, оба «oldDict» и «newDict» настроены точно так же. И ни предлагаемое решение, ни призыв к SequenceEqual не работают должным образом. Интересно, является ли это результатом Исключения, используя ленивую загрузку или способ, которым сравнитель устанавливает для Словаря. (Хотя, глядя на структуру и пояснения, предположим, что это должно быть.)
Вот решение, которое я придумал. Обратите внимание, что правило, которое я использовал, выглядит следующим образом: два словаря равны, если оба содержат одинаковые ключи и значения для каждого совпадения ключей. Оба ключа и значения должны быть в одном и том же порядке. И мое решение может быть не самым эффективным, так как оно полагается на итерацию через весь набор ключей.
private static bool DictionaryEqual (Dictionary & lt; string, List & lt; string & gt; gt; olddict, Dictionary & lt; string, List & lt; string & gt ;, newDict) {// Простая проверка, являются ли значениями одинаковые ? if (! oldDict.Count.Equals (newDict.Count)) возвращает false; // Проверяем ключи, если (! OldDict.Keys.SequenceEqual (newDict.Keys)) возвращает false; // Проверяем значения для каждого ключа foreach (строковый ключ в oldDict.Keys), если (! OldDict [key] .SequenceEqual (newDict [key])) возвращает false; return true; }
Также посмотрите, как изменится результат, если: порядок клавиш не совпадает. (возвращает false)
newDict = новый словарь & lt; string, List & lt; string & gt; () {{"001A", новый List & lt; string & gt; {"John", "Doe"}}, {"003C", новый List & lt; string & gt; {«Doe», «Jane»}}, {"002B", новый List & lt; string & gt; {«Фрэнк», «Abignale»}}};
и совпадения с порядковым номером, но значение не соответствует (возвращает false)
newDict = новый словарь & lt; string, List & lt; string & gt; & gt; () {{"001A", новый список & lt; string & gt; {"John", "Doe"}}, {"002B", новый List & lt; string & gt; {«Франк», «Abignale»}}, {"003C", новый List & lt; string & gt; {"Джейн Доу"}}};
Если порядок последовательности не имеет значения, функция может быть изменена следующим образом, но, скорее всего, будет производительный удар.
private static bool DictionaryEqual_NoSort ( Словарь & lt; string, List & lt; string & gt; gt; oldDict, Dictionary & lt; string, List & lt; string & gt; & gt; newDict) {// Простая проверка, совпадают ли подсчеты? if (! oldDict.Count.Equals (newDict.Count)) возвращает false; // перебираем все ключи в oldDict и // проверяем, существует ли ключ в newDict foreach (строковый ключ в oldDict.Keys) {if (newDict.Keys.Contains (key)) {// повторять каждое значение для текущий ключ в oldDict и // проверить, существует ли он для текущего ключа в newDict foreach (строковое значение в olddict [key]), если (! newDict [key] .Contains (value)) возвращает false; } else {return false; }} return true; }
Проверьте, не использует ли DictionaryEqual_NoSort следующее для newDict (DictionaryEquals_NoSort возвращает true):
newDict = новый словарь & lt; string, List & lt; string & gt; & gt; & gt; & gt; ; () {{"001A", новый List & lt; string & gt; {"John", "Doe"}}, {"003C", новый List & lt; string & gt; {"Jane", "Doe"}}, {"002B", новый List & lt; string & gt; {«Фрэнк», «Abignale»}}};
Единственными двумя решениями, которые я видел для этой проблемы, являются:
Радует мою функцию Get-WmiCustom здесь http://blogs.msdn.com/b/dmuscett/archive/2009/05/27/get_2d00_wmicustom.aspx полезен.
Я модифицировал Get-WmiCustom Daniel Muscetta для поддержки передачи учетных данных.
Я знаю, что этот пост немного стар, надеюсь, это помогает кому-то другому.
# Define modified custom get-wmiobject for timeout with credential from http://blogs.msdn.com/b/dmuscett/archive/2009/05/27/get_2d00_wmicustom.aspx
Function Get-WmiCustom([string]$Class,[string]$ComputerName,[string]$Namespace = "root\cimv2",[int]$Timeout=15, [pscredential]$Credential)
{
$ConnectionOptions = new-object System.Management.ConnectionOptions
$EnumerationOptions = new-object System.Management.EnumerationOptions
if($Credential){
$ConnectionOptions.Username = $Credential.UserName;
$ConnectionOptions.SecurePassword = $Credential.Password;
}
$timeoutseconds = new-timespan -seconds $timeout
$EnumerationOptions.set_timeout($timeoutseconds)
$assembledpath = "\\$Computername\$Namespace"
#write-host $assembledpath -foregroundcolor yellow
$Scope = new-object System.Management.ManagementScope $assembledpath, $ConnectionOptions
$Scope.Connect()
$querystring = "SELECT * FROM " + $class
#write-host $querystring
$query = new-object System.Management.ObjectQuery $querystring
$searcher = new-object System.Management.ManagementObjectSearcher
$searcher.set_options($EnumerationOptions)
$searcher.Query = $querystring
$searcher.Scope = $Scope
trap { $_ } $result = $searcher.get()
return $result
}
Вы можете попробовать функцию get-wmiCustom, размещенную здесь здесь . Было бы неплохо, если бы у get-wmiObject был параметр тайм-аута? Возьмем эту вещь .
при создании задания с использованием get-wmiobject назначает это задание переменной, то эту переменную можно передать в get-job для статуса или получения-задания для результатов
$ThisJob = start-job -scriptblock {param ($Target) Get-WmiObject -Class Win32_Service -ComputerName $Target -AsJob} -ArgumentList $server
$Timer = [System.Diagnostics.Stopwatch]::StartNew()
While ($ThisJob | Get-Job | where {$_.State -imatch "Running"}){
If ($Timer.Elapsed.Seconds -ge 5) {
echo "five seconds has passed, removing"
$ThisJob | Get-Job | Remove-Job -Force
} # end if
echo "still running"
Start-Sleep -Seconds 3
} # end while
$Results = $ThisJob | where {$_.State -inotmatch "failed"} | receive-job
$Timer.Stop | out-null
В дополнение к тому, что было сказано, а не пуленепробиваемым решением, но сначала рассмотрите pinging ваших серверов (Test-Connection
), он может ускорить время выполнения, если у вас нет машин-ответчиков.