Форум программистов, компьютерный форум, киберфорум
Наши страницы
PowerShell
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.56/9: Рейтинг темы: голосов - 9, средняя оценка - 4.56
Zackovich
0 / 0 / 0
Регистрация: 09.10.2014
Сообщений: 23
1

Создание PsCustomObject

11.07.2019, 15:27. Просмотров 1852. Ответов 8
Метки нет (Все метки)

Доброго времени суток, форумчане.

Подскажите пожалуйста, как можно создать грамотно кастомный объект. Имеется скрипт по сбору информации о мониторах, следующего вида:

PowerShell
1
2
3
4
5
6
7
8
9
10
11
$Monitor = gwmi wmimonitorid -namespace root\wmi -ComputerName $comp
    $Monitor | %{
    $psObject = New-Object PSObject
    $psObject | Add-Member NoteProperty SerialNumber ""
    $psObject | Add-Member NoteProperty Name ""
    $psObject | Add-Member NoteProperty WorkstationName ""
    $psObject.SerialNumber = ($_.SerialNumberID -ne 0 | %{[char]$_}) -join ""
    $psObject.Name = ($_.UserFriendlyName -ne 0 | %{[char]$_}) -join ""
    $psObject.WorkstationName = $_.PSComputerName
    $psObject
    }
Мне бы хотелось его привести к виду DataGridView. В принципе, в таком виде - все отлично работает, но вопрос в том, как можно подцепить другие данные 4-ым столбцом? Например, серийник ПК, без создания дублирующихся записей и чтобы при опросе нескольких компьютеров они отделялись друг от друга.

Единственный вариант, который я смог предположить - наследования одного объекта к другому, но получается сильно громоздко. Возможно есть какой-нибудь более простой путь?

И еще один небольшой вопросик: читал, что add-member работает медленно и рекомендуется создавать объекты другими способами. Исходя из данной задачи, можно как то оптимизировать код?
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.07.2019, 15:27
Ответы с готовыми решениями:

Создать базу данных с(Создание функции БД, Создание процедуры БД, Создание тригера БД)
В задание для курсовой работы по БД входят вот такие пункты: 1.2 Создание функции БД. 1.3...

Хочу освоить и применить на практике создание локальной сети, создание домена
Доброго времени суток. Господа, на днях начал осваиваю win server 2003. Хочу освоить и применить...

Создание БД учет заявок на доступ к информационным ресурсам: создание отчетов
Доброго времени суток. Это всего вторая моя попытка что-то наваять в MS Access, сильно не...

Создание локальной БД. Создание класса для работы с БД. Ошибка подключения к БД
Доброго времени суток! Нужно создать БД и создать класс для работы с ним - методы: добавление,...

Создание кода из строк или создание произвольного количества объектов
Привет сообществу. Возник такой вопрос: Мне в мидлете необходимо создать некоторое количество...

8
v_svitere
697 / 408 / 134
Регистрация: 03.06.2009
Сообщений: 1,189
Записей в блоге: 4
11.07.2019, 15:51 2
Лучший ответ Сообщение было отмечено Zackovich как решение

Решение

Zackovich,
PowerShell
1
2
3
4
5
6
7
8
9
10
$Monitors = gwmi wmimonitorid -namespace root\wmi -ComputerName $comp
$report=@()
$Monitors | %{
    $PS=New-Object PSobject
    $PS|Add-Member -Type NoteProperty -Name "SerialNumber" -Value (($_.SerialNumberID -ne 0) -join "")
    $PS|Add-Member -Type NoteProperty -Name "Name" -Value (($_.UserFriendlyName -ne 0) -join "")
    $PS|Add-Member -Type NoteProperty -Name "WorkstationName " -Value ($_.PSComputerName)
    $report+=$PS
    }
$report|select -Uni *, @{Name = 'Serial'; Expression = {"Myserial"}}
Отделять можно через Group-object

Добавлено через 1 минуту
В expression описываете логику нужного вам атрибута
1
KDE777
1535 / 977 / 387
Регистрация: 22.01.2016
Сообщений: 2,730
11.07.2019, 17:17 3
Лучший ответ Сообщение было отмечено Zackovich как решение

