Модераторы: bartram, Akella
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Powershell Вытаскиваем список компов леса и их ПО, проблема при взаимодействии с AD 
:(
    Опции темы
NordWolf
  Дата 16.4.2016, 10:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 15.8.2007

Репутация: нет
Всего: 1



Добрый день! У меня небольшая проблема с написанием скрипта, да и вообще хотелось бы услышать совета от более опытных людей, чем я. Задача, казалось бы, тривиальная, но я бьюсь с ней уже неделю. Суть – нужно собрать список всех рабочих станций в дереве, выбрать из них включенные, вытащить из включенных список установленного ПО и вывести итог в табличке Excel. Всё. В сети есть куча разных скриптов, но везде есть свои ньюансы. Одни скрипты лезут в AD в определённую OU и вытаскивают оттуда список всех компов, пингуют их и выкладывают в файл. Например:

Код

clear
Get-ADComputer -filter * -SearchBase "OU=Workstations,DC=domain,DC=local" | ft name -AutoSize > "C:\Scripts\ALLcomps.txt"
$comps = get-content "C:\Scripts\ALLcomps.txt"
$file = New-Item -itemtype file "C:\Scripts\ON.txt" -Force
foreach ($comp in $comps) 
{$ON = Get-WmiObject Win32_PingStatus -filter "Address='$comp'"
if ($ON.StatusCode -eq 0) {Add-Content $file "$comp"}
}


Проблема. Скрипт прекрасно отрабатывает в локальном домене, но если нам нужно чтобы скрипт доставал информацию из других поддоменов леса (Get-ADComputer -filter * -SearchBase " OU=Workstations,DC=subdomain,DC=domain,DC=local"), то возникают проблемы. На большинстве серверов поддоменов стоят Windows 2008 Standard и, как я понял, для них нужно отдельно устанавливать ADWS. На наши сервера почему-то не ставятся, пишет что данное обновление не подходит для текущей версии. Хотя все требования для установки выполнены. ((( Сам скрипт при выполнении ругается: 

Цитата

«Get-ADComputer : Сервер возвратил ссылку
C:\Scripts\ON.ps1:2 знак:1
+ Get-ADComputer -filter * -SearchBase "OU=Workstations,DC=subdomain,DC=domain,DC=local ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (smile [Get-ADComputer], ADReferralException
    + FullyQualifiedErrorId : ActiveDirectoryServer:8235,Microsoft.ActiveDirectory.Management.Commands.GetADComputer»


Файерволл отключал. Всё равно возвращает ссылку. 2 дня бился с этой проблемой, но так и не победил её. Решил пойти другим путём. Нашёл «многопоточный сканер IP адресов в локальной сети». Задал нужный диапазон подсетей и адресов, скрипт отработал нормально. Записал все пингующиеся хосты в файл. Минусы – долго, записывает не только рабочие места, но и принтеры, маршрутизаторы и пр… Начал пробовать доставать список ПО. Скрипт:


Код

# Get-InstalledApp.ps1
# Written by Bill Stewart ([email protected])
#
# Outputs installed applications on one or more computers that match one or
# more criteria.

param([String[]] $ComputerName,
      [String] $AppID,
      [String] $AppName,
      [String] $Publisher,
      [String] $Version,
      [Switch] $MatchAll,
      [Switch] $Help
     )

$HKLM = [UInt32] "0x80000002"
$UNINSTALL_KEY = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"

# Outputs a usage message and ends the script.
function usage {
  $scriptname = $SCRIPT:MYINVOCATION.MyCommand.Name

  "NAME"
  "    $scriptname"
  ""
  "SYNOPSIS"
  "    Outputs installed applications on one or more computers that match one or"
  "    more criteria."
  ""
  "SYNTAX"
  "    $scriptname [-computername <String[]>] [-appID <String>]"
  "    [-appname <String>] [-publisher <String>] [-version <String>] [-matchall]"
  ""
  "PARAMETERS"
  "    -computername <String[]>"
  "        Outputs applications on the named computer(s). If you omit this"
  "        parameter, the local computer is assumed."
  ""
  "    -appID <String>"
  "        Select applications with the specified application ID. An application's"
  "        appID is equivalent to its registry subkey in the location"
  "        HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall. For Windows"
  "        Installer-based applications, this is the application's product code"
  "        GUID (e.g. {3248F0A8-6813-11D6-A77B-00B0D0160060})."
  ""
  "    -appname <String>"
  "        Select applications with the specified application name. The appname is"
  "        the application's name as it appears in the Add/Remove Programs list."
  ""
  "    -publisher <String>"
  "        Select applications with the specified publisher name."
  ""
  "    -version <String>"
  "        Select applications with the specified version."
  ""
  "    -matchall"
  "        Output all matching applications instead of stopping after the first"
  "        match."
  ""
  "NOTES"
  "    All installed applications are output if you omit -appID, -appname,"
  "    -publisher, and -version. Also, the -appID, -appname, -publisher, and"
  "    -version parameters all accept wildcards (e.g., -version 5.2.*)."

  exit
}

function main {
  # If -help is present, output the usage message.
  if ($Help) {
    usage
  }

  # Create a hash table containing the requested application properties.
  #CALLOUT A
  $propertyList = @{}
  if ($AppID -ne "")     { $propertyList.AppID = $AppID }
  if ($AppName -ne "")   { $propertyList.AppName = $AppName }
  if ($Publisher -ne "") { $propertyList.Publisher = $Publisher }
  if ($Version -ne "")   { $propertyList.Version = $Version }
  #END CALLOUT A

  # Use the local computer's name if no computer name(s) specified.
  if ($ComputerName -eq $NULL) {
    $ComputerName = $ENV:COMPUTERNAME
  }

  # Iterate the computer name(s).
  foreach ($machine in $ComputerName) {
    $err = $NULL

    # If WMI throws a RuntimeException exception,
    # save the error and continue to the next statement.
    #CALLOUT B
    trap [System.Management.Automation.RuntimeException] {
      set-variable err $ERROR[0] -scope 1
      continue
    }
    #END CALLOUT B

    # Connect to the StdRegProv class on the computer.
    #CALLOUT C
    $regProv = [WMIClass] "\\$machine\root\default:StdRegProv"

    # In case of an exception, write the error
    # record and continue to the next computer.
    if ($err) {
      write-error -errorrecord $err
      continue
    }
    #END CALLOUT C

    # Enumerate the Uninstall subkey.
    $subkeys = $regProv.EnumKey($HKLM, $UNINSTALL_KEY).sNames
    foreach ($subkey in $subkeys) {
      # Get the application's display name.
      $name = $regProv.GetStringValue($HKLM,
        (join-path $UNINSTALL_KEY $subkey), "DisplayName").sValue
      # Only continue of the application's display name isn't empty.
      if ($name -ne $NULL) {
        # Create an object representing the installed application.
        $output = new-object PSObject
        $output | add-member NoteProperty ComputerName -value $machine
        $output | add-member NoteProperty AppID -value $subkey
        $output | add-member NoteProperty AppName -value $name
        $output | add-member NoteProperty Publisher -value `
          $regProv.GetStringValue($HKLM,
          (join-path $UNINSTALL_KEY $subkey), "Publisher").sValue
        $output | add-member NoteProperty Version -value `
          $regProv.GetStringValue($HKLM,
          (join-path $UNINSTALL_KEY $subkey), "DisplayVersion").sValue
        # If the property list is empty, output the object;
        # otherwise, try to match all named properties.
        if ($propertyList.Keys.Count -eq 0) {
          $output
        } else {
          #CALLOUT D
          $matches = 0
          foreach ($key in $propertyList.Keys) {
            if ($output.$key -like $propertyList.$key) {
              $matches += 1
            }
          }
          # If all properties matched, output the object.
          if ($matches -eq $propertyList.Keys.Count) {
            $output
            # If -matchall is missing, break out of the foreach loop.
            if (-not $MatchAll) {
              break
            }
          }
          #END CALLOUT D
        }
      }
    }
  }
}

Main



Запускаю так: 
Код

 .\Get-InstalledApp (Get-Content ON.txt) | Select-Object ComputerName, AppName, Version, Publisher | Sort-Object ComputerName | Export-CSV Report.csv -Delimiter ";" -notypeinformation -encoding UTF8 


Проблема осталась та же – он отработал по списку IP той подсети, в которой он запускался, но информацию о ПО рабочих станций других подсетей не собрал. 
Опыта работы в PSh не много (неделя, как начал с ним разбираться), поэтому прошу помочь в решении данной задачи. Правильной ли дорогой иду? Что упускаю? Куда копать?
Заранее Спасибо.

PM MAIL   Вверх
NordWolf
Дата 18.4.2016, 13:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 15.8.2007

Репутация: нет
Всего: 1



Немного продвинулся по своему вопросу. 
Оказывается ADWS не устанавливался на Windows 2008 Standrad потому, что не было накатано последнее обновление на Microsoft .Net Framework 3.5 SP1 под номером NDP35SP1-KB969166-x64, хотя автоматические обновления стоят. Подробнее проблема описывается здесь: https://blogs.technet.microsoft.com/heyscri...ershell-access/

После этого разобрался, почему не запускался скрипт, который получает список компьютеров из AD сервера,находящегося в поддомене. В итоге, подкорректировал скрипт и теперь он выглядит так:

Код

clear
import-Module ActiveDirectory
Get-ADComputer -server subdomain -filter * -SearchBase "ou=Workstations,dc=subdomain,dc=domain,dc=local" | ft dnshostname -AutoSize > "C:\Scripts\ALLcomps.txt"
(Get-Content ALLcomps.txt) -replace " ","" -replace "dnshostname","" -replace "-----------","" | ? {$_.trim() -ne "" } | set-content ALLComps.txt
$comps = get-content "C:\Scripts\ALLComps.txt"
$file = New-Item -itemtype file "C:\Scripts\ON.txt" -Force
foreach ($comp in $comps) 
{$ON = Get-WmiObject Win32_PingStatus -filter "Address='$comp'"
if ($ON.StatusCode -eq 0) {Add-Content $file "$comp"}
}



Скрипт берёт список рабочих станций в нужной OU в нужном поддомене, сохраняет в файл, удаляет лишние символы, пингует хосты по списку, какие откликаются - записывает в файл ON.txt.
Далее нужно вытащить из полученного списка рабочих станций, список установленного на них ПО. При попытки выполнить вышеупомянутый в первом сообщении скрипт  (Get-InstalledApp.ps1) командой:

Код

.\Get-InstalledApp (Get-Content ON.txt) | Select-Object ComputerName, AppName, Version, Publisher | Sort-Object ComputerName | Export-CSV Report.csv -Delimiter ";" -notypeinformation -encoding UTF8 


Выдаёт ошибку: 

Цитата

main : Не удается преобразовать значение "\\cmpname.sudomain.domain.local\root\default:StdRegProv" в тип "System.Managemen
t.ManagementClass". Ошибка: "Отказано в доступе. (Исключение из HRESULT: 0x80070005 (E_ACCESSDENIED))"
C:\Scripts\Get-InstalledApp.ps1:159 знак:5
+ main <<<<
    + CategoryInfo          : NotSpecified: (smile [Write-Error], RuntimeException
    + FullyQualifiedErrorId : RuntimeException,main


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

Start-Process powershell -ArgumentList "-file .\Get-InstalledApp.ps1" -Credential $cred (Get-Content ON.txt) | Select-Object ComputerName, AppName, Version, Publisher | Sort-Object ComputerName | Export-CSV Report.csv -Delimiter ";" -notypeinformation -encoding UTF8


При выполнении выдаёт окно ввода логина и пароля, ввожу, выходит ошибка:

Цитата

Start-Process : Не удается найти позиционный параметр, принимающий аргумент "System.Object[]".
строка:1 знак:14
+ Start-Process <<<<  powershell -ArgumentList "-file .\Get-InstalledApp.ps1" -Credential $cred (Get-Content ON.txt) |
Select-Object ComputerName, AppName, Version, Publisher | Sort-Object ComputerName | Export-CSV Report.csv -Delimiter "
;" -notypeinformation -encoding UTF8
    + CategoryInfo          : InvalidArgument: (smile [Start-Process], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.StartProcessCommand



куда копать, подскажите?
PM MAIL   Вверх
01MDM
Дата 18.4.2016, 22:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 273
Регистрация: 10.5.2008
Где: Default City

Репутация: 29
Всего: 29



На мой взгляд вы запутались в Start-Process. Отработает или нет не знаю, так как не админ.
Код

Start-Process powershell -arg "-command { .\Get-InstalledApp ...... | Export-CSV Report.csv -Delimiter ';' -notypeinformation -encoding UTF8 }" -credential $cred



--------------------
Вопросы в личке останутся без ответов.
PM MAIL   Вверх
NordWolf
Дата 19.4.2016, 07:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 15.8.2007

Репутация: нет
Всего: 1



Цитата(01MDM @  18.4.2016,  22:16 Найти цитируемый пост)
На мой взгляд вы запутались в Start-Process. Отработает или нет не знаю, так как не админ.


Возможно. Я делаю по примерам из сети. Попробовал сделать проще:

Код

Start-Process powershell -ArgumentList "-file .\Get-InstalledApp.ps1 Get-Content ON.txt" -Credential $cred


Выходит окошко для ввода логина и пароля, ввожу, он думает секунд 7, а потом выдаёт ошибку и быстро закрывает окно:

Цитата

main: Не удается преобразовать значение "\\(Get-Content\root\default:StdRegProv" в тип "System.Management.ManagementClass". Ошибка: "Сервер RPC недоступен."(
Исключение из HRESULT: 0x800706BA)"
C:\Scripts\Get-InstalledApp.ps1:159 знак:5
+main <<<
      +CategoryInfo : NotSpecified: (smile [Write-Error], RuntimeException
      +FullyQualifiedErrorId : RuntimeException.main


PM MAIL   Вверх
01MDM
Дата 19.4.2016, 07:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 273
Регистрация: 10.5.2008
Где: Default City

Репутация: 29
Всего: 29



Что это такое?
Код

"-file .\Get-InstalledApp.ps1 Get-Content ON.txt"

Если к скрипту Get-InstalledApp.ps1 идет набор парараметров из содержимого файла on.txt, то и оформите это соответствующим образом:
Код

"-file .\Get-InstalledApp.ps1 (Get-Content ON.txt)"


Но и здесь, без самого on.txt, возникают вопросы.


--------------------
Вопросы в личке останутся без ответов.
PM MAIL   Вверх
NordWolf
Дата 19.4.2016, 08:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 15.8.2007

Репутация: нет
Всего: 1



Цитата(01MDM @  19.4.2016,  07:47 Найти цитируемый пост)
Если к скрипту Get-InstalledApp.ps1 идет набор парараметров из содержимого файла on.txt, то и оформите это соответствующим образом:


да, я увидел, что скобочки не поставил, собственно эффект тот же. 
Сам скрипт Get-InstalledApp.ps1  отрабатывает отлично при условии что в файле ON.txt список раб мест, находящихся в основном домене (domain.local). Запускаю так:
Код

.\Get-InstalledApp (Get-Content ON.txt) | Select-Object ComputerName, AppName, Version, Publisher | Sort-Object ComputerName | Export-CSV Report.csv -Delimiter ";" -notypeinformation -encoding UTF8


Если в файле ON.txt список раб мест, находящихся в в поддомене (subdoamin.pelican.local), то возникает проблема описанная выше. Содержимое ON.txt это записи вида:
Код

comp001.subdomain.domain.local
comp002.subdomain.domain.local
comp005.subdomain.domain.local
comp008.subdomain.domain.local

PM MAIL   Вверх
01MDM
Дата 19.4.2016, 08:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 273
Регистрация: 10.5.2008
Где: Default City

Репутация: 29
Всего: 29



А где остальные параметры? Их нет в файле on.txt:
Код

param([String[]] $ComputerName,
      [String] $AppID,
      [String] $AppName,
      [String] $Publisher,
      [String] $Version,
      [Switch] $MatchAll,
      [Switch] $Help
     )



--------------------
Вопросы в личке останутся без ответов.
PM MAIL   Вверх
NordWolf
Дата 19.4.2016, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 15.8.2007

Репутация: нет
Всего: 1



Цитата(01MDM @  19.4.2016,  08:47 Найти цитируемый пост)
где остальные параметры? Их нет в файле on.txt:


в  ON.txt лишь список рабочих компов. По сценарию скрипт Get-InstalledApp вытаскивает информацию об установленном ПО с этих рабочих компов и сортирует их по параметрам указанным выше. Например,  если я сделаю так:
Код

.\Get-InstalledApp | Select-Object ComputerName, AppName, Version, Publisher | Sort-Object ComputerName | Export-CSV Report.csv -Delimiter ";" -notypeinformation -encoding UTF8


То он мне выведет список всего ПО установленного у меня на компе в 4 колонки (ComputerName, AppName, Version, Publisher). Тоже самое произойдёт, если в файле ON.txt будет название компов находящихся в корневом домене(domain.local) - он выведет список с 4-мя колонками и отсортирует по названию компа. Но если в файле будут списки компов из поддомена (subdomain.domain.local), то он выведет ошибку: Отказано в доступе. Пробую запускать от имени админа поддомена, он выдаёт другую ошибку "Сервер RPC недоступен".

Суть вопроса проста. Как вытащить список ПО имея список компов(ON.txt), которые находятся в твоём поддомене?

PM MAIL   Вверх
01MDM
Дата 19.4.2016, 11:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 273
Регистрация: 10.5.2008
Где: Default City

Репутация: 29
Всего: 29



NordWolf,
Понятно, я не внимательно посмотрел скрипт.
Значит это проблема доступа, наверное следует смотреть в сторону изучения PowerShell Remoting (есть доходчивые статьи) -- настройки удаленного доступа.
Это к сожалению выходит за рамки моей компетенции -- никогда не имел даже рабочего компьютера, не говоря о сети.



--------------------
Вопросы в личке останутся без ответов.
PM MAIL   Вверх
NordWolf
Дата 20.4.2016, 05:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 15.8.2007

Репутация: нет
Всего: 1



Цитата(01MDM @  19.4.2016,  11:53 Найти цитируемый пост)
Значит это проблема доступа, наверное следует смотреть в сторону изучения PowerShell Remoting (есть доходчивые статьи) -- настройки удаленного доступа

Понял, поищу, спасибо за наводку. 
Если будут какие-то подвижки, то отпишусь.
PM MAIL   Вверх
NordWolf
Дата 27.4.2016, 13:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 15.8.2007

Репутация: нет
Всего: 1



Нашёл отличную статью на хабре по PSh Remoting
https://habrahabr.ru/post/278691/

Итак, добился вывода списка ПО со всех компов леса. Есть несколько вопросов по оптимизации... Что сейчас происходит.

1) Запускаю скрипт ON.ps1 без каких-либо дополнительных параметров.  
Скрипт пробегает по всем серверам леса, находит там все компы и записывает в файл  с именем *_Allcomps.txt. Далее берёт их из списка и пингует. 
Тех, кто откликается на пинг - закидывает в файл ON.txt на СЕРВЕР филиала, к которому принадлежат эти компы.
Пример скрипта:

Код

clear
import-Module ActiveDirectory
Get-ADComputer -server brn -filter * -SearchBase "dc=brn,dc=domain,dc=local" | ft dnshostname -AutoSize > "\\comp\c$\Scripts\LOGS!\BRN_ALLcomps.txt"
(Get-Content \\comp\c$\Scripts\LOGS!\BRN_ALLcomps.txt) -replace " ","" -replace "dnshostname","" -replace "-----------","" | ? {$_.trim() -ne "" } | set-content \\comp\c$\Scripts\LOGS!\BRN_ALLComps.txt
$comps = get-content "\\comp\c$\Scripts\LOGS!\BRN_ALLComps.txt"
$file = New-Item -itemtype file "\\brndc.brn.domain.local\c$\Scripts\ON.txt" -Force
foreach ($comp in $comps) 
{$ON = Get-WmiObject Win32_PingStatus -filter "Address='$comp'"
if ($ON.StatusCode -eq 0) {Add-Content $file "$comp"}
}

Get-ADComputer -server ekb -filter * -SearchBase "dc=ekb,dc=domain,dc=local" | ft dnshostname -AutoSize > "\\comp\c$\Scripts\LOGS!\EKB_ALLcomps.txt"
(Get-Content \\comp\c$\Scripts\LOGS!\EKB_ALLcomps.txt) -replace " ","" -replace "dnshostname","" -replace "-----------","" | ? {$_.trim() -ne "" } | set-content \\comp\c$\Scripts\LOGS!\EKB_ALLcomps.txt
$comps = get-content "\\comp\c$\Scripts\LOGS!\EKB_ALLcomps.txt"
$file = New-Item -itemtype file "\\ekbdc.ekb.domain.local\c$\Scripts\ON.txt" -Force
foreach ($comp in $comps) 
{$ON = Get-WmiObject Win32_PingStatus -filter "Address='$comp'"
if ($ON.StatusCode -eq 0) {Add-Content $file "$comp"}
}

Get-ADComputer -server krsk -filter * -SearchBase "dc=krsk,dc=domain,dc=local" | ft dnshostname -AutoSize > "\\comp\c$\Scripts\LOGS!\KRSKDC_ALLcomps.txt"
(Get-Content \\comp\c$\Scripts\LOGS!\KRSKDC_ALLcomps.txt) -replace " ","" -replace "dnshostname","" -replace "-----------","" | ? {$_.trim() -ne "" } | set-content \\comp\c$\Scripts\LOGS!\KRSKDC_ALLComps.txt
$comps = get-content "\\comp\c$\Scripts\LOGS!\KRSKDC_ALLComps.txt"
$file = New-Item -itemtype file "\\KRSKDC.krsk.domain.local\c$\Scripts\ON.txt" -Force
foreach ($comp in $comps) 
{$ON = Get-WmiObject Win32_PingStatus -filter "Address='$comp'"
if ($ON.StatusCode -eq 0) {Add-Content $file "$comp"}
}

Get-ADComputer -server ufa -filter * -SearchBase "dc=ufa,dc=domain,dc=local" | ft dnshostname -AutoSize > "\\comp\c$\Scripts\LOGS!\UFA_ALLcomps.txt"
(Get-Content \\comp\c$\Scripts\LOGS!\UFA_ALLcomps.txt) -replace " ","" -replace "dnshostname","" -replace "-----------","" | ? {$_.trim() -ne "" } | set-content \\comp\c$\Scripts\LOGS!\UFA_ALLcomps.txt
$comps = get-content "\\comp\c$\Scripts\LOGS!\UFA_ALLcomps.txt"
$file = New-Item -itemtype file "\\ufadc.ufa.domain.local\c$\Scripts\ON.txt" -Force
foreach ($comp in $comps) 
{$ON = Get-WmiObject Win32_PingStatus -filter "Address='$comp'"
if ($ON.StatusCode -eq 0) {Add-Content $file "$comp"}
}

....



2) Далее. Я запускаю скрипт, находящийся на моём компе "comp" (S1.ps1), на удалённом серваке под определённым пользователем. По очереди (brn, ekb, krsk,etc). для каждого сервера филиала. Вот пример:
Код

PS C:\Scripts> Invoke-Command -FilePath s1.ps1 -ComputerName brndc.brn.domain.local -Credential brn\Adm


Содержание s1.ps1:
Код

C:\Scripts\Get-InstalledApp.ps1 (Get-Content C:\Scripts\LOGS!\ON.txt) | Select-Object ComputerName, AppName, Version, Publisher | Sort-Object ComputerName | export-csv -append -path \\comp.domain.local\$Scripts\LOGS!\Report.csv -Delimiter ";" -encoding UTF8 -notypeinformation


Содержание Get-InstalledApp.ps1 не менял, см. выше.
В итоге, скрипт подключается к введённому в параметрах командлета Invoke-Command серваку, берёт оттуда сформированный ранее файл ON.txt, выдёргивает ПО на компах (Get-InstalledApp.ps1) и записывает на мой комп(comp.domain.local). Для каждого сервака я проделываю процедуру с Invoke-Command вручную, т.к. нужно вписывать логины и пароли каждый раз разные.

Друзья, как можно оптимизировать данный код с вашей точки зрения?  
А то получается, что мне для того чтобы вытащить ПО нужно сначала запустить скрипт (ON.ps1) , потом запустить другой скрипт(s1.ps1), вписывая в параметры ручками название сервака  и логин\пароль админа того сервака, от имени которого нужно запустить данный скрипт...
PM MAIL   Вверх
NordWolf
Дата 27.4.2016, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 15.8.2007

Репутация: нет
Всего: 1



Да, забыл уточнить. Версия PowerShell 3.0
PM MAIL   Вверх
NordWolf
Дата 24.5.2016, 07:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 15.8.2007

Репутация: нет
Всего: 1



Спасение утопающих дело рук самих утопающих)
1) первое, что нужно обязательно сделать - так это внести в групповые политики настройки брандмауэра - разрешить работу с WinRM и WS-Management (WMI). На эту тему есть куча статей, например, на хабре.
2) Немного перегруппировал куски кода, чтобы можно было запускать 1 файл, а не несколько как раньше. Добавил маркеры (write host) для удобства мониторинга, немного переделал логику. А так же добавил возможность сохранения пароля после разового ввода и последующего его использования в коде. В итоге получилось, что при запуске скрипта ON.ps1, запрашиваются сразу авторизационные данные (Credentials) для всех дочерних доменов(7 шт), для последующего их использования.  
3) На некоторых хостах появлялась ошибка  "Сервер RPC недоступен. (Исключение из HRESULT: 0x800706BA)". Чаще всего это устранялось  - добавлением исключений в брандмауэр (см. пункт 1), либо исправлением ошибок в DNS. Либо надо смотреть на конкретном примере)
Ну а теперь собственно сам скрипт... приведу лишь часть, т.к. он повторяется.

