└── DFSR ├── HISTORY.md ├── LICENSE ├── README.md ├── README-RU.md ├── Get-DFSRObjectDiscovery.ps1 └── Get-DFSRObjectParam.ps1 /DFSR/HISTORY.md: -------------------------------------------------------------------------------- 1 |

1.0.3

2 | 6 |

1.0.2

7 | 11 |

1.0.1

12 | 18 |

1.0.0

19 | First version 20 | -------------------------------------------------------------------------------- /DFSR/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Nikolay Proskuryakov aka Perlestius 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /DFSR/README.md: -------------------------------------------------------------------------------- 1 | Русская версия 2 | 3 |

Template for monitoring Windows hosts with DFS Replication role installed

4 | 5 |

FEATURES

6 | 14 | 15 |

REQUIREMENTS

16 | 24 | 25 |

HOW TO INSTALL

26 | It is assumed that Zabbix server is already deployed and Zabbix Agent is already installed on host 27 |
    28 |
  1. Add Zabbix Agent service account to the local 'Administrators' group on EACH of partner servers. By default, the service runs under SYSTEM account, so, the computer account should be added. Instead, you can create special AD account for Zabbix Agent service and add that account to the local 'Administrators' group on each partner server via group policy 29 |
  2. 30 |
  3. Copy Get-DFSRObjectDiscovery.ps1 and Get-DFSRObjectParam.ps1 files to Zabbix Agent folder
  4. 31 |
  5. Add these lines to Zabbix Agent configuration file (<ZabbixAgentFolder> should be replaced with path to Zabbix Agent folder): 32 |
    33 | UserParameter=dfsr.discovery[*],powershell -NoProfile -ExecutionPolicy Bypass -File "<ZabbixAgentFolder>\Get-DFSRObjectDiscovery.ps1" "$1" 34 | 35 |
    36 | 37 | UserParameter=dfsr.params[*],powershell -NoProfile -ExecutionPolicy Bypass -File "<ZabbixAgentFolder>\Get-DFSRObjectParam.ps1" "$1" "$2" "$3" 38 | 39 |
  6. 40 |
  7. Restart Zabbix Agent service
  8. 41 |
  9. This point is for Zabbix 2.X only, because the template for Zabbix 3.X and above has these mappings included 42 |
    43 | Add value mappings listed below:
    44 | DFSR::ConnectionState
    45 | 0 ⇒ Connecting
    46 | 1 ⇒ Online
    47 | 2 ⇒ Offline
    48 | 3 ⇒ In Error
    49 |
    50 | DFSR::RFState
    51 | 0 ⇒ Uninitialized
    52 | 1 ⇒ Initialized
    53 | 2 ⇒ Initial Sync
    54 | 3 ⇒ Auto Recovery
    55 | 4 ⇒ Normal
    56 | 5 ⇒ In Error
    57 |
    58 | DFSR::ServiceState
    59 | 0 ⇒ Starting
    60 | 1 ⇒ Running
    61 | 2 ⇒ Degraded
    62 | 3 ⇒ Shutting Down
    63 | 100 ⇒ Stopped
    64 | 101 ⇒ Not Found
    65 |
    66 | DFSR::VolumeState
    67 | 0 ⇒ Initialized
    68 | 1 ⇒ Shutting Down
    69 | 2 ⇒ In Error
    70 | 3 ⇒ Auto Recovery
    71 |
  10. 72 |
  11. Import the template to Zabbix server: 73 | 77 |
  12. 78 |
  13. Add the template to DFSR hosts
  14. 79 |
  15. (Optional). Enable disabled items and item prototypes you need
  16. 80 |
81 | 82 |

KNOWN ISSUES

83 | Zabbix agent stops collecting performance counters for replicated folders and generates "Cannot obtain performance information from collector" errors. It usually happens after restarting DFS Replication service or after starting host backup procedure. The reason is unknown. Workaround: restart Zabbix Agent service. 84 | 85 |

FEEDBACK

86 | It's better to use GitHub. Also, you can communicate with me via email: nproskuryakov[@]gmail[.]com 87 | 88 |

DONATE

89 |

The template is free. Nevertheless, if you are generous person, I will be pleased to receive your "thank$" :)

90 |

WMID 927723224795
WebMoney

91 | 92 |

PayPal

93 | -------------------------------------------------------------------------------- /DFSR/README-RU.md: -------------------------------------------------------------------------------- 1 | English version 2 |

Шаблон для мониторинга Windows-серверов с ролью DFS Replication

3 | 4 |

ОСОБЕННОСТИ

5 | 13 | 14 |

ТРЕБОВАНИЯ

15 | 23 | 24 |

УСТАНОВКА

