Скрипт Powershell завершает цикл ForEach-Object преждевременно. Цикл foreach powershell


foreach - Скрипт Powershell завершает цикл ForEach-Object преждевременно

Поэтому я пишу сценарий, который будет принимать все данные, хранящиеся в 238 электронных таблицах, и скопировать их в главный лист, а также 9 листов отчета высокого уровня. Я действительно не знаю, почему, но после определенного документа сценарий заканчивается преждевременно, без каких-либо ошибок. Это очень странно. Я отправлю анонимный код ниже, поэтому, возможно, кто-то может помочь мне найти ошибку в моих путях здесь.

Насколько я могу судить, документ, который он выйдет после, в порядке. Я не вижу в нем каких-либо ошибок данных, и информация успешно копируется в главный документ, прежде чем powershell просто вызывает его завершение на скрипте.

Я попытался изменить размер набора данных, ограничив только папку, содержащую файл проблемы. Он по-прежнему заканчивается после того же файла без вывода ошибок. Я не могу загрузить файл из-за политики компании, но я действительно ничего не вижу в данных о том, что один файл по сравнению с любым другим файлом такого же характера.

Кроме того, извиняюсь заранее за дрянной код. Я не разработчик и переучиваю powershell, так как это единственный инструмент, доступный мне сейчас.

$StartTime = Get-Date -Format g Write-Host $StartTime pushd "Z:\Shared Documents\IO" $TrackTemplate = "C:\Users\USERNAME\Desktop\IODATA\MasterTemplate.xlsx" # Initialize the Master Spreadsheet $xlMaster = New-Object -ComObject Excel.Application $xlMaster.Visible = $False $xlMaster.DisplayAlerts = $False $MasterFilePath = "C:\Users\USERNAME\Desktop\IODATA\Master.xlsx" Copy-Item $TrackTemplate $MasterFilePath $wbMaster = $xlMaster.Workbooks.Open($MasterFilePath) $wsMaster = $wbMaster.Worksheets.Item(2) $wsMaster.Unprotect("PASSWORD") $wsMasterRow = 3 # Initialize L4 Document Object $xlL4 = New-Object -ComObject Excel.Application $xlL4.Visible = $False $xlL4.DisplayAlerts = $False # Initialize object for input documents $xlInput = New-Object -ComObject Excel.Application $xlInput.Visible = $False $xlInput.DisplayAlerts = $False # Arrays used to create folder path names $ArrayRoot = @("FOLDER1","FOLDER2","FOLDER3","FOLDER4","FOLDER5","FOLDER6","FOLDER7","FOLDER8","FOLDER9") $ArrayShort = @("SUB1","SUB2","SUB3","SUB4","SUB5","SUB6","SUB7","SUB8","SUB9") # $counter is used to iterate inside the loop over the short name array. $counter = 0 $FileNumber = 0 $TotalFiles = 238 $ArrayRoot | ForEach-Object { $FilePathL4 = "C:\Users\USERNAME\Desktop\IODATA\ROLLUP\" + $ArrayShort[$counter] + "_DOC_ROLLUP.xlsx" Copy-Item $TrackTemplate $FilePathL4 $wbL4 = $xlL4.Workbooks.Open($FilePathL4) $wsL4 = $wbL4.Worksheets.Item(2) $wsL4.Unprotect("PASSWORD") $wsL4Row = 3 If ($ArrayShort[$counter] -eq "SUB7") {$FilePath = "Z:\Shared Documents\IO\" + $_ + "\" + $ArrayShort[$counter] + " - DOC v2\"} Else {$FilePath = "Z:\Shared Documents\IO\" + $_ + "\!" + $ArrayShort[$counter] + " - DOC v2\"} Get-ChildItem -Path $FilePath | ForEach-Object { If ($_.Name -eq "SPECIFIC_DOC.xlsx") {Continue} $FileNumber += 1 Write-Host "$FileNumber / $TotalFiles $_" $wbInput = $xlInput.Workbooks.Open($_.FullName) $wsInput = $wbInput.Worksheets.Item(2) $wsInputLastRow = 0 #Find the last row in the Input document For ($i = 3; $i -le 10000; $i++) { If ([string]::IsNullOrEmpty($wsInput.Cells.Item($i,1).Value2)) { $wsInputLastRow = $i - 1 Break } Else { Continue } } [void]$wsInput.Range("A3:AC$wsInputLastRow").Copy() Start-Sleep -Seconds 1 [void]$wsMaster.Range("A$wsMasterRow").PasteSpecial(-4163) Start-Sleep -Seconds 1 $wsMasterRow += $wsInputLastRow - 2 [void]$wsL4.Range("A$wsL4Row").PasteSpecial(-4163) Start-Sleep -Seconds 1 $wsL4Row += $wsInputLastRow - 2 $wbInput.Close() $wbMaster.Save() } $counter += 1 $wsL4.Protect("PASSWORD") $wbL4.Save() $wbL4.Close() } $wsMaster.Protect("PASSWORD") $wbMaster.Save() $wbMaster.Close() $xlMaster.Quit() $EndTime = Get-Date -Format g $TimeTotal = New-Timespan -Start $StartTime -End $EndTime Write-Host $TimeTotal

