F
F
Filkri2019-12-10 10:15:32
PowerShell
Filkri, 2019-12-10 10:15:32

Is Software Inventory and Exporting Data to Excel Possible via PowerShell?

I apologize in advance, maybe for stupid questions and dumb things, I'm not a magician, I'm just learning ....
The point is, there is a park of computers in the corporate domain. it is necessary to make an inventory of programs on computers, it is not possible to install and even more so purchase software. The idea came to make a PowerShell script that will pull information from the registry and throw it into the table. Scatter the script on computers and throw the result into a folder, then collect it in a heap through Excel. But I ran into a couple of problems, since there is little experience in PowerShell.
1) I know how to see the name of the computer, but I still haven’t figured out how to save the file with the name of this computer ....
2) there are 2 scripts, the 1st one displays information about the software on the PC, it is more than satisfied, the second one looks and writes down the information about the hardware. BUT, it didn't work for me to force the second script to take information from the registry and write to the file.
I don’t ask for the finished code, although I don’t refuse, I’ll read it, I’ll figure it out, I think =) I throw both scripts in their original form, as I found on the forums. here, rather, a couple of points, how to pull out the info from the array and force it to write to a column and how to write a variable to the file name
I tried to write to a table like this
# DeviceID
$LogiclDisk.Cells.Item($Row, $Column) = $temp | Select-Object -Property DisplayName
$Column++
# DeviceID
$LogiclDisk.Cells.Item($Row, $Column) = -Massive ( $temp | Select-Object -Property DisplayName)
$Column++
but something went wrong ... please don’t throw a lot of tomatoes, but at least direct where to dig ...

Answer the question

In order to leave comments, you need to log in

3 answer(s)
A
Andrew AT, 2019-12-10
@AAT666

1. There are plenty of such scripts on the net. This is already a trivial task. The search yields a wealth of information. The second on request "Powershell software inventory" is a century-old Khabrov article - Inventory of computers in a domain. Laziness-engine ... well, etc., etc.
2. Why bother with Excel COM objects?? Isn't it easier to save everything in a CSV file and then do whatever you want with it?
3. Why scatter the script on computers, if you can pick up the information remotely?

T
tartarelin, 2019-12-10
@tartarelin

Well, you know, if you don’t figure out how to save a file with a computer name, then maybe you should stop writing your own script, and use ready-made solutions?

F
Filkri, 2019-12-10
@Filkri

software output

