Pull to refresh

Comments 13

Знаете, можно было бы написать проще и универсальнее. Вы заново придумали функционал стандартных командлетов.

$error.Clear() #очищаем буфер ошибок Powershell
$erroractionpreference = «silentlycontinue» #подавляем вывод ошибок в консоль
$dnsresult = 0
$computername = $i.name #извлекаем имя станции
$dnsresult = [System.Net.Dns]::resolve("$computername")

if (!$error) #условие, если предыдущая команда не была завершена ошибкой
{
$ipaddress = $dnsresult.AddressList
$pingfunc = (New-Object system.net.networkinformation.ping).send("$ipaddress") #ping
if ($pingfunc.Status -eq «success»)
{
$sumreacheblepc++ #плюсуем обще количество доступных станций
$chrome = dir \\$ipaddress\C$\Program Files (x86)\Google\Chrome\Application\chrome.exe #проверка наличия Chrome
If ($chrome -ne $null) {write-host «Host $computername is reachable, use Chrome, and have ip $ipaddress»

$sumchrome++ #плюсуем количество станций с Chrome
}


Я бы использовал test-connection и test-path. Код сокращается в разы. Выйдет как-то вот так:

$computername = $i.name
if (test-connection ) {
$sumreacheblepc++
if (test-path "\\$computername\C$\Program Files (x86)\Google\Chrome\Application\chrome.exe") {$sumchrome++}
}


Опять же, обратите внимание, что код получается не универсальным. У вас всё подогнано под 64 битную винду, где хром стоит 32 битный.
Для универсальности, тогда уж лучше получить установленное ПО через WMI, смотреть, есть ли в установленных программах Chrome.

И ещё, для кода в статье есть тег source. Так как сейчас, в таких «success» кавычках, powershell код не выполнит.
Опечаточка. Вот так:

$computername = $i.name
if (test-connection $computername) {
$sumreacheblepc++
if (test-path "\\$computername\C$\Program Files (x86)\Google\Chrome\Application\chrome.exe") {$sumchrome++}
}
Ещё не забывайте про ForEach -Parallel.
Разве foreach -Parallel выполняется вне workflow? Не смущайте новичка такими нюансами без пояснений, что ли…
Раз уж вы начинающий, подскажу как оптимизировать ваше художество. Ничего, я и сам начинал с подобного.

1. Вместо Where-Object {} можете использовать альяс ?{}. А вместо Select-Object просто select. Имена свойств можно указывать без аргумента -Property. Этот аргумент удобно использовать для просмотра всех свойств объекта, например | select -Property *
2. Зачем вам в Get-AD(Object, Computer,User,Group) аргумент Filter? Вы выбрали все станции, а потом отсортировывали не выключенные станции через Where-Object проделывая, считай, двойную работу. Читай вы внимательно хелп к командлетам (это кстати можно удобно делать через Get-Help -Online), узнали бы что получить сразу не выключенные станции можно так:
$enablePCs = Get-ADComputer -Filter {enabled -eq $true}

3. Пинг компьютера вам уже подсказали выше можно было бы сделать через Test-Connection. Уточню лишь, что используя этот командлет вне условия if вы рискуете получить не булевый результат, а массив с результатами теста, по этому если вам нужно получить результат пинга в булеву переменную используйте аргумент -Quiet.
4. Получить наличие хрома на компьютере действительно лучше посредством WMI-запроса. Командлет для всех WMI запросов один — это Get-WMIObject. Необходимый командлету параметр это -Class. Что бы получить список WMI классов можно воспользоваться свитчем -List. Нужный нам для нашей задачи класс — Win32_InstalledProgram. Ну а полный запрос наличия хрома будет выглядеть так:
Get-WmiObject -Class Win32_InstalledProgram -ComputerName <computername>  | ?{$_.Name -like "*Chrome*"} | select Name, Version, Vendor

Итого, если не заниматься ерундой с выводом в консоль получается вот такой лаконичный код:
$enablePCs = Get-ADComputer -filter {enabled -eq $true} -SearchBase "OU=Computers,ou=someou,dc=somedomain,dc=corp"
$sumchrome = 0
$sumreacheblePC = 0
$sumunreacheblePC = 0
$pcwithoutchrome = 0

$enablePCs | ForEach-Object {
    if(Test-Connection -ComputerName $_.Name){
        $sumreacheblePC++
        if((Get-WmiObject -Class Win32_InstalledProgram | ?{$_.Name -like "*Chrome*"}) -ne $null){$sumchrome++}else{$pcwithoutchrome++}
    } else {$sumunreacheblePC++}
}


Он чутка сложнее для понимания новичками, так как не использует развернутую конструкцию foreach и можно легко запутаться в ссылках на текущий объект ($_). Но мне нравится как такой код выглядит. Прошу прощения за помпезность. ;-)
В коде забыл у Get-WmiObject указать -ComputerName $_.Name. Прошу прощения еще раз. Писал без проверки кода.
Спасибо за подсказку, учту все в следующих скриптах. Код кстати не сложный для понимания.
Про вывод в консоль вы правы, но я его использовал для отладки в основном, ну и еще нужно было собрать всю информацию в файл, просто исключил эту строку из кода.

Изначально для проверки наличия Chrome я использовал win32_product но не обнаружил в списке самого Chrome, поэтому решил проверять наличие исполняемого файла.
Можно поподробней про класс Win32_InstalledProgram? Я не нашел такого.
Вроде бы он появился только в Windows 10.
Воу… если так то прошу прощения. Щя изыщу способ для 2008R2/7. У меня и вправду Windows 10. =))))

Вот лопух то…
Я сам это узнал, прочитав восхищённое сообщение Йохана Арвидмарка в твиттере
Да. каждый «писатель» на повершеле должен написать свою систему сбора информации.
Это, кстати полезно.
у меня на гитхабе лежит мой вариант скриптов, тоже для этого дела, но мне было сложнее — вагон подсеток, все компьютеры по своим OU и тд — очень большая компания
Sign up to leave a comment.

Articles