Код

clear
import-Module ActiveDirectory

$cbrn = Get-Credential brn\odin
$ckrsk = Get-Credential krsk\Odin
$searchPC = "1. Поиск включенных компьютеров в AD."
$searchSOFT = "2. Поиск установленного ПО, версии, производителя и пр."
$searchOS = "3. Поиск версии установленной ОС."


Write-Host ">=======================БАРНАУЛ (BRNDC)=========================<"
Write-Host $searchPC
Get-ADComputer -server brn -filter * -SearchBase "dc=brn,dc=domain,dc=local" -Credential $cbrn | ft dnshostname -AutoSize > "c:\Scripts\LOGS!\BRN_ALLcomps.txt"
(Get-Content c:\Scripts\LOGS!\BRN_ALLcomps.txt) -replace " ","" -replace "dnshostname","" -replace "-----------","" | ? {$_.trim() -ne "" } | set-content c:\Scripts\LOGS!\BRN_ALLComps.txt
$comps = get-content "\\mycomp01\c$\Scripts\LOGS!\BRN_ALLcomps.txt"
$file = New-Item -itemtype file "c:\Scripts\LOGS!\BRN_ON.txt" -Force
foreach ($comp in $comps) 
{$ON = Get-WmiObject Win32_PingStatus -filter "Address='$comp'"
if ($ON.StatusCode -eq 0) {Add-Content $file "$comp"}
}