25 | Предполагается, что сервер Zabbix уже развернут и на хостах установлен Zabbix Agent 26 |
    27 |
  1. Предоставьте учетной записи, от имени которой работает служба Zabbix Agent, права локального администратора на КАЖДОМ из серверов-партнеров. По умолчанию служба настроена на запуск от имени встроенной учетной записи SYSTEM, т.е. права нужно будет выдавать доменной учетной записи компьютера. Более удобным вариантом будет создание в Active Directory специальной учетной записи для службы Zabbix Agent и включение ее в локальную группу "Администраторы" каждого из DFSR-серверов. Последнее можно сделать централизованно с помощью групповой политики 28 |
  2. 29 |
  3. Скопируйте файлы Get-DFSRObjectDiscovery.ps1 и Get-DFSRObjectParam.ps1 в папку с установленным Zabbix Agent
  4. 30 |
  5. Добавьте в конфигурационный файл агента Zabbix строки, заменив <ZabbixAgentFolder> на путь к папке с Zabbix Agent: 31 |
    32 | UserParameter=dfsr.discovery[*],powershell -NoProfile -ExecutionPolicy Bypass -File "<ZabbixAgentFolder>\Get-DFSRObjectDiscovery.ps1" "$1" 33 | 34 |
    35 | 36 | UserParameter=dfsr.params[*],powershell -NoProfile -ExecutionPolicy Bypass -File "<ZabbixAgentFolder>\Get-DFSRObjectParam.ps1" "$1" "$2" "$3" 37 | 38 |
  6. 39 |
  7. Перезапустите службу Zabbix Agent
  8. 40 |
  9. Этот пункт только для Zabbix версий 2.X, т.к. шаблон для версий 3.X и выше уже содержит все необходимые наборы для преобразования значений 41 |
    42 | Создайте следующие наборы преобразования значений:
    43 | DFSR::ConnectionState
    44 | 0 ⇒ Connecting
    45 | 1 ⇒ Online
    46 | 2 ⇒ Offline
    47 | 3 ⇒ In Error
    48 |
    49 | DFSR::RFState
    50 | 0 ⇒ Uninitialized
    51 | 1 ⇒ Initialized
    52 | 2 ⇒ Initial Sync
    53 | 3 ⇒ Auto Recovery
    54 | 4 ⇒ Normal
    55 | 5 ⇒ In Error
    56 |
    57 | DFSR::ServiceState
    58 | 0 ⇒ Starting
    59 | 1 ⇒ Running
    60 | 2 ⇒ Degraded
    61 | 3 ⇒ Shutting Down
    62 | 100 ⇒ Stopped
    63 | 101 ⇒ Not Found
    64 |
    65 | DFSR::VolumeState
    66 | 0 ⇒ Initialized
    67 | 1 ⇒ Shutting Down
    68 | 2 ⇒ In Error
    69 | 3 ⇒ Auto Recovery
    70 |
  10. 71 | 72 |
  11. Импортируйте шаблон мониторинга на сервер Zabbix: 73 | 77 |
  12. 78 |
  13. Добавьте шаблон к хостам с ролью DFSR
  14. 79 |
  15. (Опционально). Включите отключенные по умолчанию метрики (правила обнаружения, элементы данных, прототипы элементов), которые вам необходимы
  16. 80 |
81 | 82 |

ИЗВЕСТНЫЕ ПРОБЛЕМЫ

83 | Агент Zabbix перестает получать данные счетчиков производительности для реплицируемых папок и генерирует ошибки "Cannot obtain performance information from collector". Такое поведение замечено после перезапуска службы "Репликация DFS" и после запуска резервного копирования хоста. Причина пока не найдена. Временное решение - перезапуск службы Zabbix Agent. 84 | 85 |

ОБРАТНАЯ СВЯЗЬ

86 | Предпочтительнее использовать GitHub, также можете писать на email: nproskuryakov<собака>gmail[.]com 87 | 88 |

ОТБЛАГОДАРИТЬ

89 |

Шаблон распространяется бесплатно, но если Вы человек щедрый, можете поддержать материально - мне будет приятно.

90 |

WMID 927723224795
WebMoney

91 | 92 |

PayPal