Решение

Цитата Сообщение от Zackovich Посмотреть сообщение
Подскажите пожалуйста, как можно создать грамотно кастомный объект. Имеется скрипт по сбору информации о мониторах
Вот пример, который собирает информацию одновременно со всех указанных AD ПК и в него легко добавить любые нужные данные:

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
$OU      = 'OU=Clients,DC=mydomain,DC=ru'
$CSV_Out = 'C:\Temp\report.csv'
 
$result = Get-ADComputer -SearchBase $OU -Filter {operatingSystem -like 'Windows *'} | select -ExpandProperty DNSHostName | ForEach {
 
Start-Job -ArgumentList $_ -ScriptBlock {
 
    $comp = $args[0]
 
    $obj = [PScustomObject][ordered]@{
        'PC_Name'      = $comp
        'PC_Status'    = ''
        'PC_OS'        = ''
        'PC_RAM'       = ''
        'PC_CPU'       = ''
        'Monitor_Name' = ''
        'Monitor_SN'   = ''
    }
        
    try
    {
        $OS      = Get-WmiObject -Comp $comp -ClassName Win32_OperatingSystem -ErrorAction Stop
        $CPU     = Get-WmiObject -Comp $comp -ClassName Win32_Processor
        $Monitor = Get-WmiObject -Comp $comp -Class WMIMonitorID -Namespace root\wmi
 
        $obj.PC_Name      = $OS.PSComputerName
        $obj.PC_Status    = 'OK'
        $obj.PC_OS        = $OS.Caption
        $obj.PC_RAM       = [math]:: Round($OS.TotalVisibleMemorySize/1MB,2)
        $obj.PC_CPU       = $CPU.Name
        $obj.Monitor_Name = ($Monitor.UserFriendlyName -ne 0 | ForEach {[char]$_}) -join ""
        $obj.Monitor_SN   = ($Monitor.SerialNumberID -ne 0 | ForEach {[char]$_}) -join ""
 
    }
    catch {$obj.PC_Status = 'WMI не доступен'}
    
    $obj
 
}} | Get-Job | Receive-Job -Wait
 
Get-Job | Remove-Job -Force
 
$result | select * -ExcludeProperty RunspaceId,PSSourceJobInstanceId | Out-GridView
$result | select * -ExcludeProperty RunspaceId,PSSourceJobInstanceId | Export-Csv -Path $CSV_Out -Encoding UTF8 -Delimiter ';' -NoTypeInformation
Добавлено через 18 минут
+ совсем простой пример (без джобов, трай/кетч и AD):

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$result = Get-Content -Path 'C:\data\computers.txt' -Encoding UTF8 | ForEach {
 
    $comp = $_
 
    if (-not ($OS = Get-WmiObject -Comp $comp -ClassName Win32_OperatingSystem -ErrorAction SilentlyContinue)) {Return}
    
    $CPU     = Get-WmiObject -Comp $comp -ClassName Win32_Processor
    $Monitor = Get-WmiObject -Comp $comp -Class WMIMonitorID -Namespace root\wmi
 
    [PScustomObject]@{
        'PC_Name'      = $OS.PSComputerName
        'PC_OS'        = $OS.Caption
        'PC_RAM'       = [math]:: Round($OS.TotalVisibleMemorySize/1MB,2)
        'PC_CPU'       = $CPU.Name
        'Monitor_Name' = ($Monitor.UserFriendlyName -ne 0 | ForEach {[char]$_}) -join ""
        'Monitor_SN'   = ($Monitor.SerialNumberID -ne 0 | ForEach {[char]$_}) -join ""
    }
 
}
 
$result | Out-GridView
$result | Export-Csv -Path 'C:\data\report.csv' -Encoding UTF8 -Delimiter ';' -NoTypeInformation
1
Zackovich
0 / 0 / 0
Регистрация: 09.10.2014
Сообщений: 23
11.07.2019, 17:46  [ТС] 4
Спасибо большое, но в моем случае из AD не получиться.