Write-Host $searchSOFT
Invoke-Command -ScriptBlock {C:\Scripts\Get-InstalledApp.ps1 (Get-Content \\mycomp01\$Scripts\LOGS!\BRN_ON.txt) | Select-Object ComputerName, AppName, Version, Publisher | Sort-Object ComputerName | export-csv -append -path \\mycomp01\$Scripts\LOGS!\Report.csv -Delimiter ";" -encoding UTF8 -notypeinformation} -ComputerName brndc.brn.domain.local -Credential $cbrn

Write-Host $searchOS
Get-WmiObject Win32_OperatingSystem -Computer (Get-Content "C:\Scripts\LOGS!\BRN_ON.txt") -Credential $cbrn | Select-Object PSComputerName, Caption, CSDVersion, OSArchitecture | Sort-Object PSComputerName | export-csv -append -path C:\Scripts\LOGS!\Win_rep.csv -Delimiter ";" -encoding UTF8 -notypeinformation
Write-Host ">==========================ЗАВЕРШЕНО==========================<"
''
''
Write-Host ">=======================КРАСНОЯРСК (KRSKDC)=========================<"
и т.д.


Get-InstalledApp.ps1 - остался неизменным (см. выше).

Я уверен, код можно оптимизировать, загнав его допустим в цикл с перебором значений, но я этого пока не умею делать (осваивать PSh стал недавно). А время поджимает, начальство постоянно подкидывает всё новые задания. Поэтому буду рад вашей помощи в этом вопросе.
Ну а так, спасибо 01MDM за советы и помощь. 