qaru.site

foreach - PowerShell: как объединить результаты в цикл ForEach

Я хочу сгруппировать секцию во втором ForEach. Как сделать эквивалент $ result = $ result +...?

$clusters = "cluster1", "cluster2" ForEach ($item in $clusters) { $clusterNodes = Get-ClusterNode -Cluster $item ; $clusterNodes|select Cluster,NodeName, State|Sort-Object NodeName|Format-Table -Wrap -AutoSize; ForEach ($vm in $clusterNodes) { $result = Get-VM -ComputerName $vm.Name |select VMName, ComputerName, PrimaryOperationalStatus, State, Path, CreationTime, Uptime, IntegrationServicesVersion,ProcessorCount, DynamicMemoryEnabled, MemoryMinimum,MemoryMaximum |Sort-Object VMName|Format-Table -Wrap -AutoSize; $result } }

Например, в моем выпуске каждый раздел имеет свои собственные результаты. Я хочу совместить результаты, сортировать их, подсчитывать и отображать их как один результат, а не в x раз число $ кластеров.

Cluster NodeName State ------- -------- ----- CLUSTER1 SERVER1 Up CLUSTER1 SERVER2 Up CLUSTER1 SERVER3 Up CLUSTER1 SERVER4 Up VMName ComputerName PrimaryOperationalStatus State Path CreationTime Uptime IntegrationServicesVersion ProcessorCount Dynam ------ ------------ ------------------------ ----- ---- ------------ ------ -------------------------- -------------- ----- XYZ080 SERVER1 Ok Running C:\ClusterStorage\Volume1\XYZ080 11/15/2013 2:16:39 PM 3.13:46:52 6.2.9200.16384 4 True XYZ019 SERVER1 Ok Running C:\ClusterStorage\Volume1\XYZ019 11/6/2013 10:24:58 AM 68.07:02:32 6.2.9200.20655 2 False XYZ021A SERVER1 Ok Running C:\ClusterStorage\Volume1\ XYZ021A 11/1/2013 10:33:20 AM 68.07:02:01 6.2.9200.20655 6 False VMName ComputerName PrimaryOperationalStatus State Path CreationTime Uptime IntegrationServicesVersion ProcessorCount Dyna ------ ------------ ------------------------ ----- ---- ------------ ------ -------------------------- -------------- ---- XYZ078 SERVER2 Ok Running C:\ClusterStorage\Volume1\XYZ078 10/30/2013 11:20:05 AM 61.04:32:55 6.2.9200.20655 4 Fals NXYZ001 SERVER2 Ok Running C:\ClusterStorage\volume1\NXYZ001 11/7/2013 8:54:29 AM 1.01:55:10 6.2.9200.16384 2 Fals ABC051 SERVER2 Ok Running C:\ClusterStorage\volume1\ABC051 11/1/2013 2:52:24 PM 1.06:57:57 6.2.9200.20655 4 Fals

Я хочу, чтобы он выглядел следующим образом:

Cluster NodeName State ------- -------- ----- CLUSTER1 SERVER1 Up CLUSTER1 SERVER2 Up CLUSTER1 SERVER3 Up CLUSTER1 SERVER4 Up VMName ComputerName PrimaryOperationalStatus State Path CreationTime Uptime IntegrationServicesVersion ProcessorCount Dynam ------ ------------ ------------------------ ----- ---- ------------ ------ -------------------------- -------------- ----- XYZ080 SERVER1 Ok Running C:\ClusterStorage\Volume1\XYZ080 11/15/2013 2:16:39 PM 3.13:46:52 6.2.9200.16384 4 True XYZ019 SERVER1 Ok Running C:\ClusterStorage\Volume1\XYZ019 11/6/2013 10:24:58 AM 68.07:02:32 6.2.9200.20655 2 False XYZ021A SERVER1 Ok Running C:\ClusterStorage\Volume1\ XYZ021A 11/1/2013 10:33:20 AM 68.07:02:01 6.2.9200.20655 6 False XYZ078 SERVER2 Ok Running C:\ClusterStorage\Volume1\XYZ078 10/30/2013 11:20:05 AM 61.04:32:55 6.2.9200.20655 4 False NXYZ001 SERVER2 Ok Running C:\ClusterStorage\volume1\NXYZ001 11/7/2013 8:54:29 AM 1.01:55:10 6.2.9200.16384 2 False ABC051 SERVER2 Ok Running C:\ClusterStorage\volume1\ABC051 11/1/2013 2:52:24 PM 1.06:57:57 6.2.9200.20655 4 Fals задан Paul S. 28 янв. '14 в 21:22 источник поделиться