93 | -------------------------------------------------------------------------------- /DFSR/Get-DFSRObjectDiscovery.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | #Какой тип объектов собираем 3 | [parameter(Mandatory=$true, Position=0)][String]$ObjectType 4 | ) 5 | 6 | [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 7 | 8 | If ($PSVersionTable.PSVersion.Major -lt 3) { 9 | "The script requires PowerShell version 3.0 or above" 10 | Break 11 | } 12 | If (!(Get-WindowsFeature FS-DFS-Replication).Installed) { 13 | "DFS Replication role not installed" 14 | Break 15 | } 16 | 17 | $ErrorActionPreference = "Continue" 18 | 19 | Set-Variable DFSNamespace -Option ReadOnly -Value "root\MicrosoftDfs" -ErrorAction Ignore 20 | 21 | $Data = @() 22 | 23 | #В зависимости от типа объекта собираем и возвращаем соответствующие данные в JSON 24 | Switch($ObjectType) { 25 | #Счетчики производительности для реплицируемых папок 26 | "RFPerfCounter" { 27 | #Находим в реестре первый номер счетчика, относящегося к объекту "Реплицированные папки DFS" (DFS Replicated Folders) 28 | #(Номера генерируются системой и индивидуальны для каждого сервера) 29 | #Этими номерами будет оперировать заббикс 30 | $PerfObjectRegKey = "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers\{d7b456d4-ca82-4080-a5d0-27fe1a27a851}\{bfe2736b-c79f-4f36-bd15-2897a1a91d4a}" 31 | $PerfObjectID = (Get-ItemProperty -Path $PerfObjectRegKey -Name "First Counter")."First Counter" 32 | #Получаем список экземпляров для объекта RF (т.е. список папок DFSR, для которых есть счетчики) 33 | Get-WmiObject -Class Win32_PerfFormattedData_Dfsr_DFSReplicatedFolders | ForEach-Object { 34 | #Экземпляр (в нашем случае это RF), с которого собираются данные счетчиков, имеет вид RFName-{RFID} 35 | #Вычленяем из него идентификатор и имя RF 36 | $RFName = $_.Name.Substring(0, $_.Name.IndexOf('-{')) 37 | $RFID = $_.Name.Substring($_.Name.IndexOf('-{') + 2, $_.Name.Length -$_.Name.IndexOf('-{') - 3) 38 | #Находим группу репликации, к которой относится RF 39 | $WMIQuery = "SELECT * FROM DfsrReplicatedFolderInfo WHERE ReplicatedFolderGuid = '$RFID'" 40 | $RGName = (Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery).ReplicationGroupName 41 | 42 | $Entry = [PSCustomObject] @{ 43 | "{#RGNAME}" = $RGName 44 | "{#RFNAME}" = $_.Name.Substring(0, $_.Name.IndexOf('-{')) 45 | "{#RFPERFOBJECTID}" = $PerfObjectID 46 | "{#RFPERFINSTANCEID}" = $_.Name 47 | #Номера счетчиков получаем последовательным увеличением на 2 того номера, который нашли выше 48 | "{#RFPERFCOUNTER1ID}" = $PerfObjectID + 2 # Staging Files Generated 49 | "{#RFPERFCOUNTER2ID}" = $PerfObjectID + 4 # Staging Bytes Generated 50 | "{#RFPERFCOUNTER3ID}" = $PerfObjectID + 6 # Staging Files Cleaned up 51 | "{#RFPERFCOUNTER4ID}" = $PerfObjectID + 8 # Staging Bytes Cleaned up 52 | "{#RFPERFCOUNTER5ID}" = $PerfObjectID + 10 # Staging Space In Use 53 | "{#RFPERFCOUNTER6ID}" = $PerfObjectID + 12 # Conflict Files Generated 54 | "{#RFPERFCOUNTER7ID}" = $PerfObjectID + 14 # Conflict Bytes Generated 55 | "{#RFPERFCOUNTER8ID}" = $PerfObjectID + 16 # Conflict Files Cleaned up 56 | "{#RFPERFCOUNTER9ID}" = $PerfObjectID + 18 # Conflict Bytes Cleaned up 57 | "{#RFPERFCOUNTER10ID}" = $PerfObjectID + 20 # Conflict Space In Use 58 | "{#RFPERFCOUNTER11ID}" = $PerfObjectID + 22 # Conflict Folder Cleanups Completed 59 | "{#RFPERFCOUNTER12ID}" = $PerfObjectID + 24 # File Installs Succeeded 60 | "{#RFPERFCOUNTER13ID}" = $PerfObjectID + 26 # File Installs Retried 61 | "{#RFPERFCOUNTER14ID}" = $PerfObjectID + 28 # Updates Dropped 62 | "{#RFPERFCOUNTER15ID}" = $PerfObjectID + 30 # Deleted Files Generated 63 | "{#RFPERFCOUNTER16ID}" = $PerfObjectID + 32 # Deleted Bytes Generated 64 | "{#RFPERFCOUNTER17ID}" = $PerfObjectID + 34 # Deleted Files Cleaned up 65 | "{#RFPERFCOUNTER18ID}" = $PerfObjectID + 36 # Deleted Bytes Cleaned up 66 | "{#RFPERFCOUNTER19ID}" = $PerfObjectID + 38 # Deleted Space In Use 67 | "{#RFPERFCOUNTER20ID}" = $PerfObjectID + 40 # Total Files Received 68 | "{#RFPERFCOUNTER21ID}" = $PerfObjectID + 42 # Size of Files Received 69 | "{#RFPERFCOUNTER22ID}" = $PerfObjectID + 44 # Compressed Size of Files Received 70 | "{#RFPERFCOUNTER23ID}" = $PerfObjectID + 46 # RDC Number of Files Received 71 | "{#RFPERFCOUNTER24ID}" = $PerfObjectID + 48 # RDC Size of Files Received 72 | "{#RFPERFCOUNTER25ID}" = $PerfObjectID + 50 # RDC Compressed Size of Files Received 73 | "{#RFPERFCOUNTER26ID}" = $PerfObjectID + 52 # RDC Bytes Received 74 | "{#RFPERFCOUNTER27ID}" = $PerfObjectID + 54 # Bandwidth Savings Using DFS Replication 75 | } 76 | $Data += $Entry 77 | } 78 | } 79 | 80 | #Счетчики производительности для DFSR-подключений 81 | "ConPerfCounter" { 82 | #Находим в реестре первый номер счетчика, относящегося к объекту "Подключения репликации DFS" (DFS Replication Connections) 83 | #(Номера генерируются системой и индивидуальны для каждого сервера) 84 | #Этими номерами будет оперировать заббикс 85 | $PerfObjectRegKey = "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers\{d7b456d4-ca82-4080-a5d0-27fe1a27a851}\{a689f9be-38ad-4c17-9d62-ad60492084a7}" 86 | $PerfObjectID = (Get-ItemProperty -Path $PerfObjectRegKey -Name "First Counter")."First Counter" 87 | Get-WmiObject -Class Win32_PerfFormattedData_Dfsr_DFSReplicationConnections | ForEach-Object { 88 | #Получаем список экземпляров для объекта RC (т.е. список подключений DFSR, для которых есть счетчики) 89 | #Экземпляр (в нашем случае это подключение), с которого собираются данные счетчиков, имеет вид SendingParnerFQDN-{RCID} 90 | #Вычленяем из него имя отправляющего сервера-партнера и ID подключения 91 | $SendingPartner = $_.Name.Substring(0, $_.Name.IndexOf('-{')) 92 | $RCID = $_.Name.Substring($_.Name.IndexOf('-{') + 2, $_.Name.Length -$_.Name.IndexOf('-{') - 3) 93 | #Находим группу репликации, к которой относится RC 94 | $WMIQuery = "SELECT * FROM DfsrConnectionInfo WHERE ConnectionGuid = '$RCID'" 95 | $RGName = (Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery).ReplicationGroupName 96 | 97 | $Entry = [PSCustomObject] @{ 98 | "{#RGNAME}" = $RGName 99 | "{#RCPARTNER}" = $SendingPartner 100 | "{#RCPERFOBJECTID}" = $PerfObjectID 101 | "{#RCPERFINSTANCEID}" = $_.Name 102 | #Номера счетчиков получаем последовательным увеличением на 2 того номера, который нашли выше 103 | "{#RCPERFCOUNTER1ID}" = $PerfObjectID + 2 # Total Bytes Received 104 | "{#RCPERFCOUNTER2ID}" = $PerfObjectID + 4 # Total Files Received 105 | "{#RCPERFCOUNTER3ID}" = $PerfObjectID + 6 # Size of Files Received 106 | "{#RCPERFCOUNTER4ID}" = $PerfObjectID + 8 # Compressed Size of Files Received 107 | "{#RCPERFCOUNTER5ID}" = $PerfObjectID + 10 # Bytes Received Per Second 108 | "{#RCPERFCOUNTER6ID}" = $PerfObjectID + 12 # RDC Number of Files Received 109 | "{#RCPERFCOUNTER7ID}" = $PerfObjectID + 14 # RDC Size of Files Received 110 | "{#RCPERFCOUNTER8ID}" = $PerfObjectID + 16 # RDC Compressed Size of Files Received 111 | "{#RCPERFCOUNTER9ID}" = $PerfObjectID + 18 # RDC Bytes Received 112 | "{#RCPERFCOUNTER10ID}" = $PerfObjectID + 20 # Bandwidth Savings Using DFS Replication 113 | } 114 | $Data += $Entry 115 | } 116 | } 117 | 118 | #Счетчики производительности для томов DFSR 119 | "VolPerfCounter" { 120 | #Находим в реестре первый номер счетчика, относящегося к объекту "Тома службы репликации DFS" (DFS Replication Service Volumes) 121 | #(Номера генерируются системой и индивидуальны для каждого сервера) 122 | #Этими номерами будет оперировать заббикс 123 | $PerfObjectRegKey = "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_V2Providers\{d7b456d4-ca82-4080-a5d0-27fe1a27a851}\{3f1707df-6381-4287-affc-a60e109a4d30}" 124 | $PerfObjectID = (Get-ItemProperty -Path $PerfObjectRegKey -Name "First Counter")."First Counter" 125 | #Получаем список DFS Replication Service Volumes 126 | Get-WmiObject -Class Win32_PerfFormattedData_Dfsr_DFSReplicationServiceVolumes | 127 | ForEach-Object { 128 | $RV = [PSCustomObject] @{ 129 | "{#RVNAME}" = $_.Name 130 | "{#RVPERFOBJECTID}" = $PerfObjectID 131 | "{#RVPERFCOUNTER1ID}" = $PerfObjectID + 2 # USN Journal Records Read 132 | "{#RVPERFCOUNTER2ID}" = $PerfObjectID + 4 # USN Journal Records Accepted 133 | "{#RVPERFCOUNTER3ID}" = $PerfObjectID + 6 # USN Journal Unread Percentage 134 | "{#RVPERFCOUNTER4ID}" = $PerfObjectID + 8 # Database Commits 135 | "{#RVPERFCOUNTER5ID}" = $PerfObjectID + 10 # Database Lookups 136 | } 137 | $Data += $RV 138 | } 139 | } 140 | 141 | #Реплицируемые папки, расположенные на сервере 142 | "RF" { 143 | (Get-WmiObject -Namespace $DFSNamespace -Class DfsrReplicatedFolderConfig) | 144 | ForEach-Object { 145 | #Определяем имя группы репликации по ее ID 146 | $RGID = $_.ReplicationGroupGuid 147 | $WMIQuery = "SELECT * FROM DfsrReplicationGroupConfig WHERE ReplicationGroupGuid='$RGID'" 148 | $RGName = (Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery).ReplicationGroupName 149 | $RF = [PSCustomObject] @{ 150 | "{#RFID}" = $_.ReplicatedFolderGuid 151 | "{#RFNAME}" = $_.ReplicatedFolderName 152 | "{#RGNAME}" = $RGName 153 | } 154 | $Data += $RF 155 | } 156 | } 157 | 158 | #Бэклог исходящих файлов для каждой из реплицируемых папок 159 | "RFBacklog" { 160 | #текст-ориентир, с помощью которого будем парсить DN подписки 161 | $ReferenceText = ",CN=DFSR-LocalSettings,CN=" 162 | $RFMembers = @() 163 | #Находим в базе AD все включенные DFSR-подписки, кроме своих 164 | (New-Object DirectoryServices.DirectorySearcher "ObjectClass=msDFSR-Subscription").FindAll() | 165 | Where-Object {($_.Properties.distinguishedname -notlike "*$ReferenceText$env:COMPUTERNAME,*") -and 166 | ($_.Properties."msdfsr-enabled" -eq $true)} | 167 | ForEach-Object { 168 | $SubscriptionDN = $_.Properties.distinguishedname 169 | #имя подписанного сервера заключено в DN-строке между текстом-ориентиром 170 | $TempText = $SubscriptionDN.Substring($SubscriptionDN.LastIndexOf($ReferenceText) + $ReferenceText.Length) 171 | #и запятой 172 | $ComputerName = $TempText.Substring(0, $TempText.IndexOf(",")) 173 | $RFMember = [PSCustomObject]@{ 174 | ComputerName = $ComputerName 175 | RFID = [String]$_.Properties.name 176 | } 177 | $RFMembers += $RFMember 178 | } 179 | #Находим группы, в которые входит локальный сервер 180 | $RGs = Get-WmiObject -Namespace $DFSNamespace -Class DfsrReplicationGroupConfig 181 | ForEach ($RG in $RGs) { 182 | $RGID = $RG.ReplicationGroupGuid 183 | $RGName = $RG.ReplicationGroupName 184 | #Находим исходящие подключения, относящиеся к группе 185 | $WMIQuery = "SELECT * FROM DfsrConnectionConfig WHERE ReplicationGroupGuid='$RGID' AND Inbound='False'" 186 | $OutConnections = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 187 | #Находим на этом сервере папки (RF), относящиеся к группе, 188 | # кроме и отключенных и readonly-папок, т.к. у них нет бэклога исходящих файлов 189 | $WMIQuery = "SELECT * FROM DfsrReplicatedFolderConfig "+ 190 | "WHERE ReplicationGroupGuid='$RGID' AND Enabled='True' AND ReadOnly='False'" 191 | $RFs = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 192 | #Проверяем наличие этих папок на каждом из принимающих партнеров группы 193 | ForEach ($Connection in $OutConnections) { 194 | ForEach ($RF in $RFs) { 195 | $RFID = $RF.ReplicatedFolderGuid 196 | $RFName = $RF.ReplicatedFolderName 197 | #Если принимающий партнер содержит папку, будем создаем метрику для соответствующего бэклога 198 | ForEach ($RFMember in $RFMembers) { 199 | If (($RFMember.RFID -eq $RFID) -and ($RFMember.ComputerName -eq $Connection.PartnerName)) { 200 | $Entry = [PSCustomObject] @{ 201 | "{#RGNAME}" = $RGName 202 | "{#RFNAME}" = $RFName 203 | "{#RFID}" = $RFID 204 | "{#SSERVERNAME}" = $env:COMPUTERNAME 205 | "{#RSERVERID}" = $Connection.PartnerGuid 206 | "{#RSERVERNAME}" = $Connection.PartnerName 207 | } 208 | $Data += $Entry 209 | } 210 | } 211 | } 212 | } 213 | } 214 | } 215 | #Подключения для групп репликации 216 | "Connection" { 217 | Get-WmiObject -Namespace $DFSNamespace -Class DfsrConnectionConfig | 218 | ForEach-Object { 219 | #Определяем имя группы репликации по ее ID 220 | $RGID = $_.ReplicationGroupGuid 221 | $WMIQuery = "SELECT * FROM DfsrReplicationGroupConfig WHERE ReplicationGroupGuid='$RGID'" 222 | $RGName = (Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery).ReplicationGroupName 223 | If ($_.Inbound) { 224 | $SendingServer = $_.PartnerName 225 | $ReceivingServer = $env:COMPUTERNAME 226 | } 227 | Else { 228 | $SendingServer = $env:COMPUTERNAME 229 | $ReceivingServer = $_.PartnerName 230 | } 231 | $Connection = [PSCustomObject] @{ 232 | "{#CONNECTIONID}" = $_.ConnectionGuid 233 | "{#RGNAME}" = $RGName 234 | "{#SSERVERNAME}" = $SendingServer 235 | "{#RSERVERNAME}" = $ReceivingServer 236 | } 237 | $Data += $Connection 238 | } 239 | } 240 | 241 | #Группы репликации 242 | "RG" { 243 | Get-WmiObject -Namespace $DFSNamespace -Class DfsrReplicationGroupConfig | 244 | ForEach-Object { 245 | $RG = [PSCustomObject] @{ 246 | "{#RGID}" = $_.ReplicationGroupGuid 247 | "{#RGNAME}" = $_.ReplicationGroupName 248 | } 249 | $Data += $RG 250 | } 251 | } 252 | 253 | #Тома, на которых хранятся реплицируемые папки 254 | "Volume" { 255 | Get-WmiObject -Namespace $DFSNamespace -Class DfsrVolumeConfig | 256 | ForEach-Object { 257 | $Volume = [PSCustomObject] @{ 258 | "{#VOLUMEID}" = $_.VolumeGuid 259 | #Путь изначально возвращается в UNC-формате, поэтому обрезаем начальные символы 260 | "{#VOLUMENAME}" = $_.VolumePath.TrimStart("\\.\") 261 | } 262 | $Data += $Volume 263 | } 264 | } 265 | 266 | #Партнеры по группам репликации 267 | "Partner" { 268 | #Находим группы репликации 269 | Get-WmiObject -Namespace $DFSNamespace -Class DfsrReplicationGroupConfig | 270 | ForEach-Object { 271 | $RGID = $_.ReplicationGroupGuid 272 | $RGName = $_.ReplicationGroupName 273 | #и в каждой группе находим партнеров 274 | $WMIQuery = "SELECT * FROM DfsrConnectionConfig WHERE ReplicationGroupGuid='$RGID'" 275 | Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery | 276 | Select-Object PartnerGuid, PartnerName -Unique | ForEach-Object { 277 | $Partner = [PSCustomObject] @{ 278 | "{#PARTNERID}" = $_.PartnerGuid 279 | "{#PARTNERNAME}" = $_.PartnerName 280 | "{#RGNAME}" = $RGName 281 | #Учетная запись, от имени которой работает служба Zabbix Agent 282 | "{#NTACCOUNT}" = "$env:USERDOMAIN\$env:USERNAME" 283 | } 284 | $Data += $Partner 285 | } 286 | } 287 | } 288 | } 289 | 290 | $JSONOutput = @{"data" = $Data} | ConvertTo-Json -Compress 291 | [Console]::WriteLine($JSONOutput) 292 | 293 | -------------------------------------------------------------------------------- /DFSR/Get-DFSRObjectParam.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | #Объект мониторинга, для которого будем возвращать метрики 3 | [parameter(Mandatory=$true, Position=0)][String]$Object, 4 | #Дополнительные параметры, на основании которых будет возвращать метрики для объекта 5 | [parameter(Mandatory=$false, Position=1)]$Param1, 6 | [parameter(Mandatory=$false, Position=2)]$Param2 7 | ) 8 | 9 | Set-Variable DFSNamespace -Option ReadOnly -Value "root\MicrosoftDfs" -ErrorAction Ignore 10 | 11 | Set-Variable RoleNotInstalledText -Option ReadOnly -Value "DFS Replication role not installed" -ErrorAction Ignore 12 | 13 | #Параметры локализации (чтобы разделителем целой и дробной части была точка, т.к. запятую заббикс не поймет) 14 | $USCulture = [System.Globalization.CultureInfo]::GetCultureInfo("en-US") 15 | [System.Threading.Thread]::CurrentThread.CurrentCulture = $USCulture 16 | 17 | <# 18 | #Тайм-аут для получения значения (должен быть меньше таймаута в настройках заббикс-агента) 19 | С помощью этого параметра ограничиваем время опроса партнеров: 20 | Учитывая, что обычно опрос недоступного партнера занимает до 20с, 21 | а Timeout для заббикс-агента обычно меньше (3с по умолчанию), 22 | мы ограничиваем время опроса в самом скрипте, чтобы заббикс-агент не получил NoData из-за таймаута 23 | Это позволит вместо NoData вернуть значение, либо текст ошибки 24 | #> 25 | Set-Variable RequestTimeout -Option ReadOnly -Value 2 -ErrorAction Ignore 26 | 27 | If ($PSVersionTable.PSVersion.Major -lt 3) { 28 | "The script requires PowerShell version 3.0 or above" 29 | Break 30 | } 31 | 32 | $DFSRRoleInstalled = (Get-WindowsFeature FS-DFS-Replication).Installed 33 | 34 | $ErrorActionPreference = "Continue" 35 | 36 | Switch($Object) { 37 | "RoleInstalled" { 38 | $DFSRRoleInstalled 39 | } 40 | "ServiceState" { 41 | $DFSRService = Get-Service DFSR -ErrorAction Ignore 42 | If ($DFSRService) { 43 | If ($DFSRService.Status -eq "Running") { 44 | (Get-WmiObject -Namespace $DFSNamespace -Class DfsrInfo).State 45 | } 46 | Else { 47 | #Если служба остановлена 48 | [int]100 49 | } 50 | } 51 | Else { 52 | #Если служба не найдена 53 | [int]101 54 | } 55 | } 56 | 57 | #DFS Replication service version 58 | "ServiceVer" { 59 | $DFSRConfig = Get-WmiObject -Namespace $DFSNamespace -Class DfsrConfig -ErrorAction Ignore 60 | If ($DFSRConfig) { 61 | $DFSRConfig.ServiceVersion 62 | } 63 | Else { 64 | "n/a" 65 | } 66 | } 67 | 68 | #DFS Replication provider version 69 | "ProvVer" { 70 | $DFSRConfig = Get-WmiObject -Namespace $DFSNamespace -Class DfsrConfig -ErrorAction Ignore 71 | If ($DFSRConfig) { 72 | $DFSRConfig.ProviderVersion 73 | } 74 | Else { 75 | "n/a" 76 | } 77 | } 78 | 79 | #DFS Replication monitoring provider version 80 | "MonProvVer" { 81 | $DFSRInfo = Get-WmiObject -Namespace $DFSNamespace -Class DfsrInfo -ErrorAction Ignore 82 | If ($DFSRInfo) { 83 | $DFSRInfo.ProviderVersion 84 | } 85 | Else { 86 | "n/a" 87 | } 88 | } 89 | 90 | "ServiceUptime" { 91 | If (!$DFSRRoleInstalled) { 92 | $RoleNotInstalledText 93 | Break 94 | } 95 | $DFSRInfo = Get-WmiObject -Namespace $DFSNamespace -Class DfsrInfo -ErrorAction Ignore 96 | If ($DFSRInfo) { 97 | #Получаем время запуска службы в WMI-формате 98 | $WMIStartTime = $DFSRInfo.ServiceStartTime 99 | #и преобразуем его в формат DateTime 100 | $StartTime = [Management.ManagementDateTimeConverter]::ToDateTime($WMIStartTime) 101 | (New-TimeSpan -Start $StartTime -End (Get-Date)).TotalSeconds 102 | } 103 | Else { 104 | "n/a" 105 | } 106 | } 107 | 108 | #Реплицируемая папка 109 | "RF" { 110 | If (!$DFSRRoleInstalled) { 111 | $RoleNotInstalledText 112 | Break 113 | } 114 | $RFID = $Param1 115 | $WMIQuery = "SELECT * FROM DfsrReplicatedFolderConfig WHERE ReplicatedFolderGuid='$RFID'" 116 | $RFConfig = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 117 | If (!$RFConfig) { 118 | "RF '$RFID' not found" 119 | Break 120 | } 121 | $RFName = $RFConfig.ReplicatedFolderName 122 | $RGID = $RFConfig.ReplicationGroupGuid 123 | #Статистику можно собирать только с Enabled-папок 124 | If ($RFConfig.Enabled) { 125 | $WMIQuery = "SELECT * FROM DfsrReplicatedFolderInfo WHERE ReplicatedFolderGuid='$RFID'" 126 | $RFInfo = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 127 | } 128 | $ErrorText = "Couldn't retrieve info for disabled RF" 129 | 130 | Switch($Param2) { 131 | "Enabled" { 132 | #Включена ли репликация для папки 133 | $RFConfig.Enabled 134 | } 135 | #Удалять файлы вместо перемещения в папку конфликтов 136 | "RemoveDeleted" { 137 | $RFConfig.DisableSaveDeletes 138 | } 139 | "ReadOnly" { 140 | #Папка работает в режиме "только чтение" 141 | $RFConfig.ReadOnly 142 | } 143 | #Максимальный размер, заданный для промежуточной папки, байт 144 | "StageQuota" { 145 | $RFConfig.StagingSizeInMb*1024*1024 146 | } 147 | #Максимальный размер, заданный для папки ConflictAndDeleted, байт 148 | "ConflictQuota" { 149 | $RFConfig.ConflictSizeInMb*1024*1024 150 | } 151 | "State" { 152 | If ($RFInfo) { 153 | # 0 - Uninitialized, 1 - Initialized, 2 - Initial Sync, 154 | # 3 - Auto Recovery, 4 - Normal, 5 - In Error 155 | $RFInfo.State 156 | } 157 | Else { 158 | "Couldn't retrieve info for disabled RF" 159 | } 160 | } 161 | #Текущий размер промежуточной папки, байт 162 | "StageSize" { 163 | If ($RFInfo) { 164 | $RFInfo.CurrentStageSizeInMb*1024*1024 165 | } 166 | Else { 167 | "Couldn't retrieve info for disabled RF" 168 | } 169 | } 170 | #% свободного места в промежуточной папке 171 | "StagePFree" { 172 | If ($RFInfo) { 173 | ($RFConfig.StagingSizeInMb - $RFInfo.CurrentStageSizeInMb)/ ` 174 | $RFConfig.StagingSizeInMb*100 175 | } 176 | Else { 177 | $ErrorText 178 | } 179 | } 180 | #Текущий размер папки ConflictAndDeleted, байт 181 | "ConflictSize" { 182 | If ($RFInfo) { 183 | $RFInfo.CurrentConflictSizeInMb*1024*1024 184 | } 185 | Else { 186 | $ErrorText 187 | } 188 | } 189 | #% свободного места в папке ConflictAndDeleted 190 | "ConflictPFree" { 191 | If ($RFInfo) { 192 | ($RFConfig.ConflictSizeInMb - $RFInfo.CurrentConflictSizeInMb)/ ` 193 | $RFConfig.ConflictSizeInMb*100 194 | } 195 | Else { 196 | $ErrorText 197 | } 198 | } 199 | #На скольких партнерах имеется копия папки в рабочем состоянии 200 | "Redundancy" { 201 | #Находим партнеров по группе репликации 202 | $WMIQuery = "SELECT * FROM DfsrConnectionConfig WHERE ReplicationGroupGuid='$RGID'" 203 | $PartnersByGroup = (Get-WmiObject ` 204 | -Namespace $DFSNamespace ` 205 | -Query $WMIQuery).PartnerName | Select-Object -Unique 206 | $n = 0 207 | #Проверяем наличие папки, имеющей состояние 'Normal' (4), на каждом из партнеров 208 | ForEach ($Partner in $PartnersByGroup) { 209 | $WMIQuery = "SELECT * FROM DfsrReplicatedFolderInfo " + 210 | "WHERE ReplicatedFolderGuid='$RFID' AND State=4" 211 | #и подсчитываем общее количество таких папок 212 | $j = Get-WmiObject -ComputerName $Partner ` 213 | -Namespace $DFSNamespace ` 214 | -Query $WMIQuery ` 215 | -ErrorAction Ignore -AsJob 216 | [void](Wait-Job $j -Timeout $RequestTimeout) 217 | If ($j.State -eq "Completed") { 218 | $n += @(Receive-Job $j).Count 219 | } 220 | #Если не можем опросить хотя одного партнера, прекращаем опрос и возвращаем ошибку 221 | Else { 222 | $n = -1 223 | "Couldn't retrieve info from partner '$Partner'" 224 | Break 225 | } 226 | } 227 | #Если всё хорошо, возвращаем количество партнеров, хранящих копию папки 228 | If ($n -ge 0) { 229 | $n 230 | } 231 | } 232 | } 233 | } 234 | 235 | "RFBacklog" { 236 | If (!$DFSRRoleInstalled) { 237 | $RoleNotInstalledText 238 | Break 239 | } 240 | $RFID = $Param1 241 | $RServerID = $Param2 #ID принимающего партнера 242 | $WMIQuery = "SELECT * FROM DfsrReplicatedFolderConfig WHERE ReplicatedFolderGuid='$RFID'" 243 | $RFConfig = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 244 | If (!$RFConfig) { 245 | "RF '$RFID' not found" 246 | Break 247 | } 248 | #Находим имя принимающего партнера по ID 249 | $WMIQuery = "SELECT * FROM DfsrConnectionConfig WHERE PartnerGuid='$RServerID' AND Inbound='False'" 250 | $ConnectionConfig = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 251 | If (!$ConnectionConfig) { 252 | "Outbound connection to partner '$RServerID' not found" 253 | Break 254 | } 255 | $RServerName = $ConnectionConfig.PartnerName 256 | #Зная ID папки, находим ее имя и имя группы, которой она принадлежит 257 | $WMIQuery = "SELECT * FROM DfsrReplicatedFolderInfo WHERE ReplicatedFolderGuid='$RFID'" 258 | #Запрашиваем у принимающего партнера информацию о папке 259 | $j = Get-WmiObject -ComputerName $RServerName ` 260 | -Namespace $DFSNamespace ` 261 | -Query $WMIQuery ` 262 | -ErrorAction Ignore -AsJob 263 | [void](Wait-Job $j -Timeout $RequestTimeout) 264 | If ($j.State -eq "Completed") { 265 | Try { 266 | #и пытаемся извлечь с этого партнера вектор версии 267 | $VersionVector = (Receive-Job $j).GetVersionVector().VersionVector 268 | #На отправляющем партнере (т.е. на локальном сервере) определяем размер бэклога для найденного вектора 269 | (Get-WmiObject ` 270 | -Namespace $DFSNamespace ` 271 | -Query $WMIQuery).GetOutboundBacklogFileCount($VersionVector).BacklogFileCount 272 | } 273 | Catch { 274 | If ($VersionVector) { 275 | "Couldn't retrieve backlog info for vector '$VersionVector'" 276 | } 277 | Else { 278 | "Version vector not found" 279 | } 280 | } 281 | } 282 | Else { 283 | "Couldn't retrieve info from partner '$RServerName'" 284 | } 285 | } 286 | 287 | "Connection" { 288 | If (!$DFSRRoleInstalled) { 289 | $RoleNotInstalledText 290 | Break 291 | } 292 | $ConnectionID = $Param1 293 | $WMIQuery = "SELECT * FROM DfsrConnectionConfig WHERE ConnectionGuid='$ConnectionID'" 294 | $ConnectionConfig = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 295 | If (!$ConnectionConfig) { 296 | "Connection '$ConnectionID' not found" 297 | Break 298 | } 299 | Switch($Param2) { 300 | "Enabled" { 301 | $ConnectionConfig.Enabled 302 | } 303 | "State" { 304 | #Статистику можно получить только с enabled-подключений 305 | If ($ConnectionConfig.Enabled) { 306 | $WMIQuery = "SELECT * FROM DfsrConnectionInfo WHERE ConnectionGuid='$ConnectionID'" 307 | $ConnectionInfo = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 308 | If ($ConnectionInfo) { 309 | #0 - Connecting, 1 - Online, 2 - Offline, 3 - In Error 310 | $ConnectionInfo.State 311 | } 312 | Else { 313 | "Coundn't retrieve connection info. Check availability of partner '$($ConnectionConfig.PartnerName)'" 314 | } 315 | } 316 | Else { 317 | "Coundn't retrieve info for disabled connection" 318 | } 319 | } 320 | #Если репликация полностью выключена по расписанию 321 | "BlankSchedule" { 322 | [Int]$s = 0 323 | $ConnectionConfig.Schedule | ForEach-Object { 324 | $s += $_ 325 | } 326 | #Если репликация отключена для каждого часа каждого дня, возвращаем True 327 | [Boolean]($s -eq 0) 328 | } 329 | } 330 | } 331 | 332 | "RG" 333 | { 334 | If (!$DFSRRoleInstalled) { 335 | $RoleNotInstalledText 336 | Break 337 | } 338 | $RGID = $Param1 339 | $WMIQuery = "SELECT * FROM DfsrReplicationGroupConfig WHERE ReplicationGroupGuid='$RGID'" 340 | $RGConfig = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 341 | If (!$RGConfig) { 342 | "RG '$RGID' not found" 343 | Break 344 | } 345 | Switch($Param2) { 346 | #количество папок в группе 347 | "RFCount" { 348 | $WMIQuery = "SELECT * FROM DfsrReplicatedFolderConfig WHERE ReplicationGroupGuid='$RGID'" 349 | @(Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery).Count 350 | } 351 | #количество входящих подключений (в т.ч. disabled) от партнеров группы 352 | "InConCount" { 353 | $WMIQuery = "SELECT * FROM DfsrConnectionConfig WHERE ReplicationGroupGuid='$RGID' AND Inbound='True'" 354 | @(Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery).Count 355 | } 356 | #количество исходящих подключений (в т.ч. disabled) от партнеров группы 357 | "OutConCount" { 358 | $WMIQuery = "SELECT * FROM DfsrConnectionConfig WHERE ReplicationGroupGuid='$RGID' AND Inbound='False'" 359 | @(Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery).Count 360 | } 361 | #Если в дефолтном расписании для группы репликация полностью выключена 362 | "BlankSchedule" { 363 | $WMIQuery = "SELECT * FROM DfsrReplicationGroupConfig WHERE ReplicationGroupGuid='$RGID'" 364 | $RGConfig = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 365 | If ($RGConfig) { 366 | [Int]$s = 0 367 | $RGConfig.DefaultSchedule | ForEach-Object { 368 | $s += $_ 369 | } 370 | #Если репликация отключена для каждого часа каждого дня, возвращаем True 371 | [Boolean]($s -eq 0) 372 | } 373 | } 374 | } 375 | } 376 | 377 | #Количество групп репликации, в которые входит сервер 378 | "RGCount" { 379 | If (!$DFSRRoleInstalled) { 380 | $RoleNotInstalledText 381 | Break 382 | } 383 | @(Get-WmiObject -Namespace $DFSNamespace -Class DfsrReplicationGroupConfig).Count 384 | } 385 | 386 | "Partner" { 387 | If (!$DFSRRoleInstalled) { 388 | $RoleNotInstalledText 389 | Break 390 | } 391 | $PartnerID = $Param1 392 | $WMIQuery = "SELECT * FROM DfsrConnectionConfig WHERE PartnerGuid='$PartnerID'" 393 | $ConnectionConfig = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 394 | If (!$ConnectionConfig) { 395 | "Partner '$PartnerID' not found" 396 | Break 397 | } 398 | $PartnerName = (Get-WmiObject ` 399 | -Namespace $DFSNamespace ` 400 | -Query $WMIQuery).PartnerName | Select-Object -Unique 401 | Switch($Param2) { 402 | "PingCheckOK" { 403 | $CheckResult = Test-Connection -ComputerName $PartnerName ` 404 | -Count 1 -Delay 1 -ErrorAction Ignore 405 | [Boolean]($CheckResult -ne $Null) 406 | } 407 | "WMICheckOK" { 408 | $WMIQuery = "SELECT * FROM DfsrConfig" 409 | $j = Get-WmiObject -ComputerName $PartnerName ` 410 | -Namespace $DFSNamespace ` 411 | -Query $WMIQuery ` 412 | -ErrorAction Ignore -AsJob 413 | [void](Wait-Job $j -Timeout $RequestTimeout) 414 | [Boolean]($j.State -eq "Completed") 415 | } 416 | } 417 | } 418 | 419 | "Volume" { 420 | If (!$DFSRRoleInstalled) { 421 | $RoleNotInstalledText 422 | Break 423 | } 424 | $VolumeID = $Param1 425 | $WMIQuery = "SELECT * FROM DfsrVolumeConfig WHERE VolumeGuid='$VolumeID'" 426 | $VolumeConfig = Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery 427 | If (!$VolumeConfig) { 428 | "Volume '$VolumeID' not found" 429 | Break 430 | } 431 | Switch ($Param2) { 432 | "State" { 433 | $WMIQuery = "SELECT * FROM DfsrVolumeInfo WHERE VolumeGuid='$VolumeID'" 434 | #0 - Initialized, 1 - Shutting Down, 2 - In Error, 3 - Auto Recovery 435 | (Get-WmiObject -Namespace $DFSNamespace -Query $WMIQuery).State 436 | } 437 | } 438 | } 439 | 440 | "Log" { 441 | If (!$DFSRRoleInstalled) { 442 | $RoleNotInstalledText 443 | Break 444 | } 445 | $ErrorActionPreference = "Stop" 446 | Try { 447 | [String]$TimeSpanAsString = $Param2 448 | $EndTime = Get-Date 449 | #Коэффициент для перевода из исходных единиц измерения в секунды 450 | $Multiplier = 1 451 | #Определяем единицы измерения (смотрим последний символ в полученной строке) 452 | $TimeUnits = $TimeSpanAsString[$TimeSpanAsString.Length-1] 453 | #Если единицы не указаны (на конце цифра), 454 | If ($TimeUnits -match "\d") { 455 | #считаем, что получили значение в секундах 456 | $TimeValue = ($TimeSpanAsString -as [Int]) 457 | } 458 | Else { 459 | #Числовое значение получаем, отбросив последний символ строки 460 | $TimeValue = ($TimeSpanAsString.Substring(0, $TimeSpanAsString.Length - 1) -as [Int]) 461 | #Переводим из исходных единиц измерения в секунды 462 | Switch ($TimeUnits) { 463 | "m" {$Multiplier = 60} #минуты 464 | "h" {$Multiplier = 3600} #часы 465 | "d" {$Multiplier = 86400} #дни 466 | "w" {$Multiplier = 604800} #недели 467 | } 468 | } 469 | $StartTime = $EndTime.AddSeconds(-$TimeValue*$Multiplier) 470 | 471 | $Filter = @{ 472 | LogName="DFS Replication" 473 | StartTime=$StartTime 474 | EndTime=$EndTime 475 | } 476 | Switch ($Param1) { 477 | "WarnCount" {$Filter += @{Level=3}} 478 | "ErrCount" {$Filter += @{Level=2}} 479 | "CritCount" {$Filter += @{Level=1}} 480 | } 481 | @(Get-WinEvent -FilterHashtable $Filter -ErrorAction Ignore).Count 482 | } 483 | Catch { 484 | $Error[0].Exception.Message 485 | } 486 | } 487 | } 488 | --------------------------------------------------------------------------------