Надеюсь мой труд и опыт кому-нибудь ещё пригодится.

Это сообщение отредактировал(а) NordWolf - 24.5.2016, 07:13
PM MAIL   Вверх
Lizukcha
Дата 30.5.2016, 11:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 15.5.2016

Репутация: нет
Всего: нет



Цитата(NordWolf @ 27.4.2016,  13:18)
Нашёл отличную статью на хабре по PSh Remoting
https://habrahabr.ru/post/278691/

Итак, добился вывода списка ПО со всех компов леса. Есть несколько вопросов по оптимизации... Что сейчас происходит.

1) Запускаю скрипт ON.ps1 без каких-либо дополнительных параметров.  
Скрипт пробегает по всем серверам леса, находит там все компы и записывает в файл  с именем *_Allcomps.txt. Далее берёт их из списка и пингует. 
Тех, кто откликается на пинг - закидывает в файл ON.txt на СЕРВЕР филиала, к которому принадлежат эти компы.
Пример скрипта:

Код

clear
import-Module ActiveDirectory
Get-ADComputer -server brn -filter * -SearchBase "dc=brn,dc=domain,dc=local" | ft dnshostname -AutoSize > "\\comp\c$\Scripts\LOGS!\BRN_ALLcomps.txt"
(Get-Content \\comp\c$\Scripts\LOGS!\BRN_ALLcomps.txt) -replace " ","" -replace "dnshostname","" -replace "-----------","" | ? {$_.trim() -ne "" } | set-content \\comp\c$\Scripts\LOGS!\BRN_ALLComps.txt
$comps = get-content "\\comp\c$\Scripts\LOGS!\BRN_ALLComps.txt"
$file = New-Item -itemtype file "\\brndc.brn.domain.local\c$\Scripts\ON.txt" -Force
foreach ($comp in $comps) 
{$ON = Get-WmiObject Win32_PingStatus -filter "Address='$comp'"
if ($ON.StatusCode -eq 0) {Add-Content $file "$comp"}
}