qaru.site

scripting - PowerShell превращает инструкцию if else в цикл Foreach

Мне нужно избавиться от некоторых пользователей, которые больше не существуют в AD, но все еще установлены в приложении.

У меня есть скрипт, который предоставляет список пользователей и назначает их переменной. На данный момент я хочу список пользователей, которые не являются безусловными. Это работает для одного пользователя:

#One user in an Application $Users = $location.Users.FindAll() | where {$_.username -like "*johnsmith*"} | select username Username -------- JohnSmith #See if user exists in AD (Match Username with AD UserPrincipalName) $users = $repository.Users.FindAll() |where {$_.username -like "*johnp*"} | select username $users2 = Get-ADUser -Filter "UserPrincipalName -eq '$($users.username)'" -Properties LastLogonDate if (!$users2 ) { Write-Host "$users doesnt exist" } else { Write-Host "$users does exist" } > @{Username=JohnSmith} doesnt exist

Проблема, которую я получаю, заключается в кормлении этого цикла foreach для нескольких пользователей в переменной. Как я могу поместить это для просмотра объекта для каждого пользователя и вывода тех, которые не существуют?

#List of all users in Appication $Users = $location.Users.FindAll() | select username Username -------- JohnSmith JohnSmith2 JohnSmith3

Пробовал это, но не работает, показывает, что все пользователи существуют, хотя JohnSmith не существует, как указано выше:

$users = $location.Users.FindAll() |select username $users2 = Get-ADUser -Filter "UserPrincipalName -eq '$($users.username)'" foreach ($users2 in $users){ if (!$users2 ) { write-host "$users2 doesnt exist" } else { write-host "$users2 does exist" } } PS C:\> @{Username=JohnSmith} does exist @{Username=JohnSmith2} does exist @{Username=JohnSmith3} does exist задан Ralluhb 12 июля '16 в 11:37 источник поделиться

qaru.site

foreach - Части цикла ForEach в PowerShell пропущены?

У меня есть сценарий Powershell, который, кажется, работает нормально, за исключением того факта, что часть моего вывода пропущена, и я не могу понять, почему. Вот сценарий запуска:

#Server list provided for the script. $ServerList = Get-Content $env:USERPROFILE\Documents\Servers.txt #Counter for first If loop. $Counter = 0 #Counter for second If loop. $Counter2 = 0 #ForEach loop going through the server list, picking out OS, Drives, and CPU info and dumping it into an array. ForEach($Server in ($ServerList)) { "Collecting server information on $Server, please wait..." "Collecting Operating System..." $OS = gwmi Win32_OperatingSystem -ComputerName $Server | select Caption "Collecting Storage..." $Drives = gwmi Win32_LogicalDisk -ComputerName $Server | Format-Table DeviceId, @{n="Size in GB";e={[math]::Round($_.Size/1GB,2)}},@{n="Free Space in GB";e={[math]::Round($_.FreeSpace/1GB,2)}} "Collecting CPU..." $CPU = gwmi Win32_Processor -ComputerName $Server | select Name, Manufacturer $ServerInfo = @($OS,$Drives,$CPU) #$ServerInfo #Do loop that posts the info stored in the array and ups the first counter. Runs while counter is equal to 0. Do { "All done. Here all the info we got on $($Server):" $ServerInfo $Counter++ }While ($Counter -eq 0) #If loop that checks if the Counter has been bumped by the Do loop. Sets Counter to 0 and increases Counter2 by 1. If ($Counter -eq 1) { $Counter = 0 $Counter2++ } #If loop that checks if Coutner2 is equal to a certain number. This is the hard stop to the loop. If ($Counter2 -eq 2) { "Max number of runs met. Stopping." break } }