Write-Output ("`n`t`Приступаю к анализу системы...`n")
Write-Output ("`n`---------------------------------------------------------")
#Объявляем функцию содержащую способ вывода и сорт. по свойству DisplayName.
function Grid-Output
{
param (
<#
Объявляем, что наличие массива элементов указанного ниже для работы
данной функции явлется строго обязательным
#>
[Parameter (Mandatory = $true)]
[Array] $Massive
)
<#
Сортируем вывод по свойству DisplayName, далее указываем формат вывода
GridView
#>
$Massive |sort-object -property DisplayName | Out-GridView
}
<#
Получаем объекты из реестра.
На данном этапе из реестра мы получ. объекты типа:
System.MarshalByRefObject.RegistryKey (Microsoft.Win32.RegistryKey)
Отдельный объект для этих целей был создан потому что:
1.Возможно данный объект, в последующем, необходимо будет изменить.
Скорее всего даже на функцию анализирующую массивы
элементов описанных ниже, формируя единый массив:
1.1: $soft = Get-WmiObject -Class Win32_Product
1.2: $soft32 = gci "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
1.3: $soft64 = gci "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
В связи с этим мы изолируем его для упрощения последующих модификаций.
2. Улучшает читабельность кода.
#>
[array]$RegUnistValues = Get-ChildItem HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
<#
Генерируем объекты Automation.PSCustomObject для каждого свойства полученных ранее объектов Win32.RegistryKey
Более подр. информацию по Get-ItemProperty можно почитать тут:
https://technet.microsoft.com/ru-ru/library/hh8498...
#>
[String]$temp = 'Здесь будут временно содержаться значения'
[Array]$temp = $RegUnistValues | ForEach-object {(Get-ItemProperty Microsoft.PowerShell.Core\Registry::$_)}
<#
Создаём запрос на активацию фильтра.
Для этого мы генерируем popup запрос вывод которого записываем в объект $result.
object.Popup(strText,[nSecondsToWait],[strTitle],[nType]) в данном случае имеет следующие параметры:
strText = "Активировать фильтрацию столбцов?" / Текст запроса
nSecondsToWait = 10 / время ожидания ответа от пользователя
strTitle = "Question" / Не обязательное значение. Данная строка будет отображаться в сообщения.
nType = 4+32 / Типы кнопок во всплывающем сообщении. В данном случае :
4 = Сочетание кнопок "Да" и "Нет"
32 = Рисунок знака вопроса в сообщении
Более подробную информацию можно взять тут:
https://msdn.microsoft.com/en-us/library/x83z1d9f(...
#>
$shell = new-object -comobject "WScript.Shell"
$result = $shell.popup("Активировать фильтрацию столбцов?",10,"Question",4+32)
<#
Используем оператор Switch для анализа знчений объект $result
(ВНИМАНИЕ!! использование данного оператору в больших проектах с .Net объектами неприемлимо
и считается дурным тоном, так как сильно затрудняет читабильность кода. Аналогов в данном
случае я, к сожалению, не нашёл)
В данном случае объект $result у нас может иметь 3 варианта:
1. -1 : если в popup окне пользователь не нажал ни одну кнопку, и окно было закрыто по Тайм-Ауту.
2. 6 : если в popup окне пользователь нажал "Да"
3. 7 : если в popup окне пользователь нажал "Нет"
Соответственно, в зависимости от значения $result выполняется сценарий.
P.S.: значение -1 и все остальные возможные значения исключая 6 и 7 у меня перекрывает сценарий: Default.
Сделано на случай если $result вернёт вместо значения ошибку.
#>
Switch ($result) {
6 {
Write-Output ("`n`t`Фильтр активирован.`n")
<#
В данном конкретном случае меня интересовали свойста DisplayName, DIsplayVersion, PSChildName.
Однако никто не запрещает выбрать самостоятельно. Напоминаю, что все доступные свойтсва объекта
можно получить: $тут_будет_указан_объект_свойства_которого_хотим_посмотреть | Get-Member
В это конкретном случае $temp | Get-Member
Далее выбираем из свойств NoteProperty, указываем через запятую после Select-Object -Property.
Выбранные нами свойства будут являться заголовками столбцов при выводе.
#>
#вывод полученных данных с помощью ранее написанной функции Grid-Output
Grid-Output -Massive ($temp | Select-Object -Property DisplayName, DIsplayVersion, PSChildName)
}
7 {
Write-Output ("`n`t`Фильтр отключен.`n")
#вывод полученных данных с помощью ранее написанной функции Grid-Output#
Grid-Output -Massive $temp
}
Default {
Write-Output ("`n`t`Время на подтверждение активации фильтра истекло. Фильтр отключен.`n")
#вывод полученных данных с помощью ранее написанной функции Grid-Output
Grid-Output -Massive $temp
}
}
#Обнуляем значение, дабы не оставлять после себя артефактов со значениями реестра.
[String]$RegUnistValues = 'Здесь содержались значения реестра'
[String]$temp = 'Здесь временно содержались значения'
Write-Output ("`n`t`Запрос успешно обработан.`n")
Write-Output ("`n`---------------------------------------------------------")
Write-Output ("`n`t`Работа скрипта завершена.`n")
<#
Блокируем автоматическое закрытие окна PowerShell после выполнения скрипта. В данном конкретном случае,
мне необходимо было сделать именно таким образом, однако правильнее будет запустить скрипт с ключом:
powershell.exe -NoExit -command c:\myscript.ps1
Ибо вносить для этого отдельные изменения в сценарий не рекомендуется.
#>
$host.ui.RawUI.ReadKey(6)|out-null
# Созадём объект Excel
$Excel = New-Object -ComObject Excel.Application
# Делаем его видимым
$Excel.Visible = $true
# Добавляем рабочую книгу
$WorkBook = $Excel.Workbooks.Add()
$LogiclDisk = $WorkBook.Worksheets.Item(1)
# Переименовываем лист
$LogiclDisk.Name = 'Логические диски'
# Заполняем ячейки - шапку таблицы
$LogiclDisk.Cells.Item(1,1) = 'Буква диска'
$LogiclDisk.Cells.Item(1,2) = 'Метка'
$LogiclDisk.Cells.Item(1,3) = 'Размер (ГБ)'
$LogiclDisk.Cells.Item(1,4) = 'Свободно (ГБ)'
# Выделяем жирным шапку таблицы
$LogiclDisk.Rows.Item(1).Font.Bold = $true
# Выравниваем для того, чтобы их содержимое корректно отображалось в ячейке
$UsedRange = $LogiclDisk.UsedRange
$UsedRange.EntireColumn.AutoFit() | Out-Null
# Переходим на следующую строку...
$Row = 2
$Column = 1
# Добавляем лист
$WorkBook.Worksheets.Add()
# ... и заполняем данными в цикле по логическим разделам
Get-WmiObject Win32_LogicalDisk | ForEach-Object `
{
# DeviceID
$LogiclDisk.Cells.Item($Row, $Column) = $_.DeviceID
$Column++
# VolumeName
$LogiclDisk.Cells.Item($Row, $Column) = $_.VolumeName
$Column++
# Size
$LogiclDisk.Cells.Item($Row, $Column) = ([Math]::Round($_.Size/1GB, 2))
$Column++
# Free Space
$LogiclDisk.Cells.Item($Row, $Column) = ([Math]::Round($_.FreeSpace/1GB, 2))
# Переходим на следующую строку и возвращаемся в первую колонку
$Row++
$Column = 1
}
$PhysicalDrive = $WorkBook.Worksheets.Item(1)
# Переименовываем лист
$PhysicalDrive.Name = 'Физические диски'
# Заполняем ячейки - шапку таблицы
$PhysicalDrive.Cells.Item(1,1) = 'Модель'
$PhysicalDrive.Cells.Item(1,2) = 'Размер (ГБ)'
$PhysicalDrive.Cells.Item(1,3) = 'Кол-во разделов'
$PhysicalDrive.Cells.Item(1,4) = 'Тип'
# Выделяем жирным шапку таблицы
$LogiclDisk.Rows.Item(1).Font.Bold = $true
# Выравниваем для того, чтобы их содержимое корректно отображалось в ячейке
$UsedRange = $LogiclDisk.UsedRange
$UsedRange.EntireColumn.AutoFit() | Out-Null
# Переходим на следующую строку...
$Row = 2
$Column = 1
# ... и заполняем данными в цикле по физическим дискам
Get-WmiObject Win32_DiskDrive | ForEach-Object `
{
# Model
$PhysicalDrive.Cells.Item($Row, $Column) = $_.Model
$Column++
# Size
$PhysicalDrive.Cells.Item($Row, $Column) = ([Math]::Round($_.Size /1GB, 1))
$Column++
# Partitions
$PhysicalDrive.Cells.Item($Row, $Column) = $_.Partitions
$Column++
# InterfaceType
$PhysicalDrive.Cells.Item($Row, $Column) = $_.InterfaceType
# Переходим на следующую строку и возвращаемся в первую колонку
$Row++
$Column = 1
}
# Выделяем жирным шапку
$PhysicalDrive.Rows.Item(1).Font.Bold = $true
# Выравниваем для того, чтобы их содержимое корректно отображалось в ячейке
$UsedRange = $PhysicalDrive.UsedRange
$UsedRange.EntireColumn.AutoFit() | Out-Null
$WorkBook.SaveAs('C:\temp\Report')
$Excel.Quit()
$compname = (get-wmiobject -class win32_computersystem -namespace root/cimv2).Name
new-item -path . -name "$compname.xls" -type file

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question