Get-ADComputer -server ekb -filter * -SearchBase "dc=ekb,dc=domain,dc=local" | ft dnshostname -AutoSize > "\\comp\c$\Scripts\LOGS!\EKB_ALLcomps.txt"
(Get-Content \\comp\c$\Scripts\LOGS!\EKB_ALLcomps.txt) -replace " ","" -replace "dnshostname","" -replace "-----------","" | ? {$_.trim() -ne "" } | set-content \\comp\c$\Scripts\LOGS!\EKB_ALLcomps.txt
$comps = get-content "\\comp\c$\Scripts\LOGS!\EKB_ALLcomps.txt"
$file = New-Item -itemtype file "\\ekbdc.ekb.domain.local\c$\Scripts\ON.txt" -Force
foreach ($comp in $comps) 
{$ON = Get-WmiObject Win32_PingStatus -filter "Address='$comp'"
if ($ON.StatusCode -eq 0) {Add-Content $file "$comp"}
}

Get-ADComputer -server krsk -filter * -SearchBase "dc=krsk,dc=domain,dc=local" | ft dnshostname -AutoSize > "\\comp\c$\Scripts\LOGS!\KRSKDC_ALLcomps.txt"
(Get-Content \\comp\c$\Scripts\LOGS!\KRSKDC_ALLcomps.txt) -replace " ","" -replace "dnshostname","" -replace "-----------","" | ? {$_.trim() -ne "" } | set-content \\comp\c$\Scripts\LOGS!\KRSKDC_ALLComps.txt
$comps = get-content "\\comp\c$\Scripts\LOGS!\KRSKDC_ALLComps.txt"
$file = New-Item -itemtype file "\\KRSKDC.krsk.domain.local\c$\Scripts\ON.txt" -Force
foreach ($comp in $comps) 
{$ON = Get-WmiObject Win32_PingStatus -filter "Address='$comp'"
if ($ON.StatusCode -eq 0) {Add-Content $file "$comp"}
}

Get-ADComputer -server ufa -filter * -SearchBase "dc=ufa,dc=domain,dc=local" | ft dnshostname -AutoSize > "\\comp\c$\Scripts\LOGS!\UFA_ALLcomps.txt"
(Get-Content \\comp\c$\Scripts\LOGS!\UFA_ALLcomps.txt) -replace " ","" -replace "dnshostname","" -replace "-----------","" | ? {$_.trim() -ne "" } | set-content \\comp\c$\Scripts\LOGS!\UFA_ALLcomps.txt
$comps = get-content "\\comp\c$\Scripts\LOGS!\UFA_ALLcomps.txt"
$file = New-Item -itemtype file "\\ufadc.ufa.domain.local\c$\Scripts\ON.txt" -Force
foreach ($comp in $comps) 
{$ON = Get-WmiObject Win32_PingStatus -filter "Address='$comp'"
if ($ON.StatusCode -eq 0) {Add-Content $file "$comp"}
}

....



2) Далее. Я запускаю скрипт, находящийся на моём компе "comp" (S1.ps1), на удалённом серваке под определённым пользователем. По очереди (brn, ekb, krsk,etc). для каждого сервера филиала. Вот пример:
Код

PS C:\Scripts> Invoke-Command -FilePath s1.ps1 -ComputerName brndc.brn.domain.local -Credential brn\Adm