Потому что идея в ручном вводе по IP или имени ПК, да и графический интерфейс под WinForms.
Не всем удобно смотреть файлики или читать консоль.

Еще раз большое всем спасибо за ответы, теперь я знаю еще чуточку больше
0
11.07.2019, 17:46
alhaos
51 / 39 / 13
Регистрация: 20.02.2019
Сообщений: 154
12.07.2019, 08:11 5
"Альтернативный" вариант

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class monitor{
    [string]$SerialNumber
    [string]$Name
    [string]$WorkstationName
 
    monitor($s, $n, $W)
    {
        $this.SerialNumber = $s
        $this.Name = $n
        $this.WorkstationName = $w
    }
}
$monitors = @()
gwmi wmimonitorid -namespace root\wmi -ComputerName $comp| %{
    $monitors += [monitor]::new(
        (($_.SerialNumberID -ne 0 | %{[char]$_}) -join ""),
        (($_.UserFriendlyName -ne 0 | %{[char]$_}) -join ""),
        $_.PSComputerName)
}
 
$monitors | ogv
1
KDE777
1535 / 977 / 387
Регистрация: 22.01.2016
Сообщений: 2,730
12.07.2019, 10:31 6
Цитата Сообщение от alhaos Посмотреть сообщение
"Альтернативный" вариант
А зачем столько кода для примера, который выбирает несколько свойств из вывода одного gwmi? Разве простого selecta для этого не достаточно?

PowerShell
1
2
3
4
$monitors = Get-WmiObject WMIMonitorID -Namespace root\wmi -ComputerName $comp | Select `
    @{N='WorkstationName'; E={$_.PSComputerName}},
    @{N='Name';            E={($_.UserFriendlyName -ne 0 | %{[char]$_}) -join ""}},
    @{N='SerialNumber';    E={($_.SerialNumberID -ne 0 | %{[char]$_}) -join ""}}
1
alhaos
51 / 39 / 13
Регистрация: 20.02.2019
Сообщений: 154
12.07.2019, 12:34 7
Цитата Сообщение от KDE777 Посмотреть сообщение
А зачем столько кода для примера
как раз этого, для примера, может человек, что подчеркнет для себя, захочет поиграться с конструкторами или метод какой напишет
0
Zackovich
0 / 0 / 0
Регистрация: 09.10.2014
Сообщений: 23
15.07.2019, 11:59  [ТС] 8
Ребят, не хотелось бы создавать еще одну тему.. Возможно сможете подсказать, как поместить массив в текстбокс, чтобы можно было указывать несколько компьютеров в строке ввода?

Как переделать функцию для консольного варианта - я знаю, а вот с Textbox немного вошел в тупик.

Я так понимаю, что надо изменить $comp.text = "", где сейчас идет приведение к строке.

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
Add-Type -AssemblyName System.Windows.Forms 
[System.Windows.Forms.Application]::EnableVisualStyles()
 
$Table                           = New-Object System.Windows.Forms.Form
$Table.Size                      = New-Object System.Drawing.Size(600, 300)
$Table.TopMost                   = $true
$Table.StartPosition             = "CenterScreen"
 
$Table.KeyPreview = $True
$Table.Add_KeyDown({if ($_.KeyCode -eq "Enter") 
    {
    $OKButton.PerformClick()
    }
})
$Table.Add_KeyDown({if ($_.KeyCode -eq "Escape") 
    {
    $Table.Close()
    }
})
 
$DGV                             = New-Object System.Windows.Forms.DataGridView
$DGV.Size                        = New-Object System.Drawing.Size(600, 200) 
$Table.Controls.Add($DGV)
 
 
$comp                        = New-Object system.Windows.Forms.TextBox
$comp.width                  = 150
$comp.height                 = 20
$comp.location               = New-Object System.Drawing.Point(0,220)
$comp.Text                   = ""
$Table.Controls.Add($comp) 
 
$Column1 = New-Object System.Windows.Forms.DataGridViewTextboxColumn
$Column2 = New-Object System.Windows.Forms.DataGridViewTextboxColumn
$Column3 = New-Object System.Windows.Forms.DataGridViewTextboxColumn
$Column4 = New-Object System.Windows.Forms.DataGridViewTextBoxColumn
$Column5 = New-Object System.Windows.Forms.DataGridViewTextBoxColumn
$Column5.Width = 150
 
[void]$DGV.Columns.Add($Column1)
[void]$DGV.Columns.Add($Column2)
[void]$DGV.Columns.Add($Column3)
[void]$DGV.Columns.Add($Column4)
[void]$DGV.Columns.Add($Column5)
 
$DGV.Columns[0].Name = "Серийный номер монитора"
$DGV.Columns[1].Name = "Модель монитора"
$DGV.Columns[2].Name = "Имя ПК"
$DGV.Columns[3].Name = "Серийный номер ПК"
$DGV.Columns[4].Name = "Жесткий диск"
 
Function Get-SNMonitor {
$DGV.Rows.Clear()
$Monitors = gwmi wmimonitorid -namespace root\wmi -ComputerName $comp.text
$report=@()
$Monitors | %{
    $PS=New-Object PSobject
    $PS|Add-Member -Type NoteProperty -Name "SerialNumber" -Value (($_.SerialNumberID -ne 0 | %{[char]$_}) -join "")
    $PS|Add-Member -Type NoteProperty -Name "Name" -Value (($_.UserFriendlyName -ne 0| %{[char]$_}) -join "")
    $report+=$PS
    }
$report|select -Uni *,`
 @{Name = 'SerialPC'; Expression = {(gwmi Win32_Bios -ComputerName $comp.text).SerialNumber}},
 @{Name = 'ModelPC'; Expression = {(gwmi Win32_ComputerSystem -ComputerName $comp.text).Model}},
 @{Name = 'PCName'; Expression = {(gwmi Win32_ComputerSystem -ComputerName $comp.text).PSComputerName}},
 @{Name="ModelHardDrive";Expression={(gwmi Win32_DiskDrive -ComputerName $comp.text).Model}} | foreach {$DGV.rows.Add($_.SerialNumber, $_.Name,$_.PCNAme, $_.SerialPC, $_.ModelHardDrive)}
    }
   
 