Я знаю, что скрипт запутан и требует большой работы, но по какой-то причине после второго прохода цикла ForEach переменная ОС полностью пропущена и не отображается в консоли. После первого запуска он полностью исключает его и просто публикует информацию о драйвере и процессоре. Я думал, что это было что-то странное с циклами Do и If, поэтому я прокомментировал их, чтобы проверить, но это тот же результат.

Я пробовал отправлять переменные OS, Drives и CPU по мере того, как цикл запускается, чтобы убедиться, что он фактически сохраняет что-то в переменной, и это так, и я также вызываю переменные сами после того, как цикл разбивается, чтобы увидеть, что-то странное происходит в цикле/скрипте. Я узнал, что вызов переменной ОС и массива ServerInfo после завершения цикла вызывает его вывод с информацией о ОС.

Любая идея, почему это так?

qaru.site

arrays - PowerShell - не создает Jagged Array внутри цикла forEach

Вы видите, как PowerShell разворачивает массивы. Переменная сконструирована так: большой массив. Однако PowerShell при их отображении помещает каждый элемент в свою собственную строку. Если вы этого не хотите, и особенно если вы собираетесь использовать Эти данные будут использоваться для фильтрации компьютеров, которые не находятся в сети, тогда вы должны использовать объекты PowerShell.

if ( $entry -ne $strKioskIpAddress ){ $objPing += New-Object -TypeName psobject -Property @{ Entry = $entry Result = Test-Connection -ComputerName $entry -Count 1 -BufferSize 16 -Quiet -ErrorAction SilentlyContinue } }

Вместо этого я продолжу и использую другой foreach который более дружелюбен к трубопроводу. Таким образом, вы можете использовать другие командлеты, такие как Export-CSV если вам нужен этот вывод в других местах. Также ложь PetSerAl говорит

[Y] ou не следует использовать оператор добавления массива и добавлять элементы один за другим. Он [будет] создавать [новый] массив (поскольку массивы не изменяются по размеру) и копировать элементы из [старого] на каждую операцию.

$tmpIpAddress | Where-Object{$_ -ne $strKioskIpAddress} | ForEach-Object{ New-Object -TypeName psobject -Property @{ Entry = $_ Result = Test-Connection -ComputerName $_ -Count 1 -BufferSize 16 -Quiet -ErrorAction SilentlyContinue } } | Export-CSV -NoTypeInformation $path

if теперь избыточно, что мы переместили эту логику в Where-Object так как вы использовали ее, все равно отфильтровывайте определенные записи. Это то, что " Where-Object хорошо.

Вышеприведенный код хорош для PowerShell 2.0. Если у вас есть 3.0 или более поздняя [pscutomobject] используйте [pscutomobject] и [ordered]

$tmpIpAddress | Where-Object{$_ -ne $strKioskIpAddress} | ForEach-Object{ [psobject][ordered] @{ Entry = $_ Result = Test-Connection -ComputerName $_ -Count 1 -BufferSize 16 -Quiet -ErrorAction SilentlyContinue } } | Export-CSV -NoTypeInformation $path

qaru.site

powershell - PowerShell - цикл foreach каждые 1 минуту

У меня есть сценарий, который запрашивает AD, и если он найдет пользователей, созданных в течение 24 часов, он отправит их по электронной почте. У меня эта часть работает нормально, но я не могу понять, почему 1) она работает по строкам в окнах PowerShell, но не работает с тем же кодом, что и файл.ps1; и 2) почему поле $ name в $ mailBody вообще не отображается. Он отображает $ username, но не $ name. Я отправлю сообщение об ошибке ниже кода.

clear Import-Module ActiveDirectory $secpasswd = ConvertTo-SecureString "xxxx" -AsPlainText -Force $mycreds = New-Object System.Management.Automation.PSCredential ("[email protected]", $secpasswd) $PSEmailServer = "[email protected]" $SMTPPort = 587 $SMTPUsername = "[email protected]" $MailFrom = "[email protected]" $MailSubject = "Your user account has been created" #Pull users created within last 24 hours $when = ((get-date).AddDays(-2)).addMinutes(-0) #past 24 hours from current time $when $users = Get-ADUser -Filter {whenCreated -ge $when} -Properties whenCreated,mail,givenname,surname,SAMAccountName,info | Select-Object whenCreated,mail,givenname,surname,SAMAccountName,info | where info -ne true Foreach ($user in $users) { $users $name = $user.name $emailTo = $user.mail $username = $user.SAMAccountName $MailBody =" <p>Dear $name, Your CDAT Account has been created. <br><br> Your Username is $username <br><br> Please contact CDAT support for further assistance. <br><br> CDAT Support Team <br><br> This email was auto-generated. Please do not reply. If you need assistance, please contact CDAT Support. <br><br> Confidentiality Notice: This email message, including any attachments, is for the sole use of the intended recipient(s), and may contain confidential and privileged information. Any unauthorized review, use, disclosure, or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message.<br><br> </P>" Send-MailMessage -From $MailFrom -To $emailTo -Subject $MailSubject -Body $MailBody -BodyAsHtml -Port $SMTPPort -UseSsl -Credential $mycreds Set-AdUser -identity $username –replace @{info="true"} } "PS C:\scripts> .\EmailUsers24HoursAfterAccountCreation.ps1 At C:\scripts\EmailUsers24HoursAfterAccountCreation.ps1:33 char:36 + Set-AdUser -identity $username â€"replace @{info=â€trueâ€} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The string is missing the terminator: ". At C:\scripts\EmailUsers24HoursAfterAccountCreation.ps1:18 char:2 + { + ~ Missing closing '}' in statement block or type definition. + CategoryInfo : ParserError: (:) [], ParseException + FullyQualifiedErrorId : TerminatorExpectedAtEndOfString" источник поделиться

qaru.site

powershell - Последний цикл foreach в PowerShell выходит из строя, но предыдущий цикл работает отлично

Вы тратите время на чтение, изменение и удаление файлов. Я бы переписал его примерно так:

$iScript = "GetADGroups" $StrPath = "C:\Temp\$iScript" $StrFile = "$StrPath\$iScript.txt" #-Force to also create missing parents-folders if(!(Test-Path $StrPath)){New-Item -ItemType Directory -Path $StrPath -Force} $OUs = "OU=Users,OU=OC,DC=domain,DC=com", "OU=Users,OU=AMC,DC=domain,DC=com", "OU=Users,OU=FI,DC=domain,DC=com" $Groups = $OUs | Foreach-Object { Get-ADGroup -Filter 'GroupCategory -eq "Security"' -SearchBase $_ } #Save groupnames to file if you need them $Groups | Select-Object -ExpandProperty Name | Set-Content -Path $StrFile foreach($group in $Groups){ Write-Host $group $members = @(Get-ADGroupMember -Identity $group) #If group contains members if($members.Count -gt 0) { #Create list of members $members | Select-Object -ExpandProperty sAMAccountName | Set-Content -Path "$StrPath\$group.Members.txt" #Create list with new IDs (is the other list necessary?) $members | Get-ADUser -Properties MailNickName | Select-Object -ExpandProperty MailNickName | Set-Content -Path "$StrPath\$group.NID.txt" } }

И желательно объединить элементы и NID-список в один файл csv, где имя пользователя и mailnickname связаны одной строкой. Пример:

#If group contains members if($members.Count -gt 0) { #Create csv-list of members with current username (samaccountname) and new id (mailnickname) $members | Get-ADUser -Properties MailNickName | Select-Object -Property sAMAccountName, MailNickName | Export-CSV -Path "$StrPath\$group.csv" -NoTypeInformation }

Или сделайте это еще на один шаг и просто получите один CSV файл со всеми членами группы.

$iScript = "GetADGroups" $StrPath = "C:\Temp\$iScript" $StrFile = "$StrPath\$iScript.txt" $OUs = "OU=Users,OU=OC,DC=domain,DC=com", "OU=Users,OU=AMC,DC=domain,DC=com", "OU=Users,OU=FI,DC=domain,DC=com" $Groups = $OUs | Foreach-Object { Get-ADGroup -Filter 'GroupCategory -eq "Security"' -SearchBase $_ } #Save groupnames to file if you need them (if you're migrating empty groups) $Groups | Select-Object -ExpandProperty Name | Set-Content -Path $StrFile $Groups | Foreach-Object { $group = $_ Write-Host $group Get-ADGroupMember -Identity $group | #Getting ADUser object to get missing property Get-ADUser -Properties MailNickName | Select-Object -Property @{n="Group";e={$group}}, sAMAccountName, MailNickName } | Export-CSV -Path "$StrPath\GroupMembers.csv" -NoTypeInformation

Ваш CSV будет выглядеть так, который можно легко импортировать, сгруппировать и т.д. Позже с помощью Import-CSV при добавлении членов в новые группы:

Group,sAMAccountName,MailNickName Group1,user1,mailnickforuser1 Group2,user1,mailnickforuser1 Group2,user2,mailnickforuser2

qaru.site