Содержание s1.ps1:
Код

C:\Scripts\Get-InstalledApp.ps1 (Get-Content C:\Scripts\LOGS!\ON.txt) | Select-Object ComputerName, AppName, Version, Publisher | Sort-Object ComputerName | export-csv -append -path \\comp.domain.local\$Scripts\LOGS!\Report.csv -Delimiter ";" -encoding UTF8 -notypeinformation


Содержание Get-InstalledApp.ps1 не менял, см. выше.
В итоге, скрипт подключается к введённому в параметрах командлета Invoke-Command серваку, берёт оттуда сформированный ранее файл ON.txt, выдёргивает ПО на компах (Get-InstalledApp.ps1) и записывает на мой комп(comp.domain.local). Для каждого сервака я проделываю процедуру с Invoke-Command вручную, т.к. нужно вписывать логины и пароли каждый раз разные.

Друзья, как можно оптимизировать данный код с вашей точки зрения?  
А то получается, что мне для того чтобы вытащить ПО нужно сначала запустить скрипт (ON.ps1) , потом запустить другой скрипт(s1.ps1), вписывая в параметры ручками название сервака  и логин\пароль админа того сервака, от имени которого нужно запустить данный скрипт...

Хорошо статья!  smile 


PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Windows"
December
bartram
Akella

Запрещается!

1. Обсуждать взлом и делиться кряками

2. Способствовать созданию и распространению вирусов

  • Для бессмертных бородатых вопросов типа Win vs Nix есть специальный форум Религиозные Войны
  • Несанкционированная реклама на форуме запрещена
  • Пожалуйста, давайте своим темам осмысленный, информативный заголовок. Вопль "Помогите!" таковым не является.
  • Чем полнее и яснее Вы изложите проблему, тем быстрее мы её решим.
  • ВСЕГДА УКАЗЫВАЙТЕ ВЕРСИЮ ОС

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, December, bartram, Akella.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | MS Windows | Следующая тема »


 




[ Время генерации скрипта: 0.1103 ]   [ Использовано запросов: 20 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.