$OKButton                       = New-Object System.Windows.Forms.Button
$OKButton.Location              = New-Object System.Drawing.Size(150,218)
$OKButton.Text                  = "Поиск"
$OKButton.AutoSize              = $True
$OKButton.Add_Click({
if ([bool] (Test-Connection -ComputerName $comp.Text -Count 1 -Quiet) -eq $true)
{
Get-SNMonitor
}
else 
{
[System.Windows.Forms.MessageBox]::Show("Компьютер пользователя выключен или недоступен" , "ПК Недоступен")
}
}
)
$Table.Controls.Add($OKButton)
 
[void]$Table.ShowDialog()
0
v_svitere
697 / 408 / 134
Регистрация: 03.06.2009
Сообщений: 1,189
Записей в блоге: 4
15.07.2019, 12:31 9
Zackovich, Из простых вариантов, сделать разделитель, например запятую. При клике на кнопку, делать split текста, по запятой, и обрабатывать полученную коллекцию в цикле.

Если делаете Gui-обертку, то лучше делайте WPF, это в разы удобнее. В студии отрисовываете интрефейс и просто копируете его в скрипт. Гораздо лучше, чем описывать каждый контрол
0
15.07.2019, 12:31
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.07.2019, 12:31

Создание базы данных на лету, создание и заполнение таблиц в базе DB (Paradox? или..).
Здравствуйте Профи! --- Видел я "простенькую" (exe-шник небольшого размера, запускается сразу,...

Создание формулы и последующее заполнение таблицы, избежание повторов информации, создание интерфейса
Не люблю просить о помощи, но, к сожалению, сроки поджимают и не позволяют подробно ознакомиться с...

Создание источника данных, создание серверных страниц и выбор WEB-сервера и его установка
на практике попросили сделать задание. 1)Создание источника данных 2)Создание серверных страниц...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru