├── Autotask ├── New-ATWSQuery function.ps1 └── atws-RateUpdate.ps1 ├── Azure └── Access-StorageContext.ps1 ├── LICENSE ├── MAXfocus ├── Enable-HardwareEvents.ps1 ├── Install-ApplicationsFromMAXfocus.ps1 ├── MAXfocus_PatchSettings.ps1 ├── README Verify-MAXfocusConfig.md ├── README.md ├── ReadRecoveryOptions.ps1 ├── Set-RebootSchedule.ps1 ├── Verify-MAXfocusConfig.ps1 └── Verify-MAXfocusVMwareChecks.ps1 ├── README.md ├── Resources ├── README.txt ├── script_1024_28.vbs ├── script_1024_29.vbs ├── script_1024_30.vbs ├── script_1024_32.vbs ├── script_1024_33.vbs ├── script_1024_34.ps1 ├── script_1024_35.ps1 ├── script_1024_38.ps1 └── script_1024_39.ps1 ├── SNMP ├── MAXFocus_SNMP_Checks.ps1 ├── README.txt └── lib │ ├── SNMP-Funcs.ps1 │ └── SharpSnmpLib.dll ├── XML └── Remove-XMLDuplicates.ps1 └── klemmestad.no └── Get-ValutaKurser.ps1 /Autotask/New-ATWSQuery function.ps1: -------------------------------------------------------------------------------- 1 | # A small QueryXML function I got from Jon Czerwinski in an autotask forum 2 | # https://community.autotask.com/forums/p/15090/38343.aspx#38343 3 | # I have modified it to handle more fields and expressions 4 | 5 | function New-ATWSQuery { 6 | [CmdletBinding()] 7 | param( 8 | [Parameter(Position=0,Mandatory=$true)] 9 | [string]$Entity, 10 | [Parameter(Position=1,Mandatory=$true)] 11 | [string]$Field, 12 | [Parameter(Position=2,Mandatory=$false)] 13 | [string]$Expression, 14 | [Parameter(Position=3,Mandatory=$false)] 15 | [string]$Value, 16 | [Parameter(Position=4,Mandatory=$false)] 17 | [string]$Field2, 18 | [Parameter(Position=5,Mandatory=$false)] 19 | [string]$Expression2, 20 | [Parameter(Position=6,Mandatory=$false)] 21 | [string]$Value2, 22 | [Parameter(Position=7,Mandatory=$false)] 23 | [string]$Field3, 24 | [Parameter(Position=8,Mandatory=$false)] 25 | [string]$Expression3, 26 | [Parameter(Position=9,Mandatory=$false)] 27 | [string]$Value3, 28 | [Parameter(Position=10,Mandatory=$false)] 29 | [string]$Field4, 30 | [Parameter(Position=11,Mandatory=$false)] 31 | [string]$Expression4, 32 | [Parameter(Position=12,Mandatory=$false)] 33 | [string]$Value4, 34 | [Parameter(Position=13,Mandatory=$false)] 35 | [string]$Field5, 36 | [Parameter(Position=14,Mandatory=$false)] 37 | [string]$Expression5, 38 | [Parameter(Position=15,Mandatory=$false)] 39 | [string]$Value5 40 | 41 | ) 42 | $query = "$Entity$Field$Value" 43 | 44 | If (!($Field2 -eq "")) { 45 | $query= "$query $Field2$Value2" 46 | } 47 | 48 | If (!($Field3 -eq "")) { 49 | $query= "$query $Field3$Value3" 50 | } 51 | 52 | If (!($Field4 -eq "")) { 53 | $query= "$query $Field4$Value4" 54 | } 55 | 56 | If (!($Field5 -eq "")) { 57 | $query= "$query $Field5$Value5" 58 | } 59 | 60 | $query = "$query " 61 | 62 | $query 63 | 64 | } -------------------------------------------------------------------------------- /Autotask/atws-RateUpdate.ps1: -------------------------------------------------------------------------------- 1 | #REQUIRES -Version 2 2 | 3 | <# 4 | .SYNOPSIS 5 | Script to update hourly rates in Autotask. The script is not generic, you 6 | need to modify it before each use. 7 | 8 | .DESCRIPTION 9 | This script uses Autotask Web Services API to update all hourly rates with 10 | a percentage defined as variable in this script. The change will be effecive 11 | immediately, so this script is only meant to be used by someone who knows 12 | what they are doing! 13 | 14 | .NOTES 15 | File Name : atwsPriceUpdate.ps1 16 | Author : Hugo Klemmestad hugo@klemmestad.com 17 | Prerequisite : PowerShell V2 over Vista and upper. 18 | Copyright 2014 - Hugo Klemmestad 19 | .LINK 20 | Inspired by av: 21 | https://community.autotask.com/forums/p/15090/38343.aspx#38343 22 | .LINK 23 | Oppdragsgiver: 24 | http://www.office-center.no 25 | .LINK 26 | Blog post: 27 | http://klemmestad.com/2014/08/01/batch-update-your-hourly-rates-in-autotask-using-powershell 28 | .EXAMPLE 29 | atwsPriceUpdate 30 | #> 31 | 32 | # A small QueryXML function I got from Jon Czerwinski in an autotask forum 33 | # https://community.autotask.com/forums/p/15090/38343.aspx#38343 34 | # I have modified it to handle more fields and expressions 35 | 36 | function New-ATWSQuery { 37 | [CmdletBinding()] 38 | param( 39 | [Parameter(Position=0,Mandatory=$true)] 40 | [string]$Entity, 41 | [Parameter(Position=1,Mandatory=$true)] 42 | [string]$Field, 43 | [Parameter(Position=2,Mandatory=$false)] 44 | [string]$Expression, 45 | [Parameter(Position=3,Mandatory=$false)] 46 | [string]$Value, 47 | [Parameter(Position=4,Mandatory=$false)] 48 | [string]$Field2, 49 | [Parameter(Position=5,Mandatory=$false)] 50 | [string]$Expression2, 51 | [Parameter(Position=6,Mandatory=$false)] 52 | [string]$Value2, 53 | [Parameter(Position=7,Mandatory=$false)] 54 | [string]$Field3, 55 | [Parameter(Position=8,Mandatory=$false)] 56 | [string]$Expression3, 57 | [Parameter(Position=9,Mandatory=$false)] 58 | [string]$Value3, 59 | [Parameter(Position=10,Mandatory=$false)] 60 | [string]$Field4, 61 | [Parameter(Position=11,Mandatory=$false)] 62 | [string]$Expression4, 63 | [Parameter(Position=12,Mandatory=$false)] 64 | [string]$Value4, 65 | [Parameter(Position=13,Mandatory=$false)] 66 | [string]$Field5, 67 | [Parameter(Position=14,Mandatory=$false)] 68 | [string]$Expression5, 69 | [Parameter(Position=15,Mandatory=$false)] 70 | [string]$Value5 71 | 72 | ) 73 | $query = "$Entity$Field$Value" 74 | 75 | If (!($Field2 -eq "")) { 76 | $query= "$query $Field2$Value2" 77 | } 78 | 79 | If (!($Field3 -eq "")) { 80 | $query= "$query $Field3$Value3" 81 | } 82 | 83 | If (!($Field4 -eq "")) { 84 | $query= "$query $Field4$Value4" 85 | } 86 | 87 | If (!($Field5 -eq "")) { 88 | $query= "$query $Field5$Value5" 89 | } 90 | 91 | $query = "$query " 92 | 93 | $query 94 | 95 | } 96 | 97 | # Log file 98 | $myDir = Split-Path -Parent $MyInvocation.MyCommand.Path 99 | $logFile = $myDir + "\atws.log" 100 | 101 | # Username and password for Autotask 102 | # The username must begin with a backslash, otherwise Windows will add a domain 103 | # element that Autotask do not understand. 104 | $username = "\your_autotask_user@domain.com" 105 | $password = ConvertTo-SecureString "your_autotask_password" -AsPlainText -Force 106 | $credentials = New-Object System.Management.Automation.PSCredential($username,$password) 107 | 108 | # Create an Autotask SOAP object 109 | $AutotaskURL = "https://webservices4.Autotask.net/atservices/1.5/atws.wsdl" 110 | $atws = New-WebServiceProxy -URI $AutotaskURL -Credential $credentials 111 | $zoneInfo = $atws.getZoneInfo($username) 112 | If ($zoneInfo.Url -ne $AutotaskURL) 113 | { 114 | $atws = New-WebServiceProxy -URI $zoneInfo.Url -Credential $credentials 115 | } 116 | 117 | # Todays date for logging 118 | [datetime]$toDay = Get-Date -Format s 119 | 120 | # Get all Time and Materials contracts 121 | # Important: I have created a special contract category to mark updated contracts 122 | # as updated. That way I may run the script more than once without getting a contract 123 | # updated twice. I created the contract categori in Autotask and used 124 | # powershell to learn its numerical ID 125 | $contractQuery = New-ATWSQuery "Contract" "ContractType" "Equals" "1" "Status" "Equals" "1" "ContractCategory" "NotEqual" "16" 126 | $contracts = $atws.query($contractQuery) 127 | 128 | # Verify we have a result to work with 129 | # Exit if we don't 130 | If(!($contracts.EntityResults.Count -gt 0)) { 131 | $logFileText = "{0,-25} | Ingenting" -f $toDay 132 | Add-Content $logFile $logFileText 133 | 134 | Exit 2 135 | } 136 | 137 | # Get your main role by name 138 | $roleQuery = New-ATWSQuery "Role" "Name" "Equals" "your_role_name_goes_here" 139 | $mainRole = $atws.query($roleQuery).EntityResults[0] 140 | 141 | 142 | $percentage = 4.3 143 | 144 | foreach ($contract in $contracts.EntityResults) { 145 | 146 | # Update main role first 147 | $rateQuery = New-ATWSQuery "ContractRate" "ContractID" "Equals" $contract.id "RoleID" "Equals" $mainRole.id 148 | $baserate = $atws.query($rateQuery).EntityResults[0] 149 | 150 | # Calculate new hourly rate slowly to make sure you know what the code does 151 | # Round up(!) to nearest 5 152 | $hourlyRate = $hourlyRate + $hourlyRate * $percentage / 100 # manual percentage for code clarity 153 | $hourlyRate = $hourlyRate - ($hourlyRate % 5) + 5 # Round UP to nearest 5 154 | 155 | # Save hourly rate back to $baserate. We are not saving just yet. 156 | $baserate.ContractHourlyRate = $hourlyRate 157 | 158 | 159 | # Get other roles on contracts 160 | # In this script all rates will be set equal. You may not want this. Be 161 | # careful! 162 | $rateQuery = New-ATWSQuery "ContractRate" "ContractID" "Equals" $contract.id "RoleID" "NotEqual" $mainRole.id "ContractHourlyRate" "GreaterThan" "0" 163 | $rates = $atws.query($rateQuery) 164 | foreach ($rate in $rates.EntityResults) { 165 | $rate.ContractHourlyRate = $hourlyRate 166 | $result = $atws.update($rate) 167 | If(!($result.ReturnCode -eq 1)) { 168 | $logFileText = "{0,-25} | Contract {1,30} | Role {2,15} | {3}" -f $toDay, $contract.ContractName, $rate.id, $result.Errors[1].Message 169 | Add-Content $logFile $logFileText 170 | Exit 2 171 | } 172 | } 173 | # If we gotten this far: Update $baserate 174 | # It is important to wait until now. If the script fails before this, 175 | # the hourly rate of your main role is still untouched. Since we use it to 176 | # set the other rates, the script may still be used to fix things. 177 | $result = $atws.update($baserate) 178 | If(!($result.ReturnCode -eq 1)) { 179 | $logFileText = "{0,-25} | Contract {1,30} | Main Role {2,15} | {3}" -f $toDay, $contract.ContractName, $rate.id, $result.Errors[1].Message 180 | Add-Content $logFile $logFileText 181 | Exit 2 182 | } 183 | 184 | # Remember: Your custom category may have a different ID 185 | $contract.ContractCategory = 16 186 | $atws.update($contract) 187 | If(!($result.ReturnCode -eq 1)) { 188 | $logFileText = "{0,-25} | Contract {1,30} | Could not update contract | {3}" -f $toDay, $contract.ContractName, $result.Errors[1].Message 189 | Add-Content $logFile $logFileText 190 | Exit 2 191 | } 192 | 193 | # Save a note of the work you have done 194 | $noteToCreate = New-Object Microsoft.PowerShell.Commands.NewWebserviceProxy.AutogeneratedTypes.WebServiceProxy1k_net_atservices_1_5_atws_wsdl.ContractNote 195 | $noteToCreate.ContractID = $contract.id 196 | $noteToCreate.Title = "Price Update" 197 | $noteToCreate.Description = "Hourly rates updated to $hourlyRate the $toDay." 198 | $atws.create($noteToCreate) 199 | 200 | # Write some info to the log file 201 | $logFileText = "{0,-25} | Contract {1,30} | {2,30}" -f $toDay, $contract.ContractName, $noteToCreate.Description 202 | Add-Content $logFile $logFileText 203 | 204 | } 205 | 206 | Exit 0 -------------------------------------------------------------------------------- /Azure/Access-StorageContext.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | # The name of the storage account to enumerate. 3 | [Parameter(Mandatory = $true)] 4 | [string]$StorageAccountName 5 | ) 6 | 7 | $storageAccount = Get-AzureStorageAccount -StorageAccountName $StorageAccountName -ErrorAction SilentlyContinue 8 | if ($storageAccount -eq $null) 9 | { 10 | throw "The storage account specified does not exist in this subscription." 11 | } 12 | 13 | # Instantiate a storage context for the storage account. 14 | $storagePrimaryKey = (Get-AzureStorageKey -StorageAccountName $StorageAccountName).Primary 15 | $storageContext = New-AzureStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $storagePrimaryKey -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /MAXfocus/Enable-HardwareEvents.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Enables a hardware events subscription if IPMI is available. 4 | 5 | .DESCRIPTION 6 | Checks whether IPMI is available and creates a hardware events 7 | subscription if it is missing. Such a subscription is maintained 8 | by Windows service Wecsvc. It is started if it isn't running and 9 | startupmode set to Auto. 10 | 11 | .PARAMETER None 12 | No parameters are needed. Any parameters given are ignored. 13 | 14 | .NOTES 15 | Name: Enable-HardwareEvents 16 | Author: Hugo L. Klemmestad 17 | DateCreated: 14 NOV 2014 18 | 19 | .EXAMPLE 20 | Enable-HardwareEvents 21 | HardwareEvents Enabled 22 | 23 | Description 24 | ----------- 25 | Returns IPMI NOT AVAILABLE if IPMI driver not loaded. 26 | #> 27 | 28 | ## I put the literal string at top for esthetic reasons only 29 | [xml]$WSManSelRg = @" 30 | 31 | A subscription for the HardwareEvents 32 | WSManSelRg 33 | http://schemas.microsoft.com/wbem/wsman/1/logrecord/sel 34 | 35 | 36 |
LOCALHOST
37 |
38 |
39 | HardwareEvents 40 | 41 | 42 | 43 | 44 | 45 |
46 | "@ 47 | 48 | 49 | $ErrorActionPreference = "Stop" 50 | 51 | ## First we try if IPMI is available. It is always present if BMC is avaliable 52 | Try { 53 | $ipmi = Get-WmiObject -Namespace root/wmi -Class Microsoft_IPMI 2>$null 54 | # IPMI is available. 55 | $ErrorActionPreference = "Continue" 56 | ## SETUP 57 | $FilePath = $env:TEMP + "\WSManSelRg.xml" 58 | $Wecsvc = Get-WmiObject Win32_service | where { $_.Name -eq "Wecsvc" } 59 | $HardwareEvents = Get-WmiObject Win32_NTEventLogFile | where { $_.LogFileName -eq "HardwareEvents" } 60 | 61 | $SubscriptionStatus = wecutil gr wsmanselrg 2>$null 62 | 63 | If ($LASTEXITCODE -gt 0) { 64 | # Create Subscription 65 | If (!($Wecsvc.Started)) { 66 | Start-Service -Name "Wecsvc" 67 | } 68 | If (!($Wecsvc.StartMode -eq "Auto")) { 69 | Set-Service -Name "Wecsvc" -StartupType Automatic 70 | } 71 | # Create the subscription file 72 | $WSManSelRg.Save($FilePath) 73 | 74 | # Create the subscription 75 | wecutil cs $FilePath 2>$null 76 | 77 | If ($LASTEXITCODE -gt 0) { 78 | Write-Host "'wecutil cs $FilePath' Failed!" 79 | Remove-Item $FilePath -Force 80 | Exit 1001 # Error 81 | } 82 | # Clean up file system 83 | Remove-Item $FilePath -Force 84 | 85 | $SubscriptionStatus = wecutil gr wsmanselrg 86 | } 87 | 88 | } Catch { 89 | Write-Host "IPMI not available. This check should be removed now." 90 | Exit 0 91 | } 92 | $HardwareEventsOK = $SubscriptionStatus | Select-String "LastError: 0" 93 | If ($HardwareEventsOK) { 94 | Write-Host "HardwareEvents Enabled. This check should be removed now." 95 | Exit 0 96 | } Else { 97 | Write-Host "Enabling HardwareEvents failed." 98 | Write-Host $SubscriptionStatus 99 | Exit 1001 100 | } -------------------------------------------------------------------------------- /MAXfocus/Install-ApplicationsFromMAXfocus.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Installs software silently on servers and workstations using Chocolatey. 4 | .DESCRIPTION 5 | The script is to be uploaded to your dashboard account as a user script. 6 | It can run both as a script check and as a scheduled task. You list package 7 | names as parameter to script. Chocolatey will update packages that are 8 | already installed. 9 | 10 | Warning: If you later omit a package name it will NOT be uninstalled! 11 | .EXAMPLE 12 | Install-ApplicationsFromMAXfocus notepadplusplus adobereader 13 | .EXAMPLE 14 | Install-ApplicationsFromMAXfocus dropbox googlechrome 15 | .EXAMPLE 16 | Install-ApplicationsFromMAXfocus google-chrome-x64 17 | .OUTPUTS 18 | Installed applications and text log 19 | .LINK 20 | http://klemmestad.com/2015/01/15/install-and-update-software-with-maxfocus-and-chocolatey/ 21 | .LINK 22 | https://chocolatey.org 23 | .LINK 24 | https://chocolatey.org/packages 25 | .EMAIL 26 | hugo@klemmestad.com 27 | .VERSION 28 | 1.0 29 | #> 30 | 31 | 32 | # We are only binding -logfile. Leave the rest unbound. 33 | param ( 34 | # Make sure -logfile is NOT positional 35 | [Parameter(Mandatory=$false)] 36 | [string]$logfile = 'ScriptMicrosoftUpdate.log', 37 | 38 | # Capture entire parameterlist, save -logfile, as Packages 39 | [Parameter(Position=0,ValueFromRemainingArguments=$true)] 40 | [array]$Packages 41 | ) 42 | 43 | If (-not ($Packages)) { 44 | Write-Host "No packages selected." 45 | Write-Host "USAGE:" 46 | Write-Host "List package names as parameter to Check or Task." 47 | Write-Host "See https://chocolatey.org/packages for available packages." 48 | Exit 1001 49 | } 50 | 51 | #Region Functions 52 | 53 | function Restart-MAXfocusService ([bool]$Safely=$true) { 54 | If ($Safely) { 55 | # Update last runtime to prevent changes too often 56 | [int]$currenttime = $(get-date -UFormat %s) -replace ",","." # Handle decimal comma 57 | $settingsContent["DAILYSAFETYCHECK"]["RUNTIME"] = $currenttime 58 | } 59 | # Clear lastcheckday to make DSC run immediately 60 | $settingsContent["DAILYSAFETYCHECK"]["LASTCHECKDAY"] = "0" 61 | Out-IniFile $settingsContent $IniFile 62 | 63 | # Prepare restartscript 64 | $RestartScript = $env:TEMP + "\RestartMAXfocusAgent.cmd" 65 | $RestartScriptContent = @" 66 | net stop "Advanced Monitoring Agent" 67 | net start "Advanced Monitoring Agent" 68 | Del /F $RestartScript 69 | "@ 70 | $RestartScriptContent | Out-File -Encoding OEM $RestartScript 71 | # Start time in the future 72 | $JobTime = (Get-Date).AddMinutes(-2) 73 | $StartTime = Get-Date $JobTime -Format HH:mm 74 | $TaskName = "Restart Advanced Monitoring Agent" 75 | $Result = &schtasks.exe /Create /TN $TaskName /TR "$RestartScript" /RU SYSTEM /SC ONCE /ST $StartTime /F 76 | If ($Result) { 77 | Output-Debug "Restarting Agent using scheduled task now." 78 | $Result = &schtasks.exe /run /TN "$TaskName" 79 | } 80 | 81 | If (!($Result -like 'SUCCESS:*')) { 82 | Output-Debug "SCHTASKS.EXE failed. Restarting service the hard way." 83 | Restart-Service 'Advanced Monitoring Agent' 84 | } 85 | 86 | 87 | } 88 | 89 | 90 | 91 | # Downloaded from 92 | # http://blogs.technet.com/b/heyscriptingguy/archive/2011/08/20/use-powershell-to-work-with-any-ini-file.aspx 93 | # modified to use ordered list by me 94 | function Get-IniContent ($filePath) { 95 | $ini = New-Object System.Collections.Specialized.OrderedDictionary 96 | switch -regex -file $FilePath 97 | { 98 | "^\[(.+)\]" # Section 99 | { 100 | $section = $matches[1] 101 | $ini[$section] = New-Object System.Collections.Specialized.OrderedDictionary 102 | $CommentCount = 0 103 | } 104 | "^(;.*)$" # Comment 105 | { 106 | $value = $matches[1] 107 | $CommentCount = $CommentCount + 1 108 | $name = "Comment" + $CommentCount 109 | $ini[$section][$name] = $value 110 | } 111 | "(.+?)\s*=(.*)" # Key 112 | { 113 | $name,$value = $matches[1..2] 114 | $ini[$section][$name] = $value 115 | } 116 | } 117 | return $ini 118 | } 119 | # Downloaded from 120 | # http://blogs.technet.com/b/heyscriptingguy/archive/2011/08/20/use-powershell-to-work-with-any-ini-file.aspx 121 | # Modified to force overwrite by me 122 | function Out-IniFile($InputObject, $FilePath) { 123 | $outFile = New-Item -ItemType file -Path $Filepath -Force 124 | foreach ($i in $InputObject.keys) 125 | { 126 | if ("Hashtable","OrderedDictionary" -notcontains $($InputObject[$i].GetType().Name)) 127 | { 128 | #No Sections 129 | Add-Content -Path $outFile -Value "$i=$($InputObject[$i])" 130 | } else { 131 | #Sections 132 | Add-Content -Path $outFile -Value "[$i]" 133 | Foreach ($j in ($InputObject[$i].keys | Sort-Object)) 134 | { 135 | if ($j -match "^Comment[\d]+") { 136 | Add-Content -Path $outFile -Value "$($InputObject[$i][$j])" 137 | } else { 138 | Add-Content -Path $outFile -Value "$j=$($InputObject[$i][$j])" 139 | } 140 | 141 | } 142 | Add-Content -Path $outFile -Value "" 143 | } 144 | } 145 | } 146 | 147 | 148 | #EndRegion Functions 149 | 150 | # Find "Advanced Monitoring Agent" service and use path to locate files 151 | $gfimaxagent = Get-WmiObject Win32_Service | Where-Object { $_.Name -eq 'Advanced Monitoring Agent' } 152 | $gfimaxexe = $gfimaxagent.PathName 153 | $gfimaxpath = Split-Path $gfimaxagent.PathName.Replace('"',"") -Parent 154 | 155 | #Region Setup Run Environment 156 | # Package installation requires Desktop Interaction for quite a few packages 157 | # Desktop interaction for services requires the UI0Detect service to run 158 | 159 | # Get service 160 | $ServiceName = 'UI0Detect' 161 | $interactiveservice = Get-WmiObject Win32_Service | Where { $_.Name -eq $ServiceName } 162 | 163 | # Make sure interactive services are allowed 164 | $InteractiveSetting = $(Get-ItemProperty $(Get-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\Windows').PSPath).NoInteractiveServices 165 | If ($InteractiveSetting -eq 1) { 166 | Set-ItemProperty $($(Get-Item 'HKLM:\SYSTEM\CurrentControlSet\Control\Windows').PSPath) -name NoInteractiveServices -value 0 -Force 167 | } 168 | 169 | # Make sure startup mode is automatic 170 | If ($interactiveservice.StartMode -ne 'Auto') { 171 | $result = $interactiveservice.Change($null,$null,$null,$null,'Automatic') 172 | If ($result.ReturnValue -ne 0) { 173 | Write-Host 'ERROR: Could not set Interactive Service Detection servie to Automatic start.' 174 | Write-Host 'You can make this change from Remote Background in Dashboard and this script' 175 | Write-host 'will continue next time it runs.' 176 | Write-Host 'Exiting.' 177 | Exit 1001 178 | } 179 | } 180 | 181 | # Refresh service and make sure service is running 182 | $interactiveservice = Get-WmiObject Win32_Service | Where { $_.Name -eq $ServiceName } 183 | If ($interactiveservice.State -ne 'Running') { 184 | Start-Service -Name $ServiceName 185 | } 186 | 187 | ## Modify environment to support application install from User System 188 | # Set Shell folders to correct values for application install 189 | # If Shell folders must be modified the agent must be restarted 190 | # The point of the changes is to make pr user installations 191 | # put icons and files where the user can see and reach them. 192 | 193 | $RestartNeeded = $false 194 | Push-Location # Save current location 195 | cd "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" 196 | Foreach ($Property in (Get-Item . | Select -ExpandProperty Property)) { 197 | $NewValue = '' 198 | Switch ($Property) { 199 | 'Desktop' { $NewValue = '{0}\Desktop' -f $Env:PUBLIC } 200 | 'Personal' { $NewValue = '{0}\Documents' -f $Env:PUBLIC } 201 | 'My Music' { $NewValue = '{0}\Music' -f $Env:PUBLIC } 202 | 'My Pictures' { $NewValue = '{0}\Pictures' -f $Env:PUBLIC } 203 | 'My Video' { $NewValue = '{0}\Videos' -f $Env:PUBLIC } 204 | 'Favorites' { $NewValue = '{0}\Favorites' -f $Env:PUBLIC } 205 | 'Local AppData' { $NewValue = '{0}\Chocolatey\' -f $Env:ALLUSERSPROFILE } 206 | 'AppData' { $NewValue = '{0}' -f $Env:ALLUSERSPROFILE } 207 | 'Start Menu' { $NewValue = '{0}\Microsoft\Windows\Start Menu' -f $Env:ALLUSERSPROFILE } 208 | 'Programs' { $NewValue = '{0}\Microsoft\Windows\Start Menu\Programs' -f $Env:ALLUSERSPROFILE } 209 | 'Startup' { $NewValue = '{0}\Microsoft\Windows\Start Menu\Programs\Startup' -f $Env:ALLUSERSPROFILE } 210 | } 211 | $OldValue = (Get-ItemProperty . -Name $Property).($Property) 212 | If (($NewValue) -and ($NewValue -ne $OldValue )) { 213 | Set-ItemProperty -Path . -Name $Property -Value $NewValue -Force 214 | $RestartNeeded = $true 215 | } 216 | 217 | } 218 | If ($RestartNeeded) { 219 | Write-Host 'Application install enviroment has been modified.' 220 | } 221 | Pop-Location # Return to scripts directory 222 | 223 | # Make sure Desktopinteract is enabled for max agent. If it isn't the 224 | # service must unfortunately be restarted and this job resumed later 225 | If (!$gfimaxagent.DesktopInteract) { 226 | $result = $gfimaxagent.Change($null,$null,$null,$null,$null,$true) 227 | If ($result.ReturnValue -eq 0) { 228 | Write-Host 'Enabled Desktop Interact for Advanced Monitoring Agent OK.' 229 | $RestartNeeded = $true 230 | } Else { 231 | Write-Host 'Failed to enable Desktop Interact for Advanced Monitoring Agent.' 232 | Write-Host 'Exiting...' 233 | Exit 1001 234 | } 235 | } 236 | 237 | ## Check if service must be restarted 238 | If ($RestartNeeded) { 239 | Write-Host 'Service needs a restart before setting takes effect.' 240 | Write-Host 'Restarting Now.' 241 | Write-Host 'WARNING: Software installation will NOT happen until next run!' 242 | Restart-MAXfocusService 243 | Exit 0 244 | } 245 | 246 | #EndRegion 247 | 248 | #force this to run in 32 bit 249 | 250 | if ($env:Processor_Architecture -ne "x86") { 251 | 252 | Write-Host "Switching to x86 PowerShell..." 253 | 254 | &"$env:WINDIR\syswow64\windowspowershell\v1.0\powershell.exe" -ExecutionPolicy bypass -NoProfile $myInvocation.Line 255 | exit $LASTEXITCODE 256 | } 257 | 258 | 259 | 260 | # Look for parameter '-uninstall' 261 | # We can't have more than 1 non-positional parameter 262 | $ParsedArray = @() 263 | $Uninstall = $false 264 | Foreach ($Package in $Packages) { 265 | If ($Package -eq '-uninstall') { 266 | $Uninstall = $true 267 | } Else { 268 | $ParsedArray += $Package 269 | } 270 | } 271 | 272 | $Packages = $ParsedArray 273 | 274 | $inifile = $gfimaxpath + '\settings.ini' 275 | $settings = Get-IniContent $inifile 276 | 277 | If (!($Settings['CHOCOLATEY'])) { 278 | $Settings['CHOCOLATEY'] = @{} 279 | } 280 | 281 | # Chocolatey commands 282 | $Choco = $env:ProgramData + "\chocolatey\chocolateyinstall\chocolatey.ps1" 283 | 284 | #Region Install Chocolatey if necessary 285 | If (!(Test-Path $Choco)) { 286 | Write-Host "Chocolatey not installed. Trying to install." 287 | $ErrorActionPreference = 'Stop' 288 | Try { 289 | iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) 290 | } Catch { 291 | $ErrorActionPreference = 'Continue' 292 | Write-Host "ERROR: Installing Chocolatey failed with error:" 293 | Write-Host $_.Exception.Message 294 | Exit 1001 295 | } 296 | $ErrorActionPreference = 'Continue' 297 | If (Test-Path $Choco) { 298 | Write-Host "Chocolatey is installed. Proceeding." 299 | } Else { 300 | Write-Host "ERROR: Installation succeeded, but Chocolatey still not found! Exiting." 301 | Exit 1001 302 | } 303 | } 304 | #EndRegion 305 | 306 | Write-Host "Verifying package installation:" 307 | 308 | If ($Uninstall) { 309 | # Make a copy of installed packages as the hashtable cannot be changed while 310 | # using it as base for a foreach loop 311 | $packageList = @() 312 | Foreach ($InstalledPackage in $settings['CHOCOLATEY'].Keys) { 313 | $Packagelist += $InstalledPackage.ToString() 314 | } 315 | 316 | # Loop through copy of hashtable keys, updating hashtable if necessary 317 | Foreach ($InstalledPackage in $Packagelist) { 318 | $ErrorActionPreference = 'Stop' 319 | Try { 320 | If ($Packages -notcontains $InstalledPackage) { 321 | . $Choco uninstall $InstalledPackage 322 | } 323 | $settings['CHOCOLATEY'].Remove($Package) 324 | Out-IniFile $settings $inifile 325 | } Catch { 326 | $ErrorActionPreference = 'Continue' 327 | Write-Host ("ERROR: Package {0} uninstallation failed with error:" -f $Package) 328 | Write-Host $_.Exception.Message 329 | } 330 | $ErrorActionPreference = 'Continue' 331 | } 332 | } 333 | 334 | # Get installed packages and separate package name from version 335 | $InstalledPackages = ( &choco list -localonly) 336 | $InstalledList = @{} 337 | Foreach ($InstalledPackage in $InstalledPackages) { 338 | $Package = $InstalledPackage.Split(' ') 339 | $InstalledList[$Package[0]] = $Package[1] 340 | } 341 | 342 | # Loop through package names given to us from command line 343 | $InstallPackages = @() 344 | Foreach ($Package in $Packages) { 345 | # Maintain installed package list in agent settings.ini 346 | If ($Settings['CHOCOLATEY'][$Package] -notmatch '\d\d\.\d\d\.\d{4}') { 347 | $Settings['CHOCOLATEY'][$Package] = Get-Date -Format 'dd.MM.yyyy' 348 | Out-IniFile $settings $inifile 349 | } 350 | If (!($InstalledList.ContainsKey($Package))) { 351 | $InstallPackages += $Package 352 | } 353 | } 354 | 355 | Write-Host 'Updating All' 356 | Try { 357 | $ErrorActionPreference = 'Stop' 358 | . $choco update all 359 | } Catch { 360 | $ErrorActionPreference = 'Continue' 361 | Write-Host "ERROR: Update failed with error:" 362 | Write-Host $_.Exception.Message 363 | } 364 | Write-Host ('Installing packages {0}' -f $InstallPackages) 365 | If ($InstallPackages.Count -gt 0) { 366 | Try { 367 | $ErrorActionPreference = 'Stop' 368 | . $choco install @InstallPackages 369 | } Catch { 370 | $ErrorActionPreference = 'Continue' 371 | Write-Host "ERROR: Package installation failed with error:" 372 | Write-Host $_.Exception.Message 373 | } 374 | } 375 | 376 | # Add path modifications to System Path 377 | $UserPath = (Get-ItemProperty -Path 'HKCU:\ENVIRONMENT' -Name PATH -ErrorAction SilentlyContinue).PATH 378 | If ($UserPath) { 379 | $SystemPath = (Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).PATH 380 | $OLDPATH = $SystemPath 381 | Foreach ($Path in $UserPath.Split(';')) { 382 | $Path = $Path.Replace(';','') 383 | If ($OLDPATH -notmatch $Path) { 384 | $SystemPath += ";$Path" 385 | } 386 | } 387 | If ($SystemPath -ne $OLDPATH) { 388 | Set-ItemProperty $($(Get-Item 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment').PSPath) -name PATH -value $SystemPath -Force 389 | } 390 | Set-ItemProperty $($(Get-Item 'HKCU:\ENVIRONMENT').PSPath) -name PATH -value '' -Force 391 | } 392 | 393 | Exit 0 -------------------------------------------------------------------------------- /MAXfocus/MAXfocus_PatchSettings.ps1: -------------------------------------------------------------------------------- 1 |  2 | # Send something to STDOUT to prevent task_start.js to lock if the script fails 3 | Write-Host " " 4 | 5 | ## SETUP ENVIRONMENT 6 | # Find "Advanced Monitoring Agent" service and use path to locate files 7 | $gfimaxagent = Get-WmiObject Win32_Service | Where-Object { $_.Name -eq 'Advanced Monitoring Agent' } 8 | $gfimaxexe = $gfimaxagent.PathName 9 | $gfimaxpath = Split-Path $gfimaxagent.PathName.Replace('"',"") -Parent 10 | 11 | $DSCfile = $gfimaxpath + "\DSC_Config.xml" 12 | $DSC_Config = New-Object -TypeName XML 13 | $DSC_Config.Load($DSCfile) 14 | 15 | $PatchManagement = $DSC_Config.checks.VulnerabilityCheck 16 | 17 | If (!($PatchManagement)) { 18 | Write-Host "Patch Management not in use." 19 | Exit 0 20 | } 21 | 22 | $Schedule = $PatchManagement.schedule2 23 | If ($Schedule -is [System.Xml.XmlElement]) { $Schedule = $Schedule.InnerText} 24 | $Mode = $PatchManagement.mode 25 | $RebootDevice = $PatchManagement.rebootdevice 26 | $RebootCriteria = $PatchManagement.rebootcriteria 27 | If ($RebootCriteria -is [System.Xml.XmlElement]) { $RebootCriteria = $RebootCriteria.InnerText} 28 | $AutoApproval = $PatchManagement.autoapproval 29 | If ($AutoApproval -is [System.Xml.XmlElement]) { $AutoApproval = $AutoApproval.InnerText} 30 | 31 | $ApprovalOptions = @([regex]::Split($AutoApproval,",")) 32 | $Vendors = @("Microsoft", "Other Vendors") 33 | $Category = @("Critical", "Important", "Moderate", "Low", "Other") 34 | 35 | $ScheduleOptions = @([regex]::Split($Schedule,"\|")) 36 | $Time = "{0}:{1}" -f $ScheduleOptions[2], $ScheduleOptions[3] 37 | $DayConfig = $ScheduleOptions[4] 38 | 39 | $WeekDays = "" 40 | For ($i = 0;$i -le 6;$i++) { 41 | 42 | If ($DayConfig.Substring($i,1) -eq "X") { 43 | Switch ($i) { 44 | 0 { $WeekDay = "Monday "} 45 | 1 { $WeekDay = "Tuesday "} 46 | 2 { $WeekDay = "Wednesday "} 47 | 3 { $WeekDay = "Thursday "} 48 | 4 { $WeekDay = "Friday "} 49 | 5 { $WeekDay = "Saturday "} 50 | 6 { $WeekDay = "Sunday "} 51 | } 52 | $WeekDays = "$WeekDays $WeekDay" 53 | } 54 | } 55 | 56 | Switch ($RebootCriteria) { 57 | "0|0" { $ScheduleMissed = "not run" } 58 | "0|1" { $ScheduleMissed = "run ASAP, reboot NOT included" } 59 | "1|1" { $ScheduleMissed = "run ASAP, including reboot" } 60 | } 61 | 62 | If ($Mode -eq 0) { 63 | $ReportMode = "report only" 64 | } Else { 65 | $ReportMode = "fail" 66 | } 67 | 68 | Switch ($RebootDevice) { 69 | 0 { $RebootPolicy = "device will never be rebooted" } 70 | 1 { $RebootPolicy = "device will reboot when needed" } 71 | 2 { $RebootPolicy = "device will always reboot" } 72 | } 73 | 74 | 75 | 76 | Write-Host ("Device will be patched at {0} on every{1}" -f $Time, $WeekDays) 77 | Write-Host ("After patching {0}." -f $RebootPolicy) 78 | Write-Host ("If schedule is missed Patch Management will {0}." -f $ScheduleMissed) 79 | Write-Host ("If patches are missing this check will {0}." -f $ReportMode) 80 | 81 | For ($i = 0; $i -le 1; $i++) { 82 | Write-Host ("`nApprovalpolicy for {0}" -f $Vendors[$i]) 83 | $ApprovalPolicy = @([regex]::Split($ApprovalOptions[$i],"\|")) 84 | For ($y = 0; $y -le 4; $y++) { 85 | Switch ($ApprovalPolicy[$y]) { 86 | 1 { $Policy = "Ignore" } 87 | 2 { $Policy = "Approve" } 88 | 3 { $Policy = "Manual" } 89 | } 90 | Write-Host (" {0,-10} {1}" -f $Category[$y], $Policy) 91 | } 92 | } 93 | 94 | If (($ScheduleOptions[2] -ge 8)) { 95 | # FAIL SCRIPT 96 | Exit 1001 97 | } 98 | Exit 0 -------------------------------------------------------------------------------- /MAXfocus/README Verify-MAXfocusConfig.md: -------------------------------------------------------------------------------- 1 | #VERSION HISTORY 2 | 3 | ##1.0 INITIAL RELEASE 4 | 5 | ### 1.1 BUGFIX 6 | Removed all Powershell native parameter validation. Added parameters -Debug, -Verbose and -logfile to avoid parameter validation failure. Added code for parameter validation. 7 | 8 | Removed bug in parsing of Windows services if using "Default" as option. 9 | 10 | ### 1.2 MODIFICATION 11 | -Debug now implies -Verbose. 12 | 13 | ### 1.21 BUGFIX AND MODIFICATION 14 | I took module PSScheduledJob for granted. That was wrong. I have added code to detect If the module is available. If it is, it will be used. If not I fall back to hard restart of the agent service. 15 | 16 | ### 1.22 BUGFIX 17 | Not all devices with Powershell v3 has PSScheduledJob. I am loath to use 18 | 19 | Get-Module -ListAvailable 20 | 21 | because it is way to slow. I use Try-Catch to fail silently back to Restart-Service without too much cost. 22 | 23 | ### 1.23 BUGFIX AND MODIFICATION 24 | Added text "PARAMETER: " as prefix to verbose out put for parameter validation. 25 | 26 | Fixed sc.exe parameters. Using a fixed interval for all devices to avoid variable parsing errors. 27 | 28 | ### 1.24 MODIFICATION 29 | I have dropped PSScheduledJob entirely and use schtasks.exe to restart monitoring agent. -------------------------------------------------------------------------------- /MAXfocus/README.md: -------------------------------------------------------------------------------- 1 | Scripts to run as Automated Tasks or Script Checks with MAXfocus 2 | ========== 3 | 4 | ## Enable-HardwareEvents.ps1 5 | Makes hardware events show up in the eventlog HardwareEvents. It is created to run on any server and only perform actions where 6 | required. 7 | 8 | On hardware servers (as opposed to virtual servers) there are usually a management chip. On this chip any hardware events are usually logged. 9 | If a hardware chip is available, Windows automatically loads an IPMI driver. However, you must still enable an event subscription manually for the events to actuall show up in Hardware Events. 10 | 11 | This script checks if IPMI is available and creates an event subscription if it is. You only need to run this script once. 12 | 13 | If no IPMI driver is avaiable, the script does nothing. 14 | 15 | ## Install-ApplicationsFromMAXfocus.ps1 16 | Installs software silently on servers and workstations using Chocolatey. The script is to be uploaded to your dashboard account as a user script. It can run both as a script check and as a scheduled task. You list package names as parameter to script. Chocolatey will update packages that are already installed. 17 | 18 | ## MAXfocus_PatchSettings.ps1 19 | A script that reads MAXfocus patchmanagement settings from a device and writes them back to the dashboard in a human-readable format. 20 | 21 | The script does not modify anything. 22 | 23 | ## ReadRecoveryOptions.ps1 24 | A script that reads a Windows machines crash report configuration and prints it back to the dashboard in a (somewhat) human-readable format. 25 | 26 | The script does not modify anything. 27 | 28 | ## Verify-MAXfocusConfig.ps1 29 | See http://klemmestad.com/2014/12/22/automate-maxfocus-with-powershell/ 30 | 31 | Configures default checks on a MAXfocus monitored device. Any change requires a rewrite of agent configuration files and a restart of the agent service. 32 | 33 | ## Verify-MAXfocusVMwareChecks.ps1 34 | A script to automatically add VMware checks to a MAXfocus monitored device. *Warning!* This script is a hack. It downloads script items from GitHub, not the dashboard. 35 | -------------------------------------------------------------------------------- /MAXfocus/ReadRecoveryOptions.ps1: -------------------------------------------------------------------------------- 1 | # List of settings that indicate the action to be taken by a computer 2 | # Runs on Windows 7,8 workstations 3 | Try { 4 | $RecoveryConf = get-wmiobject "Win32_OSRecoveryConfiguration" 5 | foreach ($RCItem in $RecoveryConf) { 6 | switch ($RCItem.DebugInfoType) { 7 | 0{$DebugInfoType= "None"} 8 | 1{$DebugInfoType= "Complete Memory Dump"} 9 | 2{$DebugInfoType= "Kernel Memory Dump"} 10 | 3{$DebugInfoType= "Small Memory Dump"} 11 | } 12 | write-host "Automatically reboot is " $RCItem.AutoReboot 13 | write-host "Description is " $RCItem.Description 14 | write-host "Debug file path is " $RCItem.DebugFilePath 15 | write-host "Debug information type is " $DebugInfoType 16 | write-host "Expanded debug file path is " $RCItem.ExpandedDebugFilePath 17 | write-host "Expanded mini dump directory is " $RCItem.ExpandedMiniDumpDirectory 18 | write-host "Name is " $RCItem.Name 19 | write-host "Send admin alert ID is " $RCItem.SendAdminAlert 20 | write-host "Overwrite existing debug file is " $RCItem.OverwriteExistingDebugFile 21 | } 22 | write-host "Successfully passed" 23 | exit 0 24 | } 25 | Catch { 26 | write-host "Failure" 27 | exit 1001 28 | } -------------------------------------------------------------------------------- /MAXfocus/Set-RebootSchedule.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [string]$Day = 'Wed', 3 | [string]$Time = '05:30', 4 | [string]$logfile 5 | ) 6 | 7 | # Validate day 8 | $Days = @('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun') 9 | If ($Days -notcontains $Day) { 10 | Write-Host ('ERROR: Parameter -Day {0} is wrong. Value must be one of:' -f $Day) 11 | Write-host @Days 12 | Exit 1001 13 | } 14 | 15 | If ($Time -notmatch '(^\d\d):(\d\d)$') { 16 | Write-Host ('ERROR: Parameter -Time {0} is wrong. Value must be in 24 hour format HH:MM' -f $Time) 17 | Exit 1001 18 | } ElseIf ($Matches[1] -gt 23 -or $Matches[1] -lt 0) { 19 | Write-Host ('ERROR: Parameter -Time {0} is wrong. Value must be in 24 hour format HH:MM' -f $Time) 20 | Exit 1001 21 | } ElseIf ($Matches[2] -gt 59 -or $Matches[2] -lt 0) { 22 | Write-Host ('ERROR: Parameter -Time {0} is wrong. Value must be in 24 hour format HH:MM' -f $Time) 23 | Exit 1001 24 | } 25 | 26 | 27 | # Prepare restartscript 28 | $RestartScript = 'shutdown.exe /r /t 300' 29 | 30 | $TaskName = "Restart Server on Schedule" 31 | $Result = &schtasks.exe /query /tn "$TaskName" 32 | If (!($Result)) { 33 | Write-Host "Task missing. Creating Scheduled Task." 34 | $Result = &schtasks.exe /Create /TN $TaskName /TR "$RestartScript" /RU SYSTEM /SC WEEKLY /D $Day /ST $Time 35 | } 36 | 37 | # Try again 38 | $Result = &schtasks.exe /query /tn "$TaskName" 39 | If ($Result) { 40 | Write-Host $Result[4] 41 | } Else { 42 | Write-Host "ERROR: SCHTASKS.EXE failed. " 43 | Exit 1001 44 | } 45 | 46 | $DayIsWrong = $false 47 | $TimeIsWrong = $false 48 | If ($Result[4] -match '\d.{17}\d') { 49 | $NextRun = Get-Date $Matches[0] 50 | 51 | If (!($NextRun.DayOfWeek -match $Day)) { 52 | $DayIsWrong = $true 53 | } ElseIf ((Get-Date $NextRun -format 'hh:mm') -ne $Time) { 54 | $TimeIsWrong = $true 55 | } 56 | 57 | } Else { 58 | Write-Host 'ERROR: Could not parse Next Run time. Verify script and settings!' 59 | Exit 1001 60 | } 61 | 62 | 63 | If ($DayIsWrong -or $TimeIsWrong) { 64 | Write-Host ('Schedule parsed as {0} on {1}. Expected {2} on {3}.' -f (Get-Date $NextRun -format 'hh:mm'),$NextRun.DayOfWeek.ToString().Substring(0,3), $Time, $Day) 65 | Write-Host 'Reconfiguring Shedule' 66 | $Result = &schtasks.exe /Create /TN $TaskName /TR "$RestartScript" /RU SYSTEM /SC WEEKLY /D $Day /ST $Time /F 67 | If (!($Result -like 'SUCCESS:*')) { 68 | Write-Host "SCHTASKS.EXE failed. Verify script and settings." 69 | Exit 1001 70 | } 71 | } Else { 72 | Write-Host ('Schedule {0} on {1} Confirmed.' -F $Time, $Day) 73 | Exit 0 74 | } -------------------------------------------------------------------------------- /MAXfocus/Verify-MAXfocusConfig.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Compares existing configuration of a MAXfocus monitoring agent against 4 | default settings stored in this script. Can add missing default checks 5 | automatically. 6 | .DESCRIPTION 7 | The script is to be uploaded to your dashboard account as a user script. 8 | It can run both as a script check and as a scheduled task. You select 9 | check types to verify on a agent by giving the script parameters. 10 | .EXAMPLE 11 | Verify-MAXfocusConfig -Apply -All 12 | .EXAMPLE 13 | Verify-MAXfocusConfig -Apply -WinServiceCheck All 14 | .EXAMPLE 15 | Verify-MAXfocusConfig -Apply -Performance -SMART -ServerInterval 15 -All 16 | .OUTPUTS 17 | Correct XML configuration files that will reconfigure an MAXfocus agent 18 | upon agent restart. 19 | .LINK 20 | http://klemmestad.com/2014/12/22/automate-maxfocus-with-powershell/ 21 | .LINK 22 | https://www.maxfocus.com/remote-management/automated-maintenance 23 | .VERSION 24 | 1.25 25 | .FUNCTIONALITY 26 | When the script finds that checks has to be added it will create valid XML 27 | entries and add them to agent configuration files. It uses Windows scheduled 28 | tasks to restart agent after the script completes. 29 | #> 30 | 31 | #Region SETTINGS 32 | # A few settings are handled as parameters 33 | param ( 34 | [switch]$All = $false, # Accept all default check values in one go 35 | [switch]$Apply = $false, # -Apply will write new checks to configfiles and reload agent 36 | [string]$ReportMode = 'On', # -ReportMode will report missing checks, but not fail the script 37 | [switch]$Performance = $false, # Set to $false if you do not want performance checks 38 | [switch]$PingCheck = $false, # This is useful on a Fault History report. Otherwise useless. 39 | [switch]$MSSQL = $false, # Detect SQL servers 40 | [switch]$SMART = $false, # Enable physical disk check if SMART status is available 41 | [switch]$Backup = $false, # Configure a basic backup check if a compatible product is recognized 42 | [switch]$Antivirus = $false, # Configure an Antivirus check if a compatible product is recognized 43 | [switch]$LogChecks = $false, # Configure default log checks 44 | [string]$DriveSpaceCheck = $null, # Freespace as number+unit, i.e 10%, 5GB or 500MB 45 | [string]$WinServiceCheck = '',# "All" or "DefaultOnly". 46 | [string]$DiskSpaceChange, # percentage as integer 47 | [string]$ServerInterval = '15', # 5 or 15 minutes 48 | [string]$PCInterval = '60', # 30 or 60 minutes 49 | [string]$DSCHour = '8', # When DSC check should run in whole hours. Minutes not supported by agent. 50 | [switch]$Reset = $false, # A one-time reset switch that will remove overwrite existing checks in all chosen categories. 51 | [switch]$Debug = $false, 52 | [switch]$Verbose = $false, 53 | [string]$logfile, # A parameter always supplied by MAXfocus. We MUST accept it. 54 | [switch]$Library = $false # Used to source this script for its functions 55 | ) 56 | 57 | If ($Debug) { $Verbose = $true} 58 | 59 | # Enhanced Output-Host function to capture log info 60 | function Output-Host { 61 | [string]$Text = '' 62 | Foreach ($arg in $args) { $Text += $arg } 63 | Write-Host $Text 64 | # Include normal output in debug log 65 | Output-Debug $Text 66 | } 67 | 68 | 69 | # Output text to $logfile if Debug set 70 | function Output-Debug { 71 | If ($Debug) { 72 | [string]$Text = '' 73 | Foreach ($arg in $args) { $Text += $arg } 74 | ('{0}: {1}' -f (Get-Date),$Text) | Out-File -Append $logfile 75 | } 76 | } 77 | 78 | # Output text to STDOUT if Verbose set 79 | function Output-Verbose { 80 | If ($Verbose) { 81 | [string]$Text = 'VERBOSE: ' 82 | Foreach ($arg in $args) { $Text += $arg } 83 | Output-Host $Text 84 | } 85 | } 86 | 87 | If ($All) 88 | { 89 | Output-Verbose 'Parameter -All detected. Loading default values.' 90 | ## DEFAULT CHECKS 91 | $Performance = $true # Set to $false if you do not want performance checks 92 | $PingCheck = $false # This is useful on a Fault History report. Otherwise useless. 93 | $MSSQL = $true # Detect SQL servers 94 | $SMART = $true # Enable physical disk check if SMART status is available 95 | $Antivirus = $true # Configure an Antivirus check if a compatible product is recognized 96 | $DriveSpaceCheck = '10%' # Freespace as number+unit, i.e 10%, 5GB or 500MB 97 | $WinServiceCheck = 'All' # "All" or "Default". 98 | $DiskSpaceChange = 10 # percentage as integer 99 | $Backup = $true # Try to configure Backup Monitoring 100 | $LogChecks = $true # Configure default eventlog checks 101 | $ServerInterval = '5' 102 | $PCInterval = '30' 103 | } 104 | 105 | # Convert Reportmode to Boolean 106 | If ($ReportMode -Match 'On') { 107 | [bool]$ReportMode = $true 108 | } Else { 109 | [bool]$ReportMode = $false 110 | } 111 | 112 | # Test DriveSpaceCheck 113 | If (($DriveSpaceCheck) -and ($DriveSpaceCheck -match '\d+(%|MB|GB)$')) { 114 | Output-Verbose ('Parameter -DrivespaceCheck {0} validated OK.' -f $DriveSpaceCheck) 115 | } ElseIf ($DriveSpaceCheck) { 116 | Output-Host ('ERROR: -DriveSpaceCheck {0} could not be validated. Use 10%, 10MB or 10GB where "10" is any integer.' -f $DriveSpaceCheck) 117 | Output-Host 'WARNING: Ignoring -DriveSpaceCheck.' 118 | $DriveSpaceCheck = '' 119 | } 120 | 121 | # Test WinServiceCheck 122 | If (($WinServiceCheck) -and ('All', 'Default', 'DefaultOnly' -contains $WinServiceCheck)) { 123 | Output-Verbose ('Parameter -WinServiceCheck {0} validated OK.' -f $WinServiceCheck) 124 | } ElseIf ($WinServiceCheck) { 125 | Output-Host ('ERROR: -WinServiceCheck {0} could not be validated. Use All, Default or DefaultOnly' -f $WinServiceCheck) 126 | Output-Host 'WARNING: Ignoring -WinServiceCheck.' 127 | $WinServiceCheck = '' 128 | } 129 | 130 | # Test DiskSpaceChange 131 | If ($DiskSpaceChange) { 132 | $x2 = 0 133 | $isNum = [System.Int32]::TryParse($DiskSpaceChange, [ref]$x2) 134 | If ($isNUM) { 135 | [int]$DiskSpaceChange = $DiskSpaceChange 136 | Output-Verbose ('Parameter -DiskSpaceChange {0} validated OK.' -f $DiskSpaceChange) 137 | } Else { 138 | Output-Host ('ERROR: -DiskSpaceChange {0} could not be validated. Use a valid integer.' -f $DiskSpaceChange) 139 | Output-Host 'WARNING: Ignoring -DiskSpaceChange.' 140 | [string]$DiskSpaceChange = '' 141 | } 142 | } 143 | 144 | # Test ServerInterval 145 | If ('5', '15' -contains $ServerInterval) { 146 | Output-Verbose ('Parameter -ServerInterval {0} validated OK.' -f $ServerInterval) 147 | } Else { 148 | Output-Host ('ERROR: -ServerInterval {0} could not be validated. Use 5 or 15.' -f $ServerInterval) 149 | Output-Host 'WARNING: Setting value of -ServerInterval to default of 15.' 150 | $ServerInterval = '15' 151 | } 152 | 153 | # Test PCInterval 154 | If ('30', '60' -contains $PCInterval) { 155 | Output-Verbose ('Parameter -PCInterval {0} validated OK.' -f $PCInterval) 156 | } Else { 157 | Output-Host ('ERROR: -PCInterval {0} could not be validated. Use 30 or 60.' -f $PCInterval) 158 | Output-Host 'WARNING: Setting value of -PCInterval to default of 60.' 159 | $PCInterval = '60' 160 | } 161 | 162 | # Test DSChour 163 | If ($DSChour) { 164 | $x2 = 0 165 | $isNum = [System.Int32]::TryParse($DSChour, [ref]$x2) 166 | If (($isNUM) -and ($x2 -ge 0 -and $x2 -lt 24)) { 167 | Output-Verbose ('Parameter -DSChour {0} validated OK.' -f $DSChour) 168 | } Else { 169 | Output-Host ('ERROR: -DSChour {0} could not be validated. Use a valid number between 0 (12 AM) and 23 (11 PM).' -f $DSChour) 170 | Output-Host 'WARNING: Setting value of -DSChour to default of 8.' 171 | [string]$DSChour = '8' 172 | } 173 | } 174 | 175 | # Set strict mode if running interactively. Very useful when testing new code 176 | If (!((Get-WmiObject Win32_Process -Filter "ProcessID=$PID").CommandLine -match '-noni')) { 177 | Output-Debug 'WARNING: Running Interactively. Using Strict Mode.' 178 | Write-Warning 'Running Interactively. Using Strict Mode.' 179 | Set-StrictMode -Version 2 180 | } 181 | #EndRegion 182 | 183 | #Region Functions 184 | function Restart-MAXfocusService ([bool]$Safely=$true) { 185 | # Save all relevant config files 186 | If ($Safely) { 187 | # Update last runtime to prevent changes too often 188 | [int]$currenttime = $(get-date -UFormat %s) -replace ',','.' # Handle decimal comma 189 | $settingsContent['DAILYSAFETYCHECK']['RUNTIME'] = $currenttime 190 | } 191 | # Clear lastcheckday to make DSC run immediately 192 | $settingsContent['DAILYSAFETYCHECK']['LASTCHECKDAY'] = '0' 193 | Out-IniFile $settingsContent $IniFile.Replace('.ini','.newini') 194 | # Save XML files to NEW files 195 | ForEach ($Set in $Sets) { 196 | $XmlConfig[$Set].Save($XmlFile[$Set].Replace('.xml','.newxml')) 197 | } 198 | 199 | # Prepare restartscript 200 | $RestartScript = $env:TEMP + '\RestartMAXfocusAgent.cmd' 201 | $RestartScriptContent = @" 202 | net stop "Advanced Monitoring Agent" 203 | cd "$gfimaxpath" 204 | move /y 247_config.newxml 247_config.xml 205 | move /y DSC_config.newxml DSC_config.xml 206 | move /y settings.newini settings.ini 207 | net start "Advanced Monitoring Agent" 208 | Del /F "$RestartScript" 209 | "@ 210 | $RestartScriptContent | Out-File -Encoding OEM $RestartScript 211 | # Start time in the future 212 | $JobTime = (Get-Date).AddMinutes(-2) 213 | $StartTime = Get-Date $JobTime -Format HH:mm 214 | $TaskName = 'Restart Advanced Monitoring Agent' 215 | $Result = &schtasks.exe /Create /TN $TaskName /TR "$RestartScript" /RU SYSTEM /SC ONCE /ST $StartTime /F 2>&1 216 | If ($Result) { 217 | Output-Debug 'Restarting Agent using scheduled task now.' 218 | $Result = &schtasks.exe /run /TN "$TaskName" 2>&1 219 | } 220 | 221 | If ($LASTEXITCODE -ne 0) { 222 | Output-Host 'SCHTASKS.EXE failed. Could not restart agent. Changes lost.' 223 | } 224 | } 225 | 226 | function New-MAXfocusCheck ( 227 | [string]$checktype, 228 | [string]$option1, 229 | [string]$option2, 230 | [string]$option3, 231 | [string]$option4, 232 | [string]$option5, 233 | [string]$option6) { 234 | 235 | Switch ($checktype) { 236 | 'DriveSpaceCheck' { 237 | $object = '' | Select driveletter,freespace,spaceunits 238 | $checkset = '247' 239 | $object.driveletter = $option1 240 | $object.freespace = $FreeSpace 241 | $object.spaceunits = $SpaceUnits 242 | } 243 | 'DiskSpaceChange' { 244 | $object = '' | Select driveletter,threshold 245 | $checkset = 'DSC' 246 | $object.driveletter = $option1 247 | $object.threshold = $DiskSpaceChange 248 | } 249 | 'WinServiceCheck' { 250 | $object = '' | Select servicename,servicekeyname,failcount,startpendingok,restart,consecutiverestartcount,cumulativerestartcount 251 | $checkset = '247' 252 | $object.servicename = $option1 253 | $object.servicekeyname = $option2 254 | $object.failcount = 1 # How many consecutive failures before check fails 255 | $object.startpendingok = 0 # Is Startpending OK, 1 0 Yes, 0 = No 256 | $object.restart = 1 # Restart = 1 (Restart any stopped service as default) 257 | $object.consecutiverestartcount = 2 # ConsecutiveRestartCount = 2 (Fail if service doesnt run after 2 tries) 258 | $object.cumulativerestartcount = '4|24' # Cumulative Restart Count = 4 in 24 hours 259 | } 260 | 'PerfCounterCheck' { 261 | $object = '' | Select type,instance,threshold1,threshold2,threshold3,threshold4 262 | $checkset = '247' 263 | Switch ($option1) { 264 | 'Queue' { 265 | $object.type = 1 266 | If ($option2) { 267 | $object.threshold1 = $option2 268 | } Else { 269 | $object.threshold1 = 2 # Recommended threshold by Microsoft for physical servers. 270 | } 271 | } 272 | 'CPU' { 273 | $object.type = 2 274 | If ($option2) { 275 | $object.threshold1 = $option2 276 | } Else { 277 | $object.threshold1 = 99 # We are talking ALERTS here. We are not doing this for fun. 278 | } 279 | } 280 | 'RAM' { 281 | $object.type = 3 282 | $object.instance = 2 # Fails if committed memory is more than twice that of physical RAM 283 | $object.threshold1 = 10 # Fails if average available RAM is less than 10 MB 284 | $object.threshold2 = 5000 # Fails if average pages/sec > 5000 285 | $object.threshold3 = 99 # % Page file usage 286 | If ($option2) { # Nonpaged pool 287 | $object.threshold4 = $option2 288 | } Else { 289 | $object.threshold4 = 128 290 | } 291 | } 292 | 'Net' { 293 | $object.type = 4 294 | $object.instance = $option2 295 | $object.threshold1 = 80 # We don't want alerts unless there really are problems 296 | } 297 | 'Disk' { 298 | $object.type = 5 299 | $object.instance = $option2 300 | If ($option3) { 301 | $object.threshold1 = $option3 # Read queue 302 | $object.threshold2 = $option3 # Write queue 303 | } Else { 304 | $object.threshold1 = 4 # Read queue 305 | $object.threshold2 = 4 # Write queue 306 | } 307 | $object.threshold3 = 100 # Disk time, and again we are talking ALERTS 308 | } 309 | } 310 | } 311 | 'PingCheck' { 312 | $object = '' | Select name,pinghost,failcount 313 | $checkset = '247' 314 | $object.name = $option1 315 | $object.pinghost = $option2 316 | } 317 | 'BackupCheck' { 318 | $object = '' | Select BackupProduct,checkdays,partial,count 319 | $checkset = 'DSC' 320 | $object.backupproduct = $option1 321 | $object.checkdays = 'MTWTFSS' 322 | $object.partial = 0 323 | If ($option2) { 324 | $object.count = $option2 325 | } Else { 326 | $object.count = 99 # Dont know jobcount, make check fail 327 | } 328 | } 329 | 'AVUpdateCheck' { 330 | $object = '' | Select AVProduct,checkdays 331 | $checkset = 'DSC' 332 | $object.avproduct = $option1 333 | $object.checkdays = 'MTWTFSS' 334 | } 335 | 'CriticalEvents' { 336 | $object = '' | Select eventlog,mode,option 337 | $checkset = 'DSC' 338 | $object.eventlog = $option1 339 | If ($option2) { 340 | $object.mode = $option2 341 | } Else { 342 | $object.mode = 0 # Report mode 343 | } 344 | $object.option = 0 345 | } 346 | 'EventLogCheck' { 347 | $object = '' | Select uid,log,flags,ids,source,contains,exclude,ignoreexclusions 348 | $checkset = 'DSC' 349 | $object.uid = $option1 350 | $object.log = $option2 351 | $object.flags = $option3 352 | $object.source = $option4 353 | If($option5) { 354 | $object.ids = $option5 355 | } Else { 356 | $object.ids = '*' 357 | } 358 | $object.contains = '' 359 | $object.exclude = '' 360 | $object.ignoreexclusions = 'false' 361 | } 362 | 'VulnerabilityCheck' { 363 | $object = '' | Select schedule1,schedule2,devtype,mode,autoapproval,scandelaytime,failureemails,rebootdevice,rebootcriteria 364 | $checkset = 'DSC' 365 | $object.schedule1 = '' 366 | $object.schedule2 = '2|0|{0}|0|{1}|0' -f $option1, $option2 367 | If ($AgentMode -eq 'Server') { 368 | $object.devtype = 2 369 | } Else { 370 | $object.devtype = 1 371 | } 372 | $object.mode = 0 373 | $object.autoapproval = '2|2|2|2|2,2|2|2|2|2' 374 | $object.scandelaytime = '' 375 | $object.failureemails = 1 376 | $object.rebootdevice = 0 377 | $object.rebootcriteria = '0|1' 378 | } 379 | 'PhysDiskCheck' { 380 | $object = '' | Select volcheck 381 | $checkset = 'DSC' 382 | $object.volcheck = 1 383 | } 384 | } 385 | 386 | $XmlCheck = $XmlConfig[$checkset].CreateElement($checktype) 387 | 388 | # Modified and uid are attributes, not properties. Do not set uid for new checks. 389 | # Let the agent deal with that. 390 | $XmlCheck.SetAttribute('modified', '1') 391 | 392 | Foreach ($property in $object|Get-Member -MemberType NoteProperty) { 393 | $xmlProperty = $XmlConfig[$checkset].CreateElement($property.Name) 394 | $propertyValue = $object.($property.Name) 395 | # Is this a number? 396 | If ([bool]($propertyValue -as [int]) -or $propertyValue -eq '0') { 397 | # If its a number we just dump it in there 398 | $xmlProperty.set_InnerText($propertyValue) 399 | } ElseIf ($propertyValue) { 400 | # If it is text we encode it in CDATA 401 | $rs = $xmlProperty.AppendChild($XmlConfig[$checkset].CreateCDataSection($propertyValue)) 402 | } 403 | # Add Property to Check element 404 | $rs = $xmlCheck.AppendChild($xmlProperty) 405 | } 406 | $rs = $XmlConfig[$checkset].checks.AppendChild($XmlCheck) 407 | $Script:NewChecks += $XmlCheck 408 | $Script:ConfigChanged = $true 409 | 410 | } 411 | 412 | function Get-XmlPropertyValue ($xmlProperty) { 413 | If ($XmlProperty -is [System.Xml.XmlElement]) { 414 | Return $XmlProperty.InnerText 415 | } Else { 416 | Return $XmlProperty 417 | } 418 | } 419 | 420 | 421 | function Get-MAXfocusCheckList ([string]$checktype, [string]$property, [string]$value, [bool]$ExactMatch = $true ) { 422 | $return = @() 423 | $ChecksToFilter = @() 424 | $ChecksToFilter = $XmlConfig.Values | % {$_.SelectNodes('//{0}' -f $checktype)} 425 | If (!($ChecksToFilter)) { Return } 426 | If ($value) { 427 | Foreach ($XmlCheck in $ChecksToFilter) { 428 | $XmlValue = Get-XmlPropertyValue $XmlCheck.$property 429 | If ($ExactMatch) { 430 | If ($XmlValue -eq $value) { $return += $XmlCheck } 431 | } Else { 432 | If ($XmlValue -match $value) { $return += $XmlCheck } 433 | } 434 | } 435 | } Else { 436 | Return $ChecksToFilter 437 | } 438 | Return $return 439 | } 440 | 441 | function Remove-MAXfocusChecks ([array]$ChecksToRemove) { 442 | If (!($ChecksToRemove.Count -gt 0)) { Return } 443 | ForEach ($XmlCheck in $ChecksToRemove) { 444 | $XmlCheck.ParentNode.RemoveChild($XmlCheck) 445 | $Script:RemoveChecks += $XmlCheck 446 | } 447 | $Script:ConfigChanged = $true 448 | } 449 | 450 | function Get-MAXfocusCheck ([System.Xml.XmlElement]$XmlCheck) { 451 | $ChecksToFilter = @() 452 | $ChecksToFilter = Get-MAXfocusCheckList $XmlCheck.LocalName 453 | If ($ChecksToFilter.Count -eq 0) { Return $false } 454 | Foreach ($ExistingCheck in $ChecksToFilter) { 455 | $Match = $True 456 | Foreach ($ChildNode in $XmlCheck.ChildNodes) { 457 | If ($ChildNode.LocalName -eq 'uid') { Continue } 458 | $property = $ChildNode.LocalName 459 | $ExistingValue = Get-XmlPropertyValue $ExistingCheck.$property 460 | If ($ChildNode.Innertext -ne $ExistingValue) { 461 | $Match = $false 462 | Break 463 | } 464 | If ($Match) { 465 | Return $ExistingCheck 466 | } 467 | } 468 | } 469 | } 470 | 471 | # Downloaded from 472 | # http://blogs.technet.com/b/heyscriptingguy/archive/2011/08/20/use-powershell-to-work-with-any-ini-file.aspx 473 | # modified to use ordered list by me 474 | function Get-IniContent ($filePath) { 475 | $ini = New-Object System.Collections.Specialized.OrderedDictionary 476 | switch -regex -file $FilePath 477 | { 478 | '^\[(.+)\]' # Section 479 | { 480 | $section = $matches[1] 481 | $ini[$section] = New-Object System.Collections.Specialized.OrderedDictionary 482 | $CommentCount = 0 483 | } 484 | "^(;.*)$" # Comment 485 | { 486 | $value = $matches[1] 487 | $CommentCount = $CommentCount + 1 488 | $name = 'Comment' + $CommentCount 489 | $ini[$section][$name] = $value 490 | } 491 | '(.+?)\s*=(.*)' # Key 492 | { 493 | $name,$value = $matches[1..2] 494 | $ini[$section][$name] = $value 495 | } 496 | } 497 | return $ini 498 | } 499 | # Downloaded from 500 | # http://blogs.technet.com/b/heyscriptingguy/archive/2011/08/20/use-powershell-to-work-with-any-ini-file.aspx 501 | # Modified to force overwrite by me 502 | function Out-IniFile($InputObject, $FilePath) { 503 | $outFile = New-Item -ItemType file -Path $Filepath -Force 504 | foreach ($i in $InputObject.keys) 505 | { 506 | if ('Hashtable','OrderedDictionary' -notcontains $($InputObject[$i].GetType().Name)) 507 | { 508 | #No Sections 509 | Add-Content -Path $outFile -Value "$i=$($InputObject[$i])" 510 | } else { 511 | #Sections 512 | Add-Content -Path $outFile -Value "[$i]" 513 | Foreach ($j in ($InputObject[$i].keys | Sort-Object)) 514 | { 515 | if ($j -match '^Comment[\d]+') { 516 | Add-Content -Path $outFile -Value "$($InputObject[$i][$j])" 517 | } else { 518 | Add-Content -Path $outFile -Value "$j=$($InputObject[$i][$j])" 519 | } 520 | 521 | } 522 | Add-Content -Path $outFile -Value '' 523 | } 524 | } 525 | } 526 | 527 | # Small function to give missing checks output some structure 528 | function Format-Output($ArrayOfChecks) { 529 | $Result = @() 530 | Foreach ($CheckItem in $ArrayOfChecks){ 531 | Switch ($CheckItem.LocalName) { 532 | {'DriveSpaceCheck','DiskSpaceChange' -contains $_ } { 533 | $Result += $CheckItem.LocalName + ' ' + $CheckItem.driveletter.InnerText } 534 | 'WinServicecheck' { 535 | $Result += $CheckItem.LocalName + ' ' + $CheckItem.servicename.InnerText } 536 | 'PerfCounterCheck' { 537 | Switch ($CheckItem.type) { 538 | '1' { $Result += $CheckItem.LocalName + ' Processor Queue Length'} 539 | '2' { $Result += $CheckItem.LocalName + ' Average CPU Usage'} 540 | '3' { $Result += $CheckItem.LocalName + ' Memory Usage'} 541 | '4' { $Result += $CheckItem.LocalName + ' Network Interface ' + $CheckItem.instance.InnerText} 542 | '5' { $Result += $CheckItem.LocalName + ' Physical Disk ' + $CheckItem.instance.InnerText} 543 | }} 544 | {'PingCheck','AVUpdateCheck','BackupCheck','FileSizeCheck' -contains $CheckItem.LocalName } { 545 | $Result += $CheckItem.LocalName + ' ' + $CheckItem.name.InnerText } 546 | 'EventLogCheck' { 547 | $Result += $CheckItem.LocalName + ' ' + $CheckItem.log.InnerText } 548 | 'CriticalEvents' { 549 | switch ($CheckItem.mode) { 550 | 0 { $Result += $CheckItem.LocalName + ' ' + $CheckItem.eventlog.InnerText + ' (Report)' } 551 | 1 { $Result += $CheckItem.LocalName + ' ' + $CheckItem.eventlog.InnerText + ' (Alert)' }}} 552 | default { 553 | $Result += $CheckItem.LocalName } 554 | 555 | } 556 | 557 | } 558 | $Result += '' # Add blank line 559 | $Result 560 | } 561 | 562 | ## Adopted from https://gallery.technet.microsoft.com/scriptcenter/Get-SQLInstance-9a3245a0 563 | ## I changed it to check both 32 and 64 bit 564 | Function Get-SQLInstance { 565 | $Computer = $env:COMPUTERNAME 566 | Try { 567 | $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $Computer) 568 | $baseKeys = 'SOFTWARE\\Microsoft\\Microsoft SQL Server', 569 | 'SOFTWARE\\Wow6432Node\\Microsoft\\Microsoft SQL Server' 570 | ForEach ($basekey in $baseKeys) 571 | { 572 | If ($reg.OpenSubKey($basekey)) { 573 | $regPath = $basekey 574 | } Else { 575 | Continue 576 | } 577 | $regKey= $reg.OpenSubKey("$regPath") 578 | If ($regKey.GetSubKeyNames() -contains 'Instance Names') { 579 | $regKey= $reg.OpenSubKey("$regpath\\Instance Names\\SQL" ) 580 | $instances = @($regkey.GetValueNames()) 581 | } ElseIf ($regKey.GetValueNames() -contains 'InstalledInstances') { 582 | $isCluster = $False 583 | $instances = $regKey.GetValue('InstalledInstances') 584 | } Else { 585 | Continue 586 | } 587 | If ($instances.count -gt 0) { 588 | ForEach ($instance in $instances) { 589 | $nodes = New-Object System.Collections.Arraylist 590 | $clusterName = $Null 591 | $isCluster = $False 592 | $instanceValue = $regKey.GetValue($instance) 593 | $instanceReg = $reg.OpenSubKey("$regpath\\$instanceValue") 594 | If ($instanceReg.GetSubKeyNames() -contains 'Cluster') { 595 | $isCluster = $True 596 | $instanceRegCluster = $instanceReg.OpenSubKey('Cluster') 597 | $clusterName = $instanceRegCluster.GetValue('ClusterName') 598 | $clusterReg = $reg.OpenSubKey('Cluster\\Nodes') 599 | $clusterReg.GetSubKeyNames() | ForEach { 600 | $null = $nodes.Add($clusterReg.OpenSubKey($_).GetValue('NodeName')) 601 | } 602 | } 603 | $instanceRegSetup = $instanceReg.OpenSubKey('Setup') 604 | Try { 605 | $edition = $instanceRegSetup.GetValue('Edition') 606 | } Catch { 607 | $edition = $Null 608 | } 609 | Try { 610 | $ErrorActionPreference = 'Stop' 611 | #Get from filename to determine version 612 | $servicesReg = $reg.OpenSubKey('SYSTEM\\CurrentControlSet\\Services') 613 | $serviceKey = $servicesReg.GetSubKeyNames() | Where { 614 | $_ -match "$instance" 615 | } | Select -First 1 616 | $service = $servicesReg.OpenSubKey($serviceKey).GetValue('ImagePath') 617 | $file = $service -replace '^.*(\w:\\.*\\sqlservr.exe).*','$1' 618 | $version = (Get-Item ("\\$Computer\$($file -replace ':',"$")")).VersionInfo.ProductVersion 619 | } Catch { 620 | #Use potentially less accurate version from registry 621 | $Version = $instanceRegSetup.GetValue('Version') 622 | } Finally { 623 | $ErrorActionPreference = 'Continue' 624 | } 625 | New-Object PSObject -Property @{ 626 | Computername = $Computer 627 | SQLInstance = $instance 628 | Edition = $edition 629 | BitVersion = {Switch -regex ($basekey) { 630 | 'Wow6432Node' { '32-bit' } 631 | Default { '64-bit' } 632 | }}.InvokeReturnAsIs() 633 | Version = $version 634 | Caption = {Switch -Regex ($version) { 635 | '^14' {'SQL Server 2014';Break} 636 | '^11' {'SQL Server 2012';Break} 637 | '^10\.5' {'SQL Server 2008 R2';Break} 638 | '^10' {'SQL Server 2008';Break} 639 | '^9' {'SQL Server 2005';Break} 640 | '^8' {'SQL Server 2000';Break} 641 | Default {'Unknown'} 642 | }}.InvokeReturnAsIs() 643 | isCluster = $isCluster 644 | isClusterNode = ($nodes -contains $Computer) 645 | ClusterName = $clusterName 646 | ClusterNodes = ($nodes -ne $Computer) 647 | FullName = { 648 | If ($Instance -eq 'MSSQLSERVER') { 649 | $Computer 650 | } Else { 651 | "$($Computer)\$($instance)" 652 | } 653 | }.InvokeReturnAsIs() 654 | FullRecoveryModel = '' 655 | } 656 | } 657 | } 658 | } 659 | } Catch { 660 | Write-Warning ('{0}: {1}' -f $Computer,$_.Exception.Message) 661 | } 662 | } 663 | 664 | function Get-TMScanType { 665 | $tmlisten = Get-WmiObject Win32_Service | where { $_.Name -eq 'tmlisten' } 666 | $TrendDir = Split-Path $tmlisten.PathName.Replace( '"','') -Parent 667 | $SmartPath = "{0}\*icrc`$oth.*" -f $TrendDir 668 | $ConvPath = "{0}\*lpt`$vpn.*" -f $TrendDir 669 | $SmartScan = Test-Path $SmartPath 670 | $ConvScan = Test-Path $ConvPath 671 | 672 | If (($SmartScan) -and ($ConvScan)) { 673 | $SmartFile = Get-Item $SmartPath | Sort LastAccessTime -Descending | Select -First 1 674 | $ConvFile = Get-Item $ConvPath | Sort LastAccessTime -Descending | Select -First 1 675 | If ($SmartFile.LastAccessTime -gt $ConvFile.LastAccessTime) { 676 | $ConvScan = $false 677 | } Else { 678 | $SmartScan = $false 679 | } 680 | } 681 | 682 | If ($SmartScan) { 683 | Return 'Smart' 684 | } ElseIf ($ConvScan) { 685 | Return 'Conventional' 686 | } Else { 687 | Return $false 688 | } 689 | } 690 | 691 | Function Is-SMARTavailable () { 692 | $PrevErrorAction = $ErrorActionPreference 693 | $ErrorActionPreference = 'Stop' 694 | Try { 695 | $Result = Get-WmiObject MSStorageDriver_FailurePredictStatus -Namespace root\wmi 696 | } Catch { 697 | $ErrorActionPreference = $PrevErrorAction 698 | Return $False 699 | } 700 | $ErrorActionPreference = $PrevErrorAction 701 | Return $True 702 | } 703 | 704 | #EndRegion 705 | 706 | ## Exit if sourced as Library 707 | If ($Library) { Exit 0 } 708 | 709 | #Region Setup 710 | # Force the script to output something to STDOUT, else errors may cause script timeout. 711 | Output-Host ' ' 712 | 713 | 714 | $DefaultLogChecks = @( 715 | # @{ "log" = "Application|Application Hangs"; # Application log | Human readable name 716 | # "flags" = 32512; 717 | # "ids" = "*"; 718 | # "source" = "Application Hang" } 719 | @{ 'log' = 'System|NTFS Errors'; 720 | 'flags' = 32513; 721 | 'ids' = '*'; 722 | 'source' = 'Ntfs*' } 723 | @{ 'log' = 'System|BSOD Stop Errors'; 724 | 'flags' = 32513; 725 | 'ids' = '1003'; 726 | 'source' = 'System' } 727 | ) 728 | 729 | $DefaultCriticalEvents = @( 730 | @{ 'eventlog' = 'Directory Service'; 731 | 'mode' = 1 } 732 | @{ 'eventlog' = 'File Replication Service'; 733 | 'mode' = 1 } 734 | @{ 'eventlog' = 'HardwareEvents'; 735 | 'mode' = 1 } 736 | @{ 'eventlog' = 'System'; 737 | 'mode' = 0 } 738 | @{ 'eventlog' = 'Application'; 739 | 'mode' = 0 } 740 | ) 741 | 742 | # Services you do not wish to monitor, regardless. Important list when you 743 | # are adding service checks automatically 744 | $DoNotMonitorServices = @( 745 | 'wuauserv', # Windows Update Service. Does not run continously. 746 | 'gupdate', 'gupdatem', # Google Update Services. Does not always run. 747 | 'AdobeARMservice', # Another service you may not want to monitor 748 | 'Windows Agent Maintenance Service', # Clean up after N-Able 749 | 'Windows Agent Service', # Clean up after N-Able 750 | 'RSMWebServer', # Clean up after N-Able 751 | 'gpsvc' # Group Policy Client 752 | ) 753 | $AlwaysMonitorServices = @( # Services that always are to be monitored if present and autorun 754 | 'wecsvc' # Windows Event Collector 755 | ) 756 | 757 | 758 | # Find "Advanced Monitoring Agent" service and use path to locate files 759 | $gfimaxagent = Get-WmiObject Win32_Service | Where-Object { $_.Name -eq 'Advanced Monitoring Agent' } 760 | $gfimaxexe = $gfimaxagent.PathName 761 | $gfimaxpath = Split-Path $gfimaxagent.PathName.Replace('"','') -Parent 762 | 763 | # XML Document objects 764 | $XmlConfig = @{} 765 | $AgentConfig = New-Object -TypeName XML 766 | $DeviceConfig = New-Object -TypeName XML 767 | 768 | # XML Document Pathnames 769 | $XmlFile = @{} 770 | $AgentFile = $gfimaxpath + '\agentconfig.xml' 771 | $DeviceFile = $gfimaxpath + '\Config.xml' 772 | $LastChangeFile = $gfimaxpath + '\LastChange.log' 773 | 774 | # We need an array of hashes to remember which checks to add 775 | $NewChecks = @() 776 | $RemoveChecks = @() 777 | $oldChecks = @() 778 | $ChangedSettings = @{} 779 | 780 | # The prefix to the config files we need to read 781 | $Sets = @('247', 'DSC') 782 | 783 | # An internal counter for new checks since we store them in a hashtable 784 | [int]$uid = 1 785 | 786 | $IniFile = $gfimaxpath + '\settings.ini' 787 | $ConfigChanged = $false 788 | $settingsChanged = $false 789 | 790 | # Read ini-files 791 | $settingsContent = Get-IniContent($IniFile) 792 | $servicesContent = Get-IniContent($gfimaxpath + '\services.ini') 793 | 794 | 795 | # First of all, check if it is safe to make any changes 796 | If ($Apply) { 797 | # Make sure a failure to aquire settings correctly will disable changes 798 | $Apply = $false 799 | If ($settingsContent['DAILYSAFETYCHECK']['RUNTIME']) { # This setting must exist 800 | $lastRuntime = $settingsContent['DAILYSAFETYCHECK']['RUNTIME'] 801 | [int]$currenttime = $((Get-Date).touniversaltime() | get-date -UFormat %s) -replace ',','.' # Handle decimal comma 802 | $timeSinceLastRun = $currenttime - $lastRuntime 803 | If($lastRuntime -eq 0 -or $timeSinceLastRun -gt 360){ 804 | # If we have never been run or it is at least 6 minutes ago 805 | # enable changes again 806 | $Apply = $true 807 | } 808 | } 809 | If (!($Apply)) { 810 | Output-Host 'Changes Applied.' 811 | If (Test-Path $LastChangeFile) { 812 | # Print last change to STDOUT 813 | Output-Host '------------------------------------------------------' 814 | Get-Content $LastChangeFile 815 | Output-Host '------------------------------------------------------' 816 | } 817 | Exit 0 # SUCCESS 818 | } 819 | } 820 | 821 | 822 | ForEach ($Set in $Sets) { 823 | $XmlConfig[$Set] = New-Object -TypeName XML 824 | $XmlFile[$Set] = $gfimaxpath + '\{0}_Config.xml' -f $Set 825 | If (Test-Path $XmlFile[$Set]) { 826 | $XmlConfig[$Set].Load($XmlFile[$Set]) 827 | $XmlConfig[$Set].DocumentElement.SetAttribute('modified','1') 828 | } Else { 829 | # File does not exist. Create a new, emtpy XML document 830 | $XmlConfig[$Set] = New-Object -TypeName XML 831 | $decl = $XmlConfig[$Set].CreateXmlDeclaration('1.0', 'ISO-8859-1', $null) 832 | $rootNode = $XmlConfig[$Set].CreateElement('checks') 833 | $result = $XmlConfig[$Set].InsertBefore($decl, $XmlConfig[$Set].DocumentElement) 834 | $result = $XmlConfig[$Set].AppendChild($rootNode) 835 | 836 | # Mark checks as modified. We will onøy write this to disk if we have modified anything 837 | $result = $rootNode.SetAttribute('modified', '1') 838 | } 839 | 840 | } 841 | 842 | 843 | # Read agent config 844 | $AgentConfig.Load($AgentFile) 845 | 846 | # Read autodetected machine info 847 | $DeviceConfig.Load($DeviceFile) 848 | 849 | # Check Agent mode, workstation or server 850 | $AgentMode = $AgentConfig.agentconfiguration.agentmode 851 | 852 | #EndRegion 853 | 854 | # Set interval according to $AgentMode 855 | If ($AgentMode -eq 'server') { $247Interval = $ServerInterval } 856 | Else { $247Interval = $PCInterval } 857 | 858 | #Region Monitoring Settings 859 | # Check intervals. They can be modified together with other files. 860 | If ($settingsContent['247CHECK']['INTERVAL'] -ne $247Interval) { 861 | $settingsContent['247CHECK']['INTERVAL'] = $247Interval 862 | $ChangedSettings['247_Interval'] = $247Interval 863 | $ConfigChanged = $true 864 | } 865 | 866 | If ($settingsContent['DAILYSAFETYCHECK']['HOUR'] -ne $DSCHour) { 867 | $settingsContent['DAILYSAFETYCHECK']['HOUR'] = $DSCHour 868 | $ChangedSettings['DSC_Hour'] = $DSCHour 869 | $ConfigChanged = $true 870 | } 871 | 872 | #EndRegion 873 | 874 | # Check for new services that we'd like to monitor' 875 | If ($settingsContent['247CHECK']['ACTIVE'] -eq '1') { 876 | #Region 24/7 Checks 877 | 878 | If ($Reset) { 879 | $CheckTypes = @() 880 | If ($DriveSpaceCheck) {$CheckTypes += 'DriveSpaceCheck'} 881 | If ($WinServiceCheck) {$CheckTypes += 'WinServiceCheck'} 882 | If ($Performance) {$CheckTypes += 'PerfCounterCheck'} 883 | If ($PingCheck) {$CheckTypes += 'PingCheck'} 884 | Foreach ($OldCheck in $XmlConfig['247'].checks.ChildNodes) { 885 | If ($CheckTypes.Contains($OldCheck.LocalName)) { 886 | $OldCheck.ParentNode.RemoveChild($OldCheck) 887 | } 888 | } 889 | } 890 | ## DRIVESPACECHECK 891 | If ($DriveSpaceCheck) { 892 | # Process parameters that need processing 893 | $SpaceMatch = '^([0-9]+)([gmb%]+)' 894 | $Spacetype = $DriveSpaceCheck -replace $SpaceMatch,'$2' 895 | $FreeSpace = $DriveSpaceCheck -replace $SpaceMatch,'$1' 896 | 897 | Switch ($Spacetype.ToUpper().Substring(0,1)) { # SpaceUnits: 0 = Bytes, 1 = MBytes, 2 = GBytes, 3 = Percent 898 | 'B' { $SpaceUnits = 0 } 899 | 'M' { $SpaceUnits = 1 } 900 | 'G' { $SpaceUnits = 2 } 901 | '%' { $SpaceUnits = 3 } 902 | } 903 | 904 | # Get current fixed drives from WMI 905 | $DetectedDrives = GET-WMIOBJECT -query "SELECT * from win32_logicaldisk where DriveType = '3'" | select -Expandproperty DeviceID 906 | 907 | # Add any disk not currently in CurrentDiskSpaceChecks 908 | foreach ($Disk in $DetectedDrives) { 909 | If (($Disk -ne $env:SystemDrive) -and ($AgentMode -eq 'workstation')){ 910 | # Workstations are only monitoring %SystemDrive% 911 | Continue 912 | } 913 | $DriveLetter = $Disk + '\' 914 | $oldChecks = Get-MAXfocusCheckList DriveSpaceCheck driveletter $DriveLetter 915 | If (!($oldChecks)) { 916 | New-MAXfocusCheck DriveSpaceCheck $DriveLetter 917 | } 918 | } 919 | } 920 | 921 | ## WINSERVICECHECK 922 | # By default we only monitor services on servers 923 | If (('All', 'Default' -contains $WinServiceCheck) -and ($AgentMode -eq 'server')) { 924 | # We really dont want to keep annoying services in our setup 925 | Foreach ($service in $DoNotMonitorServices) { 926 | $oldChecks = Get-MAXfocusCheckList WinServiceCheck servicekeyname $service 927 | If ($oldChecks) { 928 | Remove-MAXfocusChecks $oldChecks 929 | } 930 | } 931 | # An array to store names of services to monitor 932 | $ServicesToMonitor = @() 933 | 934 | ## SERVICES TO MONITOR 935 | If ($WinServiceCheck -eq 'Default') { # Only add services that are listed in services.ini 936 | 937 | # Get all currently installed services with autostart enabled from WMI 938 | $autorunsvc = Get-WmiObject Win32_Service | 939 | Where-Object { $_.StartMode -eq 'Auto' } | select Displayname,Name 940 | 941 | Foreach ($service in $autorunsvc) { 942 | If (($servicesContent['SERVICES'][$service.Name] -eq '1') -or ($AlwaysMonitorServices -contains $service.Name)) { 943 | $ServicesToMonitor += $service 944 | } 945 | } 946 | } Else { 947 | # Add all services configured to autostart if pathname is outside %SYSTEMROOT% 948 | # if the service is currently running 949 | $autorunsvc = Get-WmiObject Win32_Service | 950 | Where-Object { $_.StartMode -eq 'Auto' -and $_.PathName -notmatch ($env:systemroot -replace '\\', '\\') -and $_.State -eq 'Running'} | select Displayname,Name 951 | Foreach ($service in $autorunsvc) { 952 | $ServicesToMonitor += $service 953 | } 954 | 955 | # Add all services located in %SYSTEMROOT% only if listed in services.ini 956 | $autorunsvc = Get-WmiObject Win32_Service | 957 | Where-Object { $_.StartMode -eq 'Auto' -and $_.PathName -match ($env:systemroot -replace '\\', '\\') } | select Displayname,Name 958 | Foreach ($service in $autorunsvc) { 959 | If (($servicesContent['SERVICES'][$service.Name] -eq '1') -or ($AlwaysMonitorServices -contains $service.Name)) { 960 | $ServicesToMonitor += $service 961 | } 962 | } 963 | } 964 | 965 | # Ignore Web Protection Agent 966 | $DoNotMonitorServices += 'WebMonAgent' 967 | ## SERVICES TO ADD 968 | Foreach ($service in $ServicesToMonitor) { 969 | If ($DoNotMonitorServices -notcontains $service.Name) { 970 | $oldChecks = Get-MAXfocusCheckList WinServiceCheck servicekeyname $service.Name 971 | If (!($oldChecks)) { 972 | New-MAXfocusCheck WinServiceCheck $service.DisplayName $service.Name 973 | } 974 | } 975 | } 976 | 977 | } 978 | 979 | ## Detect any databases and add relevant checks 980 | If ($MSSQL) { 981 | 982 | # Get any SQL services registered on device 983 | $SqlInstances = @(Get-SQLInstance) 984 | 985 | If ($SqlInstances.count -gt 0) { 986 | # Load SQL server management assembly 987 | #[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | out-null 988 | 989 | 990 | # Get next Eventlog check UID from settings.ini 991 | Try { 992 | $rs = $settingsContent['TEST_EVENTLOG']['NEXTUID'] 993 | } Catch { 994 | $settingsContent['TEST_EVENTLOG'] = @{ 'NEXTUID' = '1' } 995 | } 996 | [int]$NextUid = $settingsContent['TEST_EVENTLOG']['NEXTUID'] 997 | If ($NextUid -lt 1) { $NextUid = 1 } 998 | $LogAndDescription = 'Application|MSSQL Login Failed' 999 | $oldChecks = Get-MAXfocusCheckList EventLogCheck log $LogAndDescription 1000 | If (!($oldChecks)) { 1001 | $Flags = '32513' 1002 | $Source = 'MSSQLSERVER' 1003 | $Id = '18456' 1004 | New-MAXfocusCheck EventLogCheck $NextUid $LogAndDescription $Flags $Source $Id 1005 | $NextUid++ 1006 | } 1007 | # Save updated Eventlog test UID back to settings.ini 1008 | $settingsContent['TEST_EVENTLOG']['NEXTUID'] = $NextUid 1009 | 1010 | Foreach ($Instance in $SqlInstances){ 1011 | $sqlService = Get-WmiObject Win32_Service | where { $_.DisplayName -match $instance.SQLInstance -and $_.PathName -match 'sqlservr.exe' -and $_.StartMode -eq 'Auto'} 1012 | $oldChecks = Get-MAXfocusCheckList WinServiceCheck servicekeyname $sqlService.Name 1013 | If (!($oldChecks)) { 1014 | New-MAXfocusCheck WinServiceCheck $sqlService.DisplayName $sqlService.Name 1015 | } 1016 | } 1017 | 1018 | 1019 | } 1020 | } 1021 | 1022 | # Configure Performance Monitoring Checks 1023 | If ($Performance -and ($AgentMode -eq 'server')) { # Performance monitoring is only available on servers 1024 | $ThisDevice = Get-WmiObject Win32_ComputerSystem 1025 | 1026 | ## Processor Queue 1027 | If ($ThisDevice.Model -notmatch '^virtual|^vmware') { 1028 | # We are on a physical machine 1029 | $oldChecks = Get-MAXfocusCheckList PerfCounterCheck type 1 1030 | If (!($oldChecks)) { 1031 | New-MAXfocusCheck PerfCounterCheck Queue 1032 | } 1033 | } 1034 | 1035 | ## CPU 1036 | $oldChecks = Get-MAXfocusCheckList PerfCounterCheck type 2 1037 | If (!($oldChecks)) { 1038 | New-MAXfocusCheck PerfCounterCheck CPU 1039 | } 1040 | 1041 | ## RAM 1042 | [int]$nonpagedpool = 128 1043 | If ([System.IntPtr]::Size -gt 4) { # 64-bit 1044 | [int]$TotalMemoryInMB = $ThisDevice.TotalPhysicalMemory / 1MB 1045 | [int]$nonpagedpool = $nonpagedpool / 1024 * $TotalMemoryInMB 1046 | } 1047 | 1048 | $oldChecks = Get-MAXfocusCheckList PerfCounterCheck type 3 1049 | If (!($oldChecks)) { 1050 | New-MAXfocusCheck PerfCounterCheck RAM $nonpagedpool 1051 | } 1052 | 1053 | ## Net 1054 | # Not on Hyper-V 1055 | If ($ThisDevice.Model -notmatch '^virtual') { 1056 | $NetConnections = Get-WmiObject Win32_PerfRawData_Tcpip_Networkinterface | where {$_.BytesTotalPersec -gt 0} | Select -ExpandProperty Name 1057 | $oldChecks = Get-MAXfocusCheckList PerfCounterCheck Type 4 1058 | If (!($oldChecks)) { 1059 | Foreach ($Adapter in $NetConnections) { 1060 | New-MAXfocusCheck PerfCounterCheck Net $Adapter 1061 | } 1062 | } 1063 | } 1064 | ## Disk 1065 | # Needs physical disks 1066 | $PhysicalDisks = $DeviceConfig.configuration.physicaldisks | select -ExpandProperty name | where {$_ -ne '_Total'} 1067 | 1068 | $oldChecks = Get-MAXfocusCheckList PerfCounterCheck Type 5 1069 | If (!($oldChecks)) { 1070 | Foreach ($Disk in $PhysicalDisks ) { 1071 | New-MAXfocusCheck PerfCounterCheck Disk $Disk 1072 | } 1073 | } 1074 | } 1075 | 1076 | # Configure ping check 1077 | if($PingCheck -and ($AgentMode -eq 'server')) { # Pingcheck only supported on servers 1078 | # Get the two closest IP addresses counted from device 1079 | $trace = @() 1080 | $trace = Invoke-Expression 'tracert -d -w 10 -h 2 8.8.8.8' | 1081 | Foreach-Object { 1082 | if ($_ -like '*ms*' ) { 1083 | $chunks = $_ -split ' ' | Where-Object { $_ } 1084 | $ip = $chunks[-1] 1085 | $ip = @($ip)[0].Trim() -as [IPAddress] 1086 | $ip 1087 | } 1088 | } 1089 | # If the firewall does not answer to ICMP we wont have an array 1090 | If ($trace.Count -gt 1) { $trace = $trace[1]} 1091 | If ($trace -is [Net.IPAddress]) { 1092 | $oldChecks = Get-MAXfocusCheckList PingCheck pinghost $trace 1093 | If (!($oldChecks)) { 1094 | New-MAXfocusCheck PingCheck 'Router Next Hop' $trace 1095 | } 1096 | } 1097 | 1098 | } 1099 | 1100 | #EndRegion 1101 | } Else { 1102 | Output-Host '24/7 Checks are disabled. Enable 24/7 checks on agent' 1103 | Output-Host 'to configure 24/7 Checks automatically. To bulk update' 1104 | Output-Host 'use Add Checks... and add a single, relevant 24/7 check' 1105 | Output-Host 'to any device you want to use with this script. ' 1106 | Output-Host 'With Agent v09.5.7+ you can use Apply Template (preferred' 1107 | Output-Host 'Option).' 1108 | 1109 | } 1110 | 1111 | 1112 | If ($settingsContent['DAILYSAFETYCHECK']['ACTIVE'] -eq '1') { 1113 | #Region DSC Checks 1114 | 1115 | If ($Reset) { 1116 | $CheckTypes = @() 1117 | If ($DiskSpaceChange) {$CheckTypes += 'DiskSpaceChange'} 1118 | If ($SMART) {$CheckTypes += 'PhysDiskCheck'} 1119 | If ($Backup) {$CheckTypes += 'BackupCheck'} 1120 | If ($Antivirus) {$CheckTypes += 'AVUpdateCheck'} 1121 | If ($LogChecks) {$CheckTypes += 'EventLogCheck'} 1122 | Foreach ($OldCheck in $XmlConfig['DSC'].checks.ChildNodes) { 1123 | If ($CheckTypes.Contains($OldCheck.LocalName)) { 1124 | $OldCheck.ParentNode.RemoveChild($OldCheck) 1125 | } 1126 | } 1127 | } 1128 | ## DISKSPACECHANGE 1129 | # We only use this on servers 1130 | If (($DiskSpaceChange) -and ($AgentMode -eq 'server')) { 1131 | 1132 | # Get current fixed drives from WMI 1133 | $DetectedDrives = GET-WMIOBJECT -query "SELECT * from win32_logicaldisk where DriveType = '3'" | select -ExpandProperty DeviceID 1134 | 1135 | # Add any disk not currently in CurrentDiskSpaceChecks 1136 | foreach ($Disk in $DetectedDrives) { 1137 | $DriveLetter = $Disk + '\' 1138 | $oldChecks = Get-MAXfocusCheckList DiskSpaceChange driveletter $DriveLetter 1139 | If (!($oldChecks)) { 1140 | New-MAXfocusCheck DiskSpaceChange $DriveLetter 1141 | } 1142 | } 1143 | } 1144 | 1145 | ## Disk Health Status 1146 | If (($SMART) -and (Is-SMARTavailable)) { 1147 | $oldChecks = Get-MAXfocusCheckList PhysDiskCheck 1148 | If (!($oldChecks)) { 1149 | New-MAXfocusCheck PhysDiskCheck 1150 | } 1151 | } 1152 | 1153 | If ($Backup) { 1154 | $oldChecks = Get-MAXfocusCheckList BackupCheck 1155 | If (!($oldChecks)) { 1156 | $DetectedBackups = $DeviceConfig.configuration.backups | Select -ExpandProperty name -ErrorAction SilentlyContinue 1157 | Foreach ($BackupProduct in $DetectedBackups){ 1158 | $JobCount = 1 1159 | $AddCheck = $true 1160 | Switch ($BackupProduct) { 1161 | 'Backup Exec' { 1162 | $JobCount = 99 # Make sure unconfigured checks fail 1163 | $bengine = Get-WmiObject win32_service | where { $_.PathName -match 'bengine.exe' -and $_.DisplayName -match 'Backup Exec'} 1164 | If (!($bengine)){ 1165 | # Only add backup exec check if job engine is present 1166 | $AddCheck = $false 1167 | } 1168 | } 1169 | 'Managed Online Backup' { 1170 | $MOBsessionFile = "$env:programdata\Managed Online Backup\Backup Manager\SessionReport.xml" 1171 | [xml]$MOBsessions = Get-Content $MOBsessionFile 1172 | 1173 | $MOBplugins = @() 1174 | ForEach ($Session in $MOBsessions.SessionStatistics.Session){ 1175 | If ($MOBplugins -notcontains $Session.plugin){ 1176 | $MOBplugins += $Session.plugin 1177 | } 1178 | } 1179 | $JobCount = $MOBplugins.Count 1180 | } 1181 | 'Veeam' { 1182 | Add-PSSnapin VeeamPSSnapin -ErrorAction SilentlyContinue 1183 | If ((Get-PSSnapin '*Veeam*' -ErrorAction SilentlyContinue) -eq $null){ 1184 | Output-Host "Unable to load Veeam snapin, you must run this on your Veeam backup server, and the Powershell snapin must be installed.`n`n" 1185 | } Else { 1186 | $JobCount = (Get-VBRJob|select Name).Count 1187 | } 1188 | } 1189 | 'AppAssure v5' { 1190 | # Accept Default Jobcount, but add check 1191 | } 1192 | Default { 1193 | # Don't add any checks 1194 | $AddCheck = $false 1195 | } 1196 | } 1197 | If ($AddCheck) { 1198 | # We cannot know how many jobs or which days. Better a 1199 | # failed check that someone investigates than no check at all 1200 | New-MAXfocusCheck BackupCheck $BackupProduct $JobCount 1201 | } 1202 | } 1203 | } 1204 | } 1205 | 1206 | If ($Antivirus) { 1207 | $oldChecks = Get-MAXfocusCheckList AVUpdateCheck 1208 | If (!($oldChecks)) { 1209 | $DetectedAntiviruses = $DeviceConfig.configuration.antiviruses | Select -ExpandProperty name -ErrorAction SilentlyContinue 1210 | If (($DetectedAntiviruses) -and ($DetectedAntiviruses -notcontains 'Managed Antivirus')) { 1211 | Foreach ($AVProduct in $DetectedAntiviruses) { 1212 | $AddCheck = $true 1213 | Switch -regex ($AVProduct) { 1214 | 'Windows Defender' { $AddCheck = $false } 1215 | 'Trend.+Conventional Scan' { 1216 | If (Get-TMScanType -ne 'Conventional') { $AddCheck = $false } 1217 | } 1218 | 'Trend.+Smart Scan' { 1219 | If (Get-TMScanType -ne 'Smart') { $AddCheck = $false } 1220 | } 1221 | } 1222 | If ($AddCheck) { 1223 | # Only add a single AV check. Break after adding. 1224 | New-MAXfocusCheck AVUpdateCheck $AVProduct 1225 | Break 1226 | } 1227 | } 1228 | } 1229 | } 1230 | } 1231 | 1232 | If ($LogChecks -and $AgentMode -eq 'server') { 1233 | # Get next Eventlog check UID from settings.ini 1234 | Try { 1235 | $rs = $settingsContent['TEST_EVENTLOG']['NEXTUID'] 1236 | } Catch { 1237 | $settingsContent['TEST_EVENTLOG'] = @{ 'NEXTUID' = '1' } 1238 | } 1239 | [int]$NextUid = $settingsContent['TEST_EVENTLOG']['NEXTUID'] 1240 | If ($NextUid -lt 1) { $NextUid = 1 } 1241 | ForEach ($Check in $DefaultLogChecks) { 1242 | $oldChecks = Get-MAXfocusCheckList EventLogCheck log $Check.log 1243 | If (!($oldChecks)) { 1244 | New-MAXfocusCheck EventLogCheck $NextUid $Check.log $Check.flags $Check.source $Check.ids 1245 | $NextUid++ 1246 | } 1247 | } 1248 | # Save updated Eventlog test UID back to settings.ini 1249 | $settingsContent['TEST_EVENTLOG']['NEXTUID'] = $NextUid 1250 | 1251 | # Get Windows Eventlog names on this device 1252 | $LogNames = Get-WmiObject win32_nteventlogfile | select -ExpandProperty logfilename 1253 | ForEach ($Check in $DefaultCriticalEvents) { 1254 | # If this device doesn't have a targeted eventlog, skip the check 1255 | If($LogNames -notcontains $Check.eventlog) { Continue } 1256 | 1257 | If ($Check['eventlog'] -eq 'HardwareEvents') { 1258 | #This guy is special. We need to check if there are any events 1259 | $HardwareEvents = Get-WmiObject Win32_NTEventLogFile | where { $_.LogFileName -eq 'HardwareEvents' } 1260 | If ($HardwareEvents.NumberOfRecords -eq 0) { 1261 | Continue 1262 | } 1263 | } 1264 | # Add check if missing 1265 | $oldChecks = Get-MAXfocusCheckList CriticalEvents eventlog $Check.eventlog 1266 | If (!($oldChecks)) { 1267 | New-MAXfocusCheck CriticalEvents $Check.eventlog $Check.mode 1268 | } 1269 | } 1270 | } 1271 | #EndRegion 1272 | } Else { 1273 | Output-Host 'Daily Safety Checks are disabled. Enable DSC checks on agent' 1274 | Output-Host 'to configure DSC automatically. To bulk update' 1275 | Output-Host 'use Add Checks... and add a single, relevant DSC check' 1276 | Output-Host 'to any device you want to use with this script. ' 1277 | Output-Host 'Adding this script as a script check is our own preferred choice.' 1278 | Output-Host 'With Agent v09.5.7+ you can use Apply Template, too.' 1279 | } 1280 | 1281 | 1282 | #Region Save and Restart 1283 | 1284 | If ($ConfigChanged) { 1285 | If ($Apply) { 1286 | # Remove Reset Switch, but changes to ST_Config does not sync back to 1287 | # Dashboard. 1288 | If ($Reset) { 1289 | If ($logfile -match '_(\d+)\.log') { 1290 | $scriptuid = $Matches[1] 1291 | } 1292 | $OldCheck = $XmlConfig['DSC'].SelectSingleNode(("//*[@uid=$scriptuid]")) 1293 | If (!$OldCheck) { 1294 | $STConfig = New-Object -TypeName XML 1295 | $STConfig.Load($gfimaxpath + '\ST_Config.xml') 1296 | $OldCheck = $STConfig.SelectSingleNode(("//*[@uid=$scriptuid]")) 1297 | } 1298 | If ($OldCheck.arguments -is [System.Xml.XmlElement]) { 1299 | $OldCheck.arguments.set_InnerText($OldCheck.arguments.InnerText.Replace('-Reset','')) 1300 | } Else { 1301 | $OldCheck.arguments = $OldCheck.arguments.Replace('-Reset','') 1302 | } 1303 | If ($STConfig) { 1304 | $STConfig.Save($gfimaxpath + '\ST_Config.xml') 1305 | } 1306 | } 1307 | 1308 | # Write output to $LastChangeFile 1309 | # Overwrite file with first command 1310 | 'Last Change applied {0}:' -f $(Get-Date) | Out-File $LastChangeFile 1311 | '------------------------------------------------------' | Out-File -Append $LastChangeFile 1312 | If ($RemoveChecks.Count -gt 0) { 1313 | "`nRemoved the following checks to configuration file:" | Out-File -Append $LastChangeFile 1314 | Format-Output $RemoveChecks | Out-File -Append $LastChangeFile 1315 | } 1316 | If ($NewChecks.Count -gt 0) { 1317 | "`nAdded the following checks to configuration file:" | Out-File -Append $LastChangeFile 1318 | Format-Output $NewChecks | Out-File -Append $LastChangeFile 1319 | } 1320 | Output-Host 'Configuration has been changed. Initiating restart of agent.' 1321 | Restart-MAXfocusService 1322 | 1323 | If ($ReportMode) { 1324 | Exit 0 # Needed changes have been reported, but do not fail the check 1325 | } Else { 1326 | Exit 1001 # Internal status code: Changes made 1327 | } 1328 | } Else { 1329 | Output-Host 'Recommended changes:' 1330 | 1331 | If ($RemoveChecks.Count -gt 0) { 1332 | Output-Host 'Checks to be removed:' 1333 | Format-Output $RemoveChecks 1334 | } 1335 | If ($NewChecks.Count -gt 0) { 1336 | Output-Host 'Checks to be added:' 1337 | Format-Output $NewChecks 1338 | } 1339 | If ($ChangedSettings.Count -gt 0) { 1340 | Output-Host 'Settings to be changed:' 1341 | $ChangedSettings 1342 | } 1343 | If (Test-Path $LastChangeFile) { 1344 | # Print last change to STDOUT 1345 | Output-Host '------------------------------------------------------' 1346 | Get-Content $LastChangeFile 1347 | Output-Host '------------------------------------------------------' 1348 | } 1349 | If ($ReportMode) { 1350 | Exit 0 # Needed changes have been reported, but do not fail the check 1351 | } Else { 1352 | Exit 1000 # Internal status code: Suggested changes, but nothing has been touched 1353 | } 1354 | } 1355 | } Else { 1356 | # We have nothing to do. This Device has passed the test! 1357 | Output-Host 'Current Configuration Verified - OK:' 1358 | If ($Performance) { Output-Host 'Performance Monitoring checks verified: OK'} 1359 | If ($DriveSpaceCheck) { Output-Host 'Disk usage monitored on all harddrives: OK'} 1360 | If ($WinServiceCheck) { Output-Host 'All Windows services are now monitored: OK'} 1361 | If ($DiskSpaceChange) { Output-Host 'Disk space change harddrives monitored: OK'} 1362 | If ($PingCheck) { Output-Host 'Pingcheck Router Next Hop check tested: OK'} 1363 | If ($SqlInstances.count -gt 0) { Output-Host 'SQL Server installed:'; $SqlInstances } 1364 | If ($SMART) { Output-Host 'Physical Disk Health monitoring tested: OK'} 1365 | If ($Backup) { Output-Host 'Unmonitored Backup Products not found: OK'} 1366 | If ($Antivirus) { Output-Host 'Unmonitored Antivirus checks verified: OK'} 1367 | Output-Host 'All checks verified. Nothing has been changed.' 1368 | If (Test-Path $LastChangeFile) { 1369 | # Print last change to STDOUT 1370 | Output-Host '------------------------------------------------------' 1371 | Get-Content $LastChangeFile 1372 | Output-Host '------------------------------------------------------' 1373 | } 1374 | # Try to make Windows autostart monitoring agent if it fails 1375 | # Try to read the FailureActions property of Advanced Monitoring Agent 1376 | # If it does not exist, create it with sc.exe 1377 | $FailureActions = Get-ItemProperty 'HKLM:\System\CurrentControlSet\Services\Advanced Monitoring Agent' FailureActions -ErrorAction SilentlyContinue 1378 | If (!($FailureActions)) { 1379 | # Reset count every 24 hours, restart service after twice the 247Interval minutes 1380 | $servicename = $gfimaxagent.Name 1381 | &sc.exe failure "$servicename" reset= 86400 actions= restart/600000 1382 | } 1383 | Exit 0 # SUCCESS 1384 | } 1385 | 1386 | #EndRegion -------------------------------------------------------------------------------- /MAXfocus/Verify-MAXfocusVMwareChecks.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .DESCRIPTION 3 | Detect missing VMware checks automatically. 4 | Add or report according to script settings. 5 | 6 | .AUTHOR 7 | Hugo L. Klemmestad 8 | .DATE 9 | 23.05.2014 10 | #> 11 | 12 | 13 | 14 | ## SETTINGS 15 | # A few settings are handled as parameters 16 | param ( 17 | [switch]$Apply = $false, 18 | [switch]$ReportMode = $true, 19 | [string]$User = "root", 20 | [string]$Pass = "vmware", 21 | [array]$Hosts = "" 22 | ) 23 | ## Constants 24 | # May need updating from time to time 25 | 26 | 27 | 28 | $Scripts = @{ 29 | "script_1024_28.vbs" = @{ 30 | "arguments" = ""; 31 | "url" = "https://raw.githubusercontent.com/klemmestad/PowerShell/master/Resources/script_1024_28.vbs" }; 32 | "script_1024_29.vbs" = @{ 33 | "arguments" = ""; 34 | "url" = "https://raw.githubusercontent.com/klemmestad/PowerShell/master/Resources/script_1024_29.vbs" }; 35 | "script_1024_30.vbs" = @{ 36 | "arguments" = ""; 37 | "url" = "https://raw.githubusercontent.com/klemmestad/PowerShell/master/Resources/script_1024_30.vbs" }; 38 | "script_1024_32.vbs" = @{ 39 | "arguments" = ""; 40 | "url" = "https://raw.githubusercontent.com/klemmestad/PowerShell/master/Resources/script_1024_32.vbs" }; 41 | "script_1024_33.vbs" = @{ 42 | "arguments" = ""; 43 | "url" = "https://raw.githubusercontent.com/klemmestad/PowerShell/master/Resources/script_1024_33.vbs" }; 44 | "script_1024_34.ps1" = @{ 45 | "arguments" = ""; 46 | "url" = "https://raw.githubusercontent.com/klemmestad/PowerShell/master/Resources/script_1024_34.ps1" }; 47 | "script_1024_35.ps1" = @{ 48 | "arguments" = " -vmname ""*"""; 49 | "url" = "https://raw.githubusercontent.com/klemmestad/PowerShell/master/Resources/script_1024_35.ps1" }; 50 | "script_1024_38.ps1" = @{ 51 | "arguments" = " -datastorename ""*"" -units ""GB"" -threshold ""20"""; 52 | "url" = "https://raw.githubusercontent.com/klemmestad/PowerShell/master/Resources/script_1024_38.ps1" }; 53 | "script_1024_39.ps1" = @{ 54 | "arguments" = ""; 55 | "url" = "https://raw.githubusercontent.com/klemmestad/PowerShell/master/Resources/script_1024_39.ps1" }; 56 | } 57 | 58 | $DefaultChecks = @( 59 | @{ "checktype" = "ScriptCheck"; 60 | "checkset" = "247"; 61 | "description" = "VMware ESXi Health - Fans"; 62 | "scriptname" = "script_1024_28.vbs" ; 63 | "scriptlanguage" = "0"; 64 | "timeout" = "10"; 65 | "arguments" = "-host ""{0}"" -username ""{1}"" -password ""{2}""" } 66 | @{ "checktype" = "ScriptCheck"; 67 | "checkset" = "247"; 68 | "description" = "VMware ESXi Health - CPUs"; 69 | "scriptname" = "script_1024_29.vbs" ; 70 | "scriptlanguage" = "0"; 71 | "timeout" = "10"; 72 | "arguments" = "-host ""{0}"" -username ""{1}"" -password ""{2}""" } 73 | @{ "checktype" = "ScriptCheck"; 74 | "checkset" = "247"; 75 | "description" = "VMware ESXi Health - Memory"; 76 | "scriptname" = "script_1024_30.vbs" ; 77 | "scriptlanguage" = "0"; 78 | "timeout" = "10"; 79 | "arguments" = "-host ""{0}"" -username ""{1}"" -password ""{2}""" } 80 | @{ "checktype" = "ScriptCheck"; 81 | "checkset" = "247"; 82 | "description" = "VMware ESXi Health - PSUs"; 83 | "scriptname" = "script_1024_32.vbs" ; 84 | "scriptlanguage" = "0"; 85 | "timeout" = "10"; 86 | "arguments" = "-host ""{0}"" -username ""{1}"" -password ""{2}""" } 87 | @{ "checktype" = "ScriptCheck"; 88 | "checkset" = "247"; 89 | "description" = "VMware ESXi Health - Sensors"; 90 | "scriptname" = "script_1024_33.vbs" ; 91 | "scriptlanguage" = "0"; 92 | "timeout" = "10"; 93 | "arguments" = "-host ""{0}"" -username ""{1}"" -password ""{2}""" } 94 | @{ "checktype" = "ScriptCheck"; 95 | "checkset" = "247"; 96 | "description" = "VMware ESXi Health - Storage"; 97 | "scriptname" = "script_1024_39.ps1" ; 98 | "scriptlanguage" = "1"; 99 | "timeout" = "150"; 100 | "arguments" = "-hostname ""{0}"" -username ""{1}"" -password ""{2}""" } 101 | @{ "checktype" = "ScriptCheck"; 102 | "checkset" = "DSC"; 103 | "description" = "VMware ESXi Virtual Machine Inventory"; 104 | "scriptname" = "script_1024_34.ps1" ; 105 | "scriptlanguage" = "1"; 106 | "timeout" = "150"; 107 | "arguments" = "-hostname ""{0}"" -username ""{1}"" -password ""{2}""" } 108 | # @{ "checktype" = "ScriptCheck"; 109 | # "checkset" = "DSC"; 110 | # "description" = "VMware ESXi Virtual Machine Power State"; 111 | # "scriptname" = "script_1024_35.ps1" ; 112 | # "scriptlanguage" = "1"; 113 | # "timeout" = "150"; 114 | # "arguments" = "-hostname ""{0}"" -username ""{1}"" -password ""{2}"" -vmname ""*""" } #-hostname "oc-esx01.hverven.local" -username "root" -password "vmware" -vmname "*" 115 | @{ "checktype" = "ScriptCheck"; 116 | "checkset" = "DSC"; 117 | "description" = "VMware ESXi - Datastore Free Space"; 118 | "scriptname" = "script_1024_38.ps1" ; 119 | "scriptlanguage" = "1"; 120 | "timeout" = "150"; 121 | "arguments" = "-hostname ""{0}"" -username ""{1}"" -password ""{2}"" -datastorename ""*"" -units ""MB"" -threshold ""20000""" } 122 | ) 123 | 124 | ## VARIUS FUNCTIONS 125 | # Return an array of values from an array of XML Object 126 | function Get-GFIMAXChecks ($xmlArray, $property) { 127 | $returnArray = @() 128 | foreach ($element in $xmlArray) { 129 | If ($element.$property -is [System.Xml.XmlElement]) { 130 | $returnArray += $element.$property.InnerText 131 | } Else { 132 | $returnArray += $element.$property 133 | } 134 | } 135 | If ($returnArray) { 136 | Return $returnArray 137 | } 138 | } 139 | 140 | function Format-Output ($ArrayOfHash) { 141 | $Result = @() 142 | ForEach ($Check in $ArrayOfHash) { 143 | $Result += '{0,-40} {1}' -f $Check["description"], $Check["arguments"]#.Split(" ")[1] 144 | } 145 | Return $Result 146 | } 147 | 148 | function Make-ScriptAvailable ([string]$ScriptName) { 149 | $ScriptPath = $ScriptDir + $ScriptName 150 | If (!(Test-Path $ScriptPath)) { 151 | $Source = $Scripts[$ScriptName]["url"] 152 | $Destination = $ScriptDir + $ScriptName 153 | $webclient.DownloadFile($Source,$Destination) 154 | } 155 | } 156 | 157 | # Downloaded from 158 | # http://blogs.technet.com/b/heyscriptingguy/archive/2011/08/20/use-powershell-to-work-with-any-ini-file.aspx 159 | # modified to use ordered list by me 160 | function Get-IniContent ($filePath) { 161 | $ini = New-Object System.Collections.Specialized.OrderedDictionary 162 | switch -regex -file $FilePath 163 | { 164 | "^\[(.+)\]" # Section 165 | { 166 | $section = $matches[1] 167 | $ini[$section] = New-Object System.Collections.Specialized.OrderedDictionary 168 | $CommentCount = 0 169 | } 170 | "^(;.*)$" # Comment 171 | { 172 | $value = $matches[1] 173 | $CommentCount = $CommentCount + 1 174 | $name = "Comment" + $CommentCount 175 | $ini[$section][$name] = $value 176 | } 177 | "(.+?)\s*=(.*)" # Key 178 | { 179 | $name,$value = $matches[1..2] 180 | $ini[$section][$name] = $value 181 | } 182 | } 183 | return $ini 184 | } 185 | # Downloaded from 186 | # http://blogs.technet.com/b/heyscriptingguy/archive/2011/08/20/use-powershell-to-work-with-any-ini-file.aspx 187 | # Modified to force overwrite by me 188 | function Out-IniFile($InputObject, $FilePath) { 189 | $outFile = New-Item -ItemType file -Path $Filepath -Force 190 | foreach ($i in $InputObject.keys) 191 | { 192 | if ("Hashtable","OrderedDictionary" -notcontains $($InputObject[$i].GetType().Name)) 193 | { 194 | #No Sections 195 | Add-Content -Path $outFile -Value "$i=$($InputObject[$i])" 196 | } else { 197 | #Sections 198 | Add-Content -Path $outFile -Value "[$i]" 199 | Foreach ($j in ($InputObject[$i].keys | Sort-Object)) 200 | { 201 | if ($j -match "^Comment[\d]+") { 202 | Add-Content -Path $outFile -Value "$($InputObject[$i][$j])" 203 | } else { 204 | Add-Content -Path $outFile -Value "$j=$($InputObject[$i][$j])" 205 | } 206 | 207 | } 208 | Add-Content -Path $outFile -Value "" 209 | } 210 | } 211 | } 212 | 213 | ## SETUP ENVIRONMENT 214 | # Find "Advanced Monitoring Agent" service and use path to locate files 215 | $gfimaxagent = Get-WmiObject Win32_Service | Where-Object { $_.Name -eq 'Advanced Monitoring Agent' } 216 | $gfimaxexe = $gfimaxagent.PathName 217 | $gfimaxpath = Split-Path $gfimaxagent.PathName.Replace('"',"") -Parent 218 | 219 | # XML Document objects 220 | $XmlConfig = @{} 221 | 222 | # XML Document Pathnames 223 | $XmlFile = @{} 224 | 225 | # We need an array of hashes to remember which checks to add 226 | $NewChecks = @() 227 | 228 | $Sets = @("247", "DSC") 229 | 230 | $IniFile = $gfimaxpath + "\settings.ini" 231 | $ScriptDir = $gfimaxpath + "\scripts\" 232 | $ScriptLib = $ScriptDir + "lib\" 233 | $LastChangeFile = $gfimaxpath + "\LastChangeToVMwareChecks.log" 234 | 235 | $ConfigChanged = $false 236 | 237 | $webclient = New-Object System.Net.WebClient 238 | # Must use TLS with GitHub because of POODLE modifications serverside 239 | [System.Net.ServicePointManager]::SecurityProtocol = 'Tls12' 240 | 241 | # Read ini-files 242 | $settingsContent = Get-IniContent($IniFile) 243 | 244 | If (!(Test-Path -PathType Container $ScriptLib)) { 245 | $Silent = New-Item -ItemType Directory -Force -Path $ScriptLib 246 | } 247 | 248 | $PSSnapinVMware = $false 249 | $sSnapInName = 'VMware.VimAutomation.Core' 250 | foreach( $oSnapIn in Get-PSSnapIn -Registered ) { 251 | if( $oSnapIn.Name -eq $sSnapInName ) { 252 | Add-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue 253 | $PSSnapinVMware = $true 254 | } 255 | } 256 | 257 | 258 | # Read configuration of checks. Create an XML object if they do not exist yet. 259 | ForEach ($Set in $Sets) { 260 | $XmlConfig[$Set] = New-Object -TypeName XML 261 | $XmlFile[$Set] = $gfimaxpath + "\{0}_Config.xml" -f $Set 262 | If (Test-Path $XmlFile[$Set]) { 263 | $XmlConfig[$Set].Load($XmlFile[$Set]) 264 | $XmlConfig[$Set].DocumentElement.SetAttribute("modified","1") 265 | } Else { 266 | $decl = $XmlConfig[$Set].CreateXmlDeclaration("1.0", "ISO-8859-1", $null) 267 | $rootNode = $XmlConfig[$Set].CreateElement("checks") 268 | $result = $rootNode.SetAttribute("modified", "1") 269 | $result = $XmlConfig[$Set].InsertBefore($decl, $XmlConfig[$Set].DocumentElement) 270 | $result = $XmlConfig[$Set].AppendChild($rootNode) 271 | $uid = 1 272 | } 273 | } 274 | 275 | # Verify that hostnames are resolvable 276 | $EsxHosts = @() 277 | $CurrentChecks = Get-GFIMAXChecks ($XmlConfig.Values | % { $_.checks.ScriptCheck }) scriptname 278 | Foreach ($EsxHost in $Hosts) { 279 | # Create REF variable of correct type 280 | $ip = [System.Net.IPAddress]::Parse("127.0.0.1") 281 | # Try to parse $EsxHost as IP address 282 | If (!([System.Net.IPAddress]::TryParse($EsxHost, [ref] $ip))) { 283 | # $EsxHost is not a valid IP address. Maybe it is a hostname? 284 | Try { 285 | $ip = [System.Net.Dns]::GetHostAddresses($EsxHost)[0] 286 | # Use IPv4 for 'localhost' 287 | If ($ip -eq "::1") { $ip = [System.Net.IPAddress]::Parse("127.0.0.1") } 288 | } Catch { 289 | Write-Host ("ERROR: Could not resolve hostname ""{0}""" -f $EsxHost) 290 | Continue 291 | } 292 | Write-Host ('Resolved {0} to IP address {1}.' -f $EsxHost, $ip) 293 | } 294 | 295 | Write-Host ('Processing Checks for host {0}.' -f $EsxHost) 296 | $CurrentCount = $NewChecks.Count 297 | Foreach ($Check in $DefaultChecks) { 298 | # The name of the script is important. 299 | $ScriptName = $Check.scriptname 300 | 301 | # Download the script from our own repository if it is missing 302 | Make-ScriptAvailable $ScriptName 303 | 304 | # Put passed parameters into $Arguments 305 | $Arguments = $Check.arguments -f $EsxHost, $User, $Pass 306 | 307 | # Delete any existing checks running this very script on this very host 308 | # We may be replacing it with a new password 309 | $CurrentScriptChecks = @($XmlConfig.Values | % { $_.checks.ScriptCheck } | where {($_.scriptname.Innertext -eq $ScriptName -or $_.scriptname -eq $ScriptName) -and ($_.arguments.Innertext -match $EsxHost -or $_.arguments -match $EsxHost)}) 310 | $CheckExists = $false 311 | Foreach ($xmlCheck in $CurrentScriptChecks) { 312 | If (($xmlCheck.arguments.InnerText -eq $Arguments -or $xmlCheck.arguments -eq $Arguments ) -and ($CurrentScriptChecks.Count -eq 1) -and $xmlCheck.BaseURI.Contains($Check.checkset)) { 313 | $CheckExists = $true 314 | } Else { 315 | $null = $xmlCheck.ParentNode.RemoveChild($xmlCheck) 316 | } 317 | } 318 | 319 | If ($CheckExists) { Continue } 320 | 321 | # Create a Check 322 | $NewCheck = @{ 323 | "checktype" = "ScriptCheck"; 324 | "checkset" = $Check.checkset; 325 | "scriptname" = $ScriptName; 326 | "description" = $Check.description; 327 | "scriptlanguage" = $Check.scriptlanguage; 328 | "arguments" = $Arguments; 329 | "timeout" = $Check.timeout 330 | } 331 | $NewChecks += $NewCheck 332 | } 333 | If ($NewChecks.Count -gt $CurrentCount) { 334 | Write-Host ('New checks found for {0}.' -f $EsxHost) 335 | } Else { 336 | Write-Host ('No new checks found for {0}.' -f $EsxHost) 337 | } 338 | } 339 | 340 | 341 | If($NewChecks[0]) { 342 | Foreach ($Check in $NewChecks) { 343 | $xmlCheck = $XmlConfig[$Check.checkset].CreateElement($Check.checktype) 344 | $xmlCheck.SetAttribute('modified', '1') 345 | 346 | Foreach ($property in $Check.Keys) { 347 | If ("checkset", "checktype" -notcontains $property) { 348 | $xmlProperty = $XmlConfig[$Check.checkset].CreateElement($property) 349 | $propertyValue = $Check.get_Item($property) 350 | If ([bool]($propertyValue -as [int]) -or $propertyValue -eq "0") # Is this a number? 351 | { # If its a number we just dump it in there 352 | $xmlProperty.set_InnerText($propertyValue) 353 | } Else { # If it is text we encode it in CDATA 354 | $rs = $xmlProperty.AppendChild($XmlConfig[$Check.checkset].CreateCDataSection($propertyValue)) 355 | } 356 | # Add Property to Check element 357 | $rs = $xmlCheck.AppendChild($xmlProperty) 358 | } 359 | } 360 | # Add Check to file in check section 361 | $rs = $XmlConfig[$Check.checkset].checks.AppendChild($xmlCheck) 362 | 363 | } 364 | $XmlConfig[$Check.checkset].checks.SetAttribute("modified", "1") 365 | $ConfigChanged = $true 366 | } 367 | 368 | 369 | If($ConfigChanged) { 370 | 371 | If ($Apply) { 372 | # Update last runtime to prevent changes too often 373 | [int]$currenttime = $(get-date -UFormat %s) -replace ",","." # Handle decimal comma 374 | $settingsContent["DAILYSAFETYCHECK"]["RUNTIME"] = $currenttime 375 | 376 | # Clear lastcheckday to make DSC run immediately 377 | $settingsContent["DAILYSAFETYCHECK"]["LASTCHECKDAY"] = "0" 378 | 379 | # Stop agent before writing new config files 380 | Stop-Service $gfimaxagent.Name 381 | 382 | # Save all config files 383 | ForEach ($Set in $Sets) { 384 | $XmlConfig[$Set].Save($XmlFile[$Set]) 385 | } 386 | Out-IniFile $settingsContent $IniFile 387 | 388 | # Start monitoring agent again 389 | Start-Service $gfimaxagent.Name 390 | 391 | # Write output to $LastChangeFile 392 | # Overwrite file with first command 393 | "Last Change applied {0}:" -f $(Get-Date) | Out-File $LastChangeFile 394 | "------------------------------------------------------" | Out-File -Append $LastChangeFile 395 | If ($NewChecks.Count -gt 0) { 396 | "`nAdded the following checks to configuration file:" | Out-File -Append $LastChangeFile 397 | Format-Output $NewChecks | Out-File -Append $LastChangeFile 398 | } 399 | 400 | If ($ReportMode) { 401 | Exit 0 # Needed changes have been reported, but do not fail the check 402 | } Else { 403 | Exit 1001 # Internal status code: Changes made 404 | } 405 | } Else { 406 | Write-Host "MISSING CHECKS" 407 | If ($NewChecks) 408 | { 409 | Write-Host "You should add the following checks:" 410 | Format-Output $NewChecks 411 | } 412 | If (Test-Path $LastChangeFile) { 413 | # Print last change to STDOUT 414 | Write-Host "------------------------------------------------------" 415 | Get-Content $LastChangeFile 416 | Write-Host "------------------------------------------------------" 417 | } 418 | If ($ReportMode) { 419 | Exit 0 # Needed changes have been reported, but do not fail the check 420 | } Else { 421 | Exit 1000 # Internal status code: Suggested changes, but nothing has been touched 422 | } 423 | } 424 | } Else { 425 | # We have nothing to do. This Device has passed the test! 426 | Write-Host "CHECKS VERIFIED" 427 | If (Test-Path $LastChangeFile) { 428 | # Print last change to STDOUT 429 | Write-Host "------------------------------------------------------" 430 | Get-Content $LastChangeFile 431 | Write-Host "------------------------------------------------------" 432 | } 433 | Exit 0 # SUCCESS 434 | } 435 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PowerShell 2 | ========== 3 | 4 | PowerShell scripts posted on http://klemmestad.com 5 | ========== 6 | 7 | -------------------------------------------------------------------------------- /Resources/README.txt: -------------------------------------------------------------------------------- 1 | Test Resources rquired to make posted scripts work: 2 | 3 | "script_1024_28.vbs" VMware ESXi Health - Fans 4 | "script_1024_29.vbs" VMware ESXi Health - CPUs 5 | "script_1024_30.vbs" VMware ESXi Health - Memory 6 | "script_1024_32.vbs" VMware ESXi Health - PSUs 7 | "script_1024_33.vbs" VMware ESXi Health - Sensors 8 | "script_1024_34.ps1" VMware ESXi Virtual Machine Inventory 9 | "script_1024_35.ps1" VMware ESXi Virtual Machine Power State 10 | "script_1024_38.ps1" VMware ESXi - Datastore Free Space 11 | "script_1024_39.ps1" VMware ESXi Health - Storage 12 | 13 | -------------------------------------------------------------------------------- /Resources/script_1024_28.vbs: -------------------------------------------------------------------------------- 1 | Option Explicit 2 | ' ----------------------------------------------------------------------------- 3 | ' Fan Sensor Information - Alert When Not OK 4 | ' ----------------------------------------------------------------------------- 5 | ' Parameters: 6 | ' script.vbs --username "Username" -password "Password" -host "111.111.111.111" 7 | ' ----------------------------------------------------------------------------- 8 | ' Version Information 9 | ' ----------------------------------------------------------------------------- 10 | ' $LastChangedDate: 2013-03-15 14:19:20 +0000 (Fri, 15 Mar 2013) $ 11 | ' $Rev: 38413 $ 12 | ' ----------------------------------------------------------------------------- 13 | 14 | Const PASSED_CHECK = 0 15 | Const ERROR_MISSING_ARGUMENTS = 1 16 | Const ERROR_CONNECTION_FAIL_CREDENTIALS = 1001 17 | Const ERROR_CONNECTION_FAIL_WSMAN_HOST = 1002 18 | Const ERROR_CONNECTION_FAIL_WSMAN_ESX = 1003 19 | Const ERROR_CONNECTION_FAIL_WSMAN_UNKNOWN = 1004 20 | Const FAILED_CHECK = 2003 21 | 22 | Const CONNECTION_FAIL_WSMAN_STATUS = -1 23 | Const CONNECTION_FAIL_CREDENTIALS_STATUS = -2 24 | Const HEALTHSTATE_UNKNOWN = "0" 25 | Const HEALTHSTATE_OK = "5" 26 | Const EXPECTED_ARGUMENTS = 6 27 | 28 | Private Host 29 | Private Username 30 | Private Password 31 | 32 | Private isConnected 'True/False 33 | 34 | Private OMCSchema 35 | Private DMTFSchema 36 | Private VMWareSchema 37 | 38 | Private oWSMan 39 | Private oOptions 40 | Private oSession 41 | 42 | Private sXmlDocContent 43 | Private fSuccess 44 | Private nFailing 45 | Private nPassing 46 | Private nUnknown 47 | 48 | Private forceFailMode 49 | 50 | Public Function Class_Initialize() 51 | fSuccess = 1 52 | nFailing = 0 53 | nPassing = 0 54 | nUnknown = 0 55 | OMCSchema = "http://schema.omc-project.org/wbem/wscim/1/cim-schema/2/" 56 | DMTFSchema = "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/" 57 | VMWareSchema = "http://schemas.vmware.com/wbem/wscim/1/cim-schema/2/" 58 | End Function 59 | 60 | Public Function setCredentials(strHost, strUsername, strPassword) 61 | Host = strHost 62 | Username = strUsername 63 | Password = strPassword 64 | End Function 65 | 66 | Public Function Connect(fSkipCA, fSkipCN) 67 | Set oWSMan = CreateObject("Wsman.Automation") 68 | Set oOptions = oWSMan.CreateConnectionOptions 69 | 70 | oOptions.userName = Username 71 | oOptions.Password = Password 72 | 73 | Dim ConnectionFlags : ConnectionFlags = oWSMan.SessionFlagUseBasic 74 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagCredUserNamePassword 75 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagUTF8 76 | 77 | On Error Resume Next 78 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagSkipRevocationCheck 79 | If fSkipCA = True Then 80 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagSkipCACheck 81 | End If 82 | If fSkipCN = True Then 83 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagSkipCNCheck 84 | End If 85 | On Error Goto 0 86 | 87 | Set oSession = oWSMan.CreateSession("https://" & Host & "/wsman",ConnectionFlags,oOptions) 88 | 89 | If oSession is Nothing Then 90 | Connect = CONNECTION_FAIL_WSMAN_STATUS 'WSMan is either not installed or credentials failed. 91 | End If 92 | 93 | End Function 94 | 95 | 96 | '{GFI-MIXINS} 97 | 98 | Private Function updateSummaryHealthCounts( healthState ) 99 | If HealthState = HEALTHSTATE_OK Then 100 | nPassing = nPassing + 1 101 | ElseIf HealthState = HEALTHSTATE_UNKNOWN Then 102 | nUnknown = nUnknown + 1 103 | Else 104 | fSuccess = 0 105 | nFailing = nFailing + 1 106 | End If 107 | End Function 108 | 109 | Public Function getFanCheckInformation 110 | Dim Caption, HealthState, xmlDom 111 | Dim strBase : strBase = getBaseURL("OMC_Fan") 112 | Dim strQueryResource : strQueryResource = strBase & "OMC_Fan" 113 | Dim oQueryResponse : Set oQueryResponse = oSession.Enumerate(strQueryResource) 114 | While Not oQueryResponse.AtEndOfStream 115 | Set xmlDom = LoadDom( oQueryResponse.ReadItem ) 116 | Caption = ParseXML(xmlDom, "/n1:OMC_Fan/n1:Caption") 117 | HealthState = Replace(ParseXML(xmlDom, "/n1:OMC_Fan/n1:HealthState"), "NULL", "0") 118 | 119 | updateSummaryHealthCounts HealthState 120 | 121 | sXmlDocContent = sXmlDocContent & "" 122 | 123 | WEnd 124 | 125 | End Function 126 | 127 | Public Function getBaseURL(strCIMClass) 128 | If inStr(strCIMClass, "CIM_") <> 0 Then 129 | GetBaseURL = DMTFSchema 130 | ElseIf inStr(strCIMClass, "OMC_") <> 0 Then 131 | GetBaseURL = OMCSchema 132 | ElseIf inStr(strCIMClass, "VMware_") <> 0 Then 133 | GetBaseURL = VMWareSchema 134 | Else 135 | GetBaseURL = -1 136 | End If 137 | End Function 138 | 139 | Public Function LoadDom( ByRef Response ) 140 | Dim xmlData : Set xmlData = CreateObject("MSXml2.DOMDocument.3.0") 141 | xmlData.LoadXml( Response ) 142 | Set LoadDom = xmlData 143 | End Function 144 | 145 | Public Function ParseXML( ByRef xmlData,NodeName ) 146 | If forceFailMode Then changeHealthValues xmlData 147 | Dim node : Set node = xmlData.selectSingleNode(NodeName) 148 | Dim attrib : attrib = node.getAttribute("xsi:nil") & "" 149 | If attrib = "true" Then 150 | ParseXML = "NULL" 151 | Else 152 | ParseXML = node.text 153 | End If 154 | End Function 155 | 156 | Public Function checkArguments 157 | For nArgCount = 0 to Args.Count - 1 158 | Select Case UCase(Args(nArgCount)) 159 | Case "-FORCEFAIL" 160 | forceFailMode = True 161 | Case "-HOST" 162 | If Args.Count >= ( nArgCount + 1 ) Then 163 | sHost = Args( nArgCount + 1 ) 164 | End If 165 | Case "-USERNAME" 166 | If Args.Count >= ( nArgCount + 1 ) Then 167 | sUsername = Args( nArgCount + 1 ) 168 | End If 169 | Case "-PASSWORD" 170 | If Args.Count >= ( nArgCount + 1 ) Then 171 | sPassword = Args( nArgCount + 1 ) 172 | End If 173 | End Select 174 | Next 175 | 176 | If Args.Count < EXPECTED_ARGUMENTS Then 177 | WScript.Echo ERROR_MISSING_ARGUMENTS & "|" & "Error: Not Enough Arguments" 178 | WScript.Quit ERROR_MISSING_ARGUMENTS 179 | End If 180 | End Function 181 | 182 | Private Function changeHealthValues(ByRef xmlDoc) 183 | Dim nodes :Set nodes = xmlDoc.documentElement.selectNodes("//n1:HealthState") 184 | Dim i 185 | For i = 0 To nodes.Length -1 186 | nodes(i).Text = 6 187 | Next 188 | End Function 189 | 190 | Public Function checkConnectionState 191 | On Error Resume Next 192 | oSession.Identify 193 | 'WScript.Echo Err.Description 194 | 'WScript.Echo hex(Err.Number) 195 | If Err.Number <> 0 Then 196 | If hex(Err.Number) = "80338126" Then 197 | WScript.Echo ERROR_CONNECTION_FAIL_WSMAN_HOST & "|" & "Failed to Connect - Host Unreachable" 198 | WScript.Quit ERROR_CONNECTION_FAIL_WSMAN_HOST 199 | ElseIf hex(Err.Number) = "80072F8F" Then 200 | WScript.Echo ERROR_CONNECTION_FAIL_WSMAN_ESX & "|" & "Failed to Connect - Not an ESX Server" 201 | WScript.Quit ERROR_CONNECTION_FAIL_WSMAN_ESX 202 | ElseIf hex(Err.Number) = "80070005" Then 203 | WScript.Echo ERROR_CONNECTION_FAIL_CREDENTIALS & "|" & "Failed to connect - Ensure credentials are valid/have correct permissions" 204 | WScript.Quit ERROR_CONNECTION_FAIL_CREDENTIALS 205 | Else 206 | WScript.Echo ERROR_CONNECTION_FAIL_WSMAN_UNKNOWN & "|" & "Failed to connect - An unknown error occured. Please ensure this host is a valid ESX server" 207 | WScript.Quit ERROR_CONNECTION_FAIL_WSMAN_UNKNOWN 208 | End If 209 | End If 210 | On Error Goto 0 211 | 212 | Err.Clear 213 | 214 | isConnected = True 215 | End Function 216 | 217 | 218 | ' ----------------------------------------------------------------------------- 219 | ' Run the Script 220 | ' ----------------------------------------------------------------------------- 221 | 222 | ' Expected Arguments 223 | ' -host 224 | ' -username 225 | ' -password 226 | 227 | 228 | Dim sHost 229 | Dim sUsername 230 | Dim sPassword 231 | 232 | Dim Args 233 | Set Args = WScript.Arguments 234 | 235 | Dim nArgCount 236 | 237 | 238 | Class_Initialize 239 | checkArguments 240 | setCredentials sHost, sUsername, sPassword 241 | Connect True,True 242 | checkConnectionState 243 | 244 | ' start forming the xml string 245 | sXmlDocContent = "" 246 | sXmlDocContent = sXmlDocContent & "" 247 | ' get fan information 248 | sXmlDocContent = sXmlDocContent & "" 249 | getFanCheckInformation 250 | sXmlDocContent = sXmlDocContent & "" 251 | ' close the xml string and return 252 | sXmlDocContent = sXmlDocContent & "" 253 | 254 | 255 | ' return pass or fail 256 | IF fSuccess = 1 Then 257 | WScript.Echo PASSED_CHECK & "|" & sXmlDocContent & "|" & nPassing & "|" & nFailing & "|" & nUnknown 258 | WScript.Quit PASSED_CHECK 259 | Else 260 | WScript.Echo FAILED_CHECK & "|" & sXmlDocContent & "|" & nPassing & "|" & nFailing & "|" & nUnknown 261 | WScript.Quit FAILED_CHECK 262 | End If -------------------------------------------------------------------------------- /Resources/script_1024_29.vbs: -------------------------------------------------------------------------------- 1 | Option Explicit 2 | ' ----------------------------------------------------------------------------- 3 | ' Processor Sensor Information - Alert When Not OK 4 | ' ----------------------------------------------------------------------------- 5 | ' Parameters: 6 | ' script.vbs --username "Username" -password "Password" -host "111.111.111.111" 7 | ' ----------------------------------------------------------------------------- 8 | ' Version Information 9 | ' ----------------------------------------------------------------------------- 10 | ' $LastChangedDate: 2013-03-15 14:19:20 +0000 (Fri, 15 Mar 2013) $ 11 | ' $Rev: 38413 $ 12 | ' ----------------------------------------------------------------------------- 13 | 14 | Const PASSED_CHECK = 0 15 | Const ERROR_MISSING_ARGUMENTS = 1 16 | Const ERROR_CONNECTION_FAIL_CREDENTIALS = 1001 17 | Const ERROR_CONNECTION_FAIL_WSMAN_HOST = 1002 18 | Const ERROR_CONNECTION_FAIL_WSMAN_ESX = 1003 19 | Const ERROR_CONNECTION_FAIL_WSMAN_UNKNOWN = 1004 20 | Const FAILED_CHECK = 2003 21 | 22 | Const CONNECTION_FAIL_WSMAN_STATUS = -1 23 | Const CONNECTION_FAIL_CREDENTIALS_STATUS = -2 24 | Const HEALTHSTATE_UNKNOWN = "0" 25 | Const HEALTHSTATE_OK = "5" 26 | Const EXPECTED_ARGUMENTS = 6 27 | 28 | Private Host 29 | Private Username 30 | Private Password 31 | 32 | Private isConnected 'True/False 33 | 34 | Private OMCSchema 35 | Private DMTFSchema 36 | Private VMWareSchema 37 | 38 | Private oWSMan 39 | Private oOptions 40 | Private oSession 41 | 42 | Private sXmlDocContent 43 | Private fSuccess 44 | Private nFailing 45 | Private nPassing 46 | Private nUnknown 47 | 48 | Private forceFailMode 49 | 50 | Public Function Class_Initialize() 51 | fSuccess = 1 52 | nFailing = 0 53 | nPassing = 0 54 | nUnknown = 0 55 | OMCSchema = "http://schema.omc-project.org/wbem/wscim/1/cim-schema/2/" 56 | DMTFSchema = "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/" 57 | VMWareSchema = "http://schemas.vmware.com/wbem/wscim/1/cim-schema/2/" 58 | End Function 59 | 60 | Public Function setCredentials(strHost, strUsername, strPassword) 61 | Host = strHost 62 | Username = strUsername 63 | Password = strPassword 64 | End Function 65 | 66 | Public Function Connect(fSkipCA, fSkipCN) 67 | Set oWSMan = CreateObject("Wsman.Automation") 68 | Set oOptions = oWSMan.CreateConnectionOptions 69 | 70 | oOptions.userName = Username 71 | oOptions.Password = Password 72 | 73 | Dim ConnectionFlags : ConnectionFlags = oWSMan.SessionFlagUseBasic 74 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagCredUserNamePassword 75 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagUTF8 76 | 77 | On Error Resume Next 78 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagSkipRevocationCheck 79 | If fSkipCA = True Then 80 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagSkipCACheck 81 | End If 82 | If fSkipCN = True Then 83 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagSkipCNCheck 84 | End If 85 | On Error Goto 0 86 | 87 | Set oSession = oWSMan.CreateSession("https://" & Host & "/wsman",ConnectionFlags,oOptions) 88 | 89 | If oSession is Nothing Then 90 | Connect = CONNECTION_FAIL_WSMAN_STATUS 'WSMan is either not installed or credentials failed. 91 | End If 92 | 93 | End Function 94 | 95 | 96 | '{GFI-MIXINS} 97 | 98 | Private Function updateSummaryHealthCounts( healthState ) 99 | If HealthState = HEALTHSTATE_OK Then 100 | nPassing = nPassing + 1 101 | ElseIf HealthState = HEALTHSTATE_UNKNOWN Then 102 | nUnknown = nUnknown + 1 103 | Else 104 | fSuccess = 0 105 | nFailing = nFailing + 1 106 | End If 107 | End Function 108 | 109 | Public Function getProcessorCheckInformation 110 | Dim Caption 111 | Dim HealthState 112 | Dim EnabledDefault 113 | Dim EnabledState 114 | Dim CurrentClockSpeed 115 | Dim MaxClockSpeed 116 | Dim Level 117 | Dim NumberOfBlocks 118 | Dim ReadPolicy 119 | Dim WritePolicy 120 | Dim ModelName 121 | Dim ErrorMethodology 122 | Dim NumberOfEnabledCores 123 | Dim xmlDom 124 | 125 | Dim strBase : strBase = getBaseURL("OMC_Processor") 126 | Dim strQueryResource : strQueryResource = strBase & "OMC_Processor" 127 | Dim oQueryResponse : Set oQueryResponse = oSession.Enumerate(strQueryResource) 128 | While Not oQueryResponse.AtEndOfStream 129 | Set xmlDom = LoadDom( oQueryResponse.ReadItem ) 130 | 131 | Caption = ParseXML(xmlDom, "/n1:OMC_Processor/n1:Caption") 132 | ModelName = ParseXML(xmlDom, "/n1:OMC_Processor/n1:ModelName") 133 | NumberOfEnabledCores = ParseXML(xmlDom, "/n1:OMC_Processor/n1:NumberOfEnabledCores") 134 | CurrentClockSpeed = ParseXML(xmlDom, "/n1:OMC_Processor/n1:CurrentClockSpeed") & " MHz" 135 | MaxClockSpeed = ParseXML(xmlDom, "/n1:OMC_Processor/n1:MaxClockSpeed") & " MHz" 136 | EnabledDefault = ParseXML(xmlDom, "/n1:OMC_Processor/n1:EnabledDefault") 137 | EnabledState = ParseXML(xmlDom, "/n1:OMC_Processor/n1:EnabledState") 138 | HealthState = Replace(ParseXML(xmlDom, "/n1:OMC_Processor/n1:HealthState"), "NULL", "0") 139 | 140 | updateSummaryHealthCounts HealthState 141 | 142 | sXmlDocContent = sXmlDocContent & "" 143 | WEnd 144 | 145 | strBase = getBaseURL("OMC_ProcessorCore") 146 | strQueryResource = strBase & "OMC_ProcessorCore" 147 | Set oQueryResponse = oSession.Enumerate(strQueryResource) 148 | While Not oQueryResponse.AtEndOfStream 149 | Set xmlDom = LoadDom( oQueryResponse.ReadItem ) 150 | Caption = ParseXML(xmlDom, "/n1:OMC_ProcessorCore/n1:Caption") 151 | HealthState = Replace(ParseXML(xmlDom, "/n1:OMC_ProcessorCore/n1:HealthState"), "NULL", "0") 152 | EnabledDefault = ParseXML(xmlDom, "/n1:OMC_ProcessorCore/n1:EnabledDefault") 153 | EnabledState = ParseXML(xmlDom, "/n1:OMC_ProcessorCore/n1:EnabledState") 154 | 155 | updateSummaryHealthCounts HealthState 156 | 157 | sXmlDocContent = sXmlDocContent & "" 158 | WEnd 159 | 160 | strBase = getBaseURL("OMC_HardwareThread") 161 | strQueryResource = strBase & "OMC_HardwareThread" 162 | Set oQueryResponse = oSession.Enumerate(strQueryResource) 163 | While Not oQueryResponse.AtEndOfStream 164 | Set xmlDom = LoadDom( oQueryResponse.ReadItem ) 165 | Caption = ParseXML(xmlDom, "/n1:OMC_HardwareThread/n1:Caption") 166 | HealthState = Replace(ParseXML(xmlDom, "/n1:OMC_HardwareThread/n1:HealthState"), "NULL", "0") 167 | 168 | updateSummaryHealthCounts HealthState 169 | 170 | sXmlDocContent = sXmlDocContent & "" 171 | WEnd 172 | 173 | strBase = getBaseURL("OMC_CacheMemory") 174 | strQueryResource = strBase & "OMC_CacheMemory" 175 | Set oQueryResponse = oSession.Enumerate(strQueryResource) 176 | While Not oQueryResponse.AtEndOfStream 177 | Set xmlDom = LoadDom( oQueryResponse.ReadItem ) 178 | Caption = ParseXML(xmlDom, "/n1:OMC_CacheMemory/n1:Caption") 179 | Level = ParseXML(xmlDom, "/n1:OMC_CacheMemory/n1:Level") 180 | NumberOfBlocks = ParseXML(xmlDom, "/n1:OMC_CacheMemory/n1:NumberOfBlocks") 181 | ReadPolicy = ParseXML(xmlDom, "/n1:OMC_CacheMemory/n1:ReadPolicy") 182 | WritePolicy = ParseXML(xmlDom, "/n1:OMC_CacheMemory/n1:WritePolicy") 183 | ErrorMethodology = ParseXML(xmlDom, "/n1:OMC_CacheMemory/n1:ErrorMethodology") 184 | EnabledDefault = ParseXML(xmlDom, "/n1:OMC_CacheMemory/n1:EnabledDefault") 185 | EnabledState = ParseXML(xmlDom, "/n1:OMC_CacheMemory/n1:EnabledState") 186 | 187 | sXmlDocContent = sXmlDocContent & "" 188 | WEnd 189 | 190 | End Function 191 | 192 | Public Function getBaseURL(strCIMClass) 193 | If inStr(strCIMClass, "CIM_") <> 0 Then 194 | GetBaseURL = DMTFSchema 195 | ElseIf inStr(strCIMClass, "OMC_") <> 0 Then 196 | GetBaseURL = OMCSchema 197 | ElseIf inStr(strCIMClass, "VMware_") <> 0 Then 198 | GetBaseURL = VMWareSchema 199 | Else 200 | GetBaseURL = -1 201 | End If 202 | End Function 203 | 204 | Public Function LoadDom( ByRef Response ) 205 | Dim xmlData : Set xmlData = CreateObject("MSXml2.DOMDocument.3.0") 206 | xmlData.LoadXml( Response ) 207 | Set LoadDom = xmlData 208 | End Function 209 | 210 | Public Function ParseXML( ByRef xmlData,NodeName ) 211 | If forceFailMode Then changeHealthValues xmlData 212 | Dim node : Set node = xmlData.selectSingleNode(NodeName) 213 | Dim attrib : attrib = node.getAttribute("xsi:nil") & "" 214 | If attrib = "true" Then 215 | ParseXML = "NULL" 216 | Else 217 | ParseXML = node.text 218 | End If 219 | End Function 220 | 221 | Public Function checkArguments 222 | For nArgCount = 0 to Args.Count - 1 223 | Select Case UCase(Args(nArgCount)) 224 | Case "-FORCEFAIL" 225 | forceFailMode = True 226 | Case "-HOST" 227 | If Args.Count >= ( nArgCount + 1 ) Then 228 | sHost = Args( nArgCount + 1 ) 229 | End If 230 | Case "-USERNAME" 231 | If Args.Count >= ( nArgCount + 1 ) Then 232 | sUsername = Args( nArgCount + 1 ) 233 | End If 234 | Case "-PASSWORD" 235 | If Args.Count >= ( nArgCount + 1 ) Then 236 | sPassword = Args( nArgCount + 1 ) 237 | End If 238 | End Select 239 | Next 240 | 241 | If Args.Count < EXPECTED_ARGUMENTS Then 242 | WScript.Echo ERROR_MISSING_ARGUMENTS & "|" & "Error: Not Enough Arguments" 243 | WScript.Quit ERROR_MISSING_ARGUMENTS 244 | End If 245 | End Function 246 | 247 | Private Function changeHealthValues(ByRef xmlDoc) 248 | Dim nodes :Set nodes = xmlDoc.documentElement.selectNodes("//n1:HealthState") 249 | Dim i 250 | For i = 0 To nodes.Length -1 251 | nodes(i).Text = 6 252 | Next 253 | End Function 254 | 255 | Public Function checkConnectionState 256 | On Error Resume Next 257 | oSession.Identify 258 | 'WScript.Echo Err.Description 259 | 'WScript.Echo hex(Err.Number) 260 | If Err.Number <> 0 Then 261 | If hex(Err.Number) = "80338126" Then 262 | WScript.Echo ERROR_CONNECTION_FAIL_WSMAN_HOST & "|" & "Failed to Connect - Host Unreachable" 263 | WScript.Quit ERROR_CONNECTION_FAIL_WSMAN_HOST 264 | ElseIf hex(Err.Number) = "80072F8F" Then 265 | WScript.Echo ERROR_CONNECTION_FAIL_WSMAN_ESX & "|" & "Failed to Connect - Not an ESX Server" 266 | WScript.Quit ERROR_CONNECTION_FAIL_WSMAN_ESX 267 | ElseIf hex(Err.Number) = "80070005" Then 268 | WScript.Echo ERROR_CONNECTION_FAIL_CREDENTIALS & "|" & "Failed to connect - Ensure credentials are valid/have correct permissions" 269 | WScript.Quit ERROR_CONNECTION_FAIL_CREDENTIALS 270 | Else 271 | WScript.Echo ERROR_CONNECTION_FAIL_WSMAN_UNKNOWN & "|" & "Failed to connect - An unknown error occured. Please ensure this host is a valid ESX server" 272 | WScript.Quit ERROR_CONNECTION_FAIL_WSMAN_UNKNOWN 273 | End If 274 | End If 275 | On Error Goto 0 276 | 277 | Err.Clear 278 | 279 | isConnected = True 280 | End Function 281 | 282 | 283 | ' ----------------------------------------------------------------------------- 284 | ' Run the Script 285 | ' ----------------------------------------------------------------------------- 286 | 287 | ' Expected Arguments 288 | ' -host 289 | ' -username 290 | ' -password 291 | 292 | 293 | Dim sHost 294 | Dim sUsername 295 | Dim sPassword 296 | 297 | Dim Args 298 | Set Args = WScript.Arguments 299 | 300 | Dim nArgCount 301 | 302 | 303 | Class_Initialize 304 | checkArguments 305 | setCredentials sHost, sUsername, sPassword 306 | Connect True,True 307 | checkConnectionState 308 | 309 | ' start forming the xml string 310 | sXmlDocContent = "" 311 | sXmlDocContent = sXmlDocContent & "" 312 | ' get processor information 313 | sXmlDocContent = sXmlDocContent & "" 314 | getProcessorCheckInformation 315 | sXmlDocContent = sXmlDocContent & "" 316 | ' close the xml string and return 317 | sXmlDocContent = sXmlDocContent & "" 318 | 319 | 320 | ' return pass or fail 321 | IF fSuccess = 1 Then 322 | WScript.Echo PASSED_CHECK & "|" & sXmlDocContent & "|" & nPassing & "|" & nFailing & "|" & nUnknown 323 | WScript.Quit PASSED_CHECK 324 | Else 325 | WScript.Echo FAILED_CHECK & "|" & sXmlDocContent & "|" & nPassing & "|" & nFailing & "|" & nUnknown 326 | WScript.Quit FAILED_CHECK 327 | End If -------------------------------------------------------------------------------- /Resources/script_1024_30.vbs: -------------------------------------------------------------------------------- 1 | Option Explicit 2 | ' ----------------------------------------------------------------------------- 3 | ' Memory Sensor Information - Alert When Not OK 4 | ' ----------------------------------------------------------------------------- 5 | ' Parameters: 6 | ' script.vbs --username "Username" -password "Password" -host "111.111.111.111" 7 | ' ----------------------------------------------------------------------------- 8 | ' Version Information 9 | ' ----------------------------------------------------------------------------- 10 | ' $LastChangedDate: 2013-03-15 14:19:20 +0000 (Fri, 15 Mar 2013) $ 11 | ' $Rev: 38413 $ 12 | ' ----------------------------------------------------------------------------- 13 | 14 | Const PASSED_CHECK = 0 15 | Const ERROR_MISSING_ARGUMENTS = 1 16 | Const ERROR_CONNECTION_FAIL_CREDENTIALS = 1001 17 | Const ERROR_CONNECTION_FAIL_WSMAN_HOST = 1002 18 | Const ERROR_CONNECTION_FAIL_WSMAN_ESX = 1003 19 | Const ERROR_CONNECTION_FAIL_WSMAN_UNKNOWN = 1004 20 | Const FAILED_CHECK = 2003 21 | 22 | Const CONNECTION_FAIL_WSMAN_STATUS = -1 23 | Const CONNECTION_FAIL_CREDENTIALS_STATUS = -2 24 | Const HEALTHSTATE_UNKNOWN = "0" 25 | Const HEALTHSTATE_OK = "5" 26 | Const EXPECTED_ARGUMENTS = 6 27 | 28 | Private Host 29 | Private Username 30 | Private Password 31 | 32 | Private isConnected 'True/False 33 | 34 | Private OMCSchema 35 | Private DMTFSchema 36 | Private VMWareSchema 37 | 38 | Private oWSMan 39 | Private oOptions 40 | Private oSession 41 | 42 | Private sXmlDocContent 43 | Private fSuccess 44 | Private nFailing 45 | Private nPassing 46 | Private nUnknown 47 | 48 | Private forceFailMode 49 | 50 | Public Function Class_Initialize() 51 | fSuccess = 1 52 | nFailing = 0 53 | nPassing = 0 54 | nUnknown = 0 55 | OMCSchema = "http://schema.omc-project.org/wbem/wscim/1/cim-schema/2/" 56 | DMTFSchema = "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/" 57 | VMWareSchema = "http://schemas.vmware.com/wbem/wscim/1/cim-schema/2/" 58 | End Function 59 | 60 | Public Function setCredentials(strHost, strUsername, strPassword) 61 | Host = strHost 62 | Username = strUsername 63 | Password = strPassword 64 | End Function 65 | 66 | Public Function Connect(fSkipCA, fSkipCN) 67 | Set oWSMan = CreateObject("Wsman.Automation") 68 | Set oOptions = oWSMan.CreateConnectionOptions 69 | 70 | oOptions.userName = Username 71 | oOptions.Password = Password 72 | 73 | Dim ConnectionFlags : ConnectionFlags = oWSMan.SessionFlagUseBasic 74 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagCredUserNamePassword 75 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagUTF8 76 | 77 | On Error Resume Next 78 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagSkipRevocationCheck 79 | If fSkipCA = True Then 80 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagSkipCACheck 81 | End If 82 | If fSkipCN = True Then 83 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagSkipCNCheck 84 | End If 85 | On Error Goto 0 86 | 87 | Set oSession = oWSMan.CreateSession("https://" & Host & "/wsman",ConnectionFlags,oOptions) 88 | 89 | If oSession is Nothing Then 90 | Connect = CONNECTION_FAIL_WSMAN_STATUS 'WSMan is either not installed or credentials failed. 91 | End If 92 | 93 | End Function 94 | 95 | 96 | '{GFI-MIXINS} 97 | 98 | Private Function updateSummaryHealthCounts( healthState ) 99 | If HealthState = HEALTHSTATE_OK Then 100 | nPassing = nPassing + 1 101 | ElseIf HealthState = HEALTHSTATE_UNKNOWN Then 102 | nUnknown = nUnknown + 1 103 | Else 104 | fSuccess = 0 105 | nFailing = nFailing + 1 106 | End If 107 | End Function 108 | 109 | Public Function getMemoryCheckInformation 110 | Dim item 111 | Dim Name 112 | Dim Caption 113 | Dim HealthState 114 | Dim EnabledDefault 115 | Dim EnabledState 116 | Dim DetailedStatus 117 | Dim Capacity 118 | Dim NumberOfBlocks 119 | Dim xmlDom 120 | 121 | Dim strBase : strBase = getBaseURL("OMC_Memory") 122 | Dim strQueryResource : strQueryResource = strBase & "OMC_Memory" 123 | Dim oQueryResponse : Set oQueryResponse = oSession.Enumerate(strQueryResource) 124 | While Not oQueryResponse.AtEndOfStream 125 | Set xmlDom = LoadDom( oQueryResponse.ReadItem ) 126 | Name = ParseXML(xmlDom, "/n1:OMC_Memory/n1:Name") 127 | HealthState = Replace(ParseXML(xmlDom, "/n1:OMC_Memory/n1:HealthState"), "NULL", "0") 128 | EnabledDefault = ParseXML(xmlDom, "/n1:OMC_Memory/n1:EnabledDefault") 129 | EnabledState = ParseXML(xmlDom, "/n1:OMC_Memory/n1:EnabledState") 130 | DetailedStatus = ParseXML(xmlDom, "/n1:OMC_Memory/n1:DetailedStatus") 131 | NumberOfBlocks = ParseXML(xmlDom, "/n1:OMC_Memory/n1:NumberOfBlocks") 132 | 133 | updateSummaryHealthCounts HealthState 134 | 135 | sXmlDocContent = sXmlDocContent & "" 136 | 137 | WEnd 138 | 139 | strBase = getBaseURL("OMC_PhysicalMemory") 140 | strQueryResource = strBase & "OMC_PhysicalMemory" 141 | Set oQueryResponse = oSession.Enumerate(strQueryResource) 142 | While Not oQueryResponse.AtEndOfStream 143 | Set xmlDom = LoadDom( oQueryResponse.ReadItem ) 144 | Caption = ParseXML(xmlDom, "/n1:OMC_PhysicalMemory/n1:Caption") 145 | Capacity = ParseXML(xmlDom, "/n1:OMC_PhysicalMemory/n1:Capacity") 146 | Capacity = Capacity / 1073741824 & " GB" 147 | sXmlDocContent = sXmlDocContent & "" 148 | WEnd 149 | 150 | End Function 151 | 152 | Public Function getBaseURL(strCIMClass) 153 | If inStr(strCIMClass, "CIM_") <> 0 Then 154 | GetBaseURL = DMTFSchema 155 | ElseIf inStr(strCIMClass, "OMC_") <> 0 Then 156 | GetBaseURL = OMCSchema 157 | ElseIf inStr(strCIMClass, "VMware_") <> 0 Then 158 | GetBaseURL = VMWareSchema 159 | Else 160 | GetBaseURL = -1 161 | End If 162 | End Function 163 | 164 | Public Function LoadDom( ByRef Response ) 165 | Dim xmlData : Set xmlData = CreateObject("MSXml2.DOMDocument.3.0") 166 | xmlData.LoadXml( Response ) 167 | Set LoadDom = xmlData 168 | End Function 169 | 170 | Public Function ParseXML( ByRef xmlData,NodeName ) 171 | If forceFailMode Then changeHealthValues xmlData 172 | Dim node : Set node = xmlData.selectSingleNode(NodeName) 173 | Dim attrib : attrib = node.getAttribute("xsi:nil") & "" 174 | If attrib = "true" Then 175 | ParseXML = "NULL" 176 | Else 177 | ParseXML = node.text 178 | End If 179 | End Function 180 | 181 | Public Function checkArguments 182 | For nArgCount = 0 to Args.Count - 1 183 | Select Case UCase(Args(nArgCount)) 184 | Case "-FORCEFAIL" 185 | forceFailMode = True 186 | Case "-HOST" 187 | If Args.Count >= ( nArgCount + 1 ) Then 188 | sHost = Args( nArgCount + 1 ) 189 | End If 190 | Case "-USERNAME" 191 | If Args.Count >= ( nArgCount + 1 ) Then 192 | sUsername = Args( nArgCount + 1 ) 193 | End If 194 | Case "-PASSWORD" 195 | If Args.Count >= ( nArgCount + 1 ) Then 196 | sPassword = Args( nArgCount + 1 ) 197 | End If 198 | End Select 199 | Next 200 | 201 | If Args.Count < EXPECTED_ARGUMENTS Then 202 | WScript.Echo ERROR_MISSING_ARGUMENTS & "|" & "Error: Not Enough Arguments" 203 | WScript.Quit ERROR_MISSING_ARGUMENTS 204 | End If 205 | End Function 206 | 207 | Private Function changeHealthValues(ByRef xmlDoc) 208 | Dim nodes :Set nodes = xmlDoc.documentElement.selectNodes("//n1:HealthState") 209 | Dim i 210 | For i = 0 To nodes.Length -1 211 | nodes(i).Text = 6 212 | Next 213 | End Function 214 | 215 | Public Function checkConnectionState 216 | On Error Resume Next 217 | oSession.Identify 218 | If Err.Number <> 0 Then 219 | If hex(Err.Number) = "80338126" Then 220 | WScript.Echo ERROR_CONNECTION_FAIL_WSMAN_HOST & "|" & "Failed to Connect - Host Unreachable" 221 | WScript.Quit ERROR_CONNECTION_FAIL_WSMAN_HOST 222 | ElseIf hex(Err.Number) = "80072F8F" Then 223 | WScript.Echo ERROR_CONNECTION_FAIL_WSMAN_ESX & "|" & "Failed to Connect - Not an ESX Server" 224 | WScript.Quit ERROR_CONNECTION_FAIL_WSMAN_ESX 225 | ElseIf hex(Err.Number) = "80070005" Then 226 | WScript.Echo ERROR_CONNECTION_FAIL_CREDENTIALS & "|" & "Failed to connect - Ensure credentials are valid/have correct permissions" 227 | WScript.Quit ERROR_CONNECTION_FAIL_CREDENTIALS 228 | Else 229 | WScript.Echo ERROR_CONNECTION_FAIL_WSMAN_UNKNOWN & "|" & "Failed to connect - An unknown error occured. Please ensure this host is a valid ESX server" 230 | WScript.Quit ERROR_CONNECTION_FAIL_WSMAN_UNKNOWN 231 | End If 232 | End If 233 | On Error Goto 0 234 | 235 | Err.Clear 236 | 237 | isConnected = True 238 | End Function 239 | 240 | 241 | ' ----------------------------------------------------------------------------- 242 | ' Run the Script 243 | ' ----------------------------------------------------------------------------- 244 | 245 | ' Expected Arguments 246 | ' -host 247 | ' -username 248 | ' -password 249 | 250 | 251 | Dim sHost 252 | Dim sUsername 253 | Dim sPassword 254 | 255 | Dim Args 256 | Set Args = WScript.Arguments 257 | 258 | Dim nArgCount 259 | 260 | 261 | Class_Initialize 262 | checkArguments 263 | setCredentials sHost, sUsername, sPassword 264 | Connect True,True 265 | checkConnectionState 266 | 267 | ' start forming the xml string 268 | sXmlDocContent = "" 269 | sXmlDocContent = sXmlDocContent & "" 270 | ' get memory information 271 | sXmlDocContent = sXmlDocContent & "" 272 | getMemoryCheckInformation 273 | sXmlDocContent = sXmlDocContent & "" 274 | ' close the xml string and return 275 | sXmlDocContent = sXmlDocContent & "" 276 | 277 | 278 | ' return pass or fail 279 | IF fSuccess = 1 Then 280 | WScript.Echo PASSED_CHECK & "|" & sXmlDocContent & "|" & nPassing & "|" & nFailing & "|" & nUnknown 281 | WScript.Quit PASSED_CHECK 282 | Else 283 | WScript.Echo FAILED_CHECK & "|" & sXmlDocContent & "|" & nPassing & "|" & nFailing & "|" & nUnknown 284 | WScript.Quit FAILED_CHECK 285 | End If -------------------------------------------------------------------------------- /Resources/script_1024_32.vbs: -------------------------------------------------------------------------------- 1 | Option Explicit 2 | ' ----------------------------------------------------------------------------- 3 | ' PSU Sensor Information - Alert When Not OK 4 | ' ----------------------------------------------------------------------------- 5 | ' Parameters: 6 | ' script.vbs --username "Username" -password "Password" -host "111.111.111.111" 7 | ' ----------------------------------------------------------------------------- 8 | ' Version Information 9 | ' ----------------------------------------------------------------------------- 10 | ' $LastChangedDate: 2013-03-15 14:19:20 +0000 (Fri, 15 Mar 2013) $ 11 | ' $Rev: 38413 $ 12 | ' ----------------------------------------------------------------------------- 13 | 14 | Const PASSED_CHECK = 0 15 | Const ERROR_MISSING_ARGUMENTS = 1 16 | Const ERROR_CONNECTION_FAIL_CREDENTIALS = 1001 17 | Const ERROR_CONNECTION_FAIL_WSMAN_HOST = 1002 18 | Const ERROR_CONNECTION_FAIL_WSMAN_ESX = 1003 19 | Const ERROR_CONNECTION_FAIL_WSMAN_UNKNOWN = 1004 20 | Const FAILED_CHECK = 2003 21 | 22 | Const CONNECTION_FAIL_WSMAN_STATUS = -1 23 | Const CONNECTION_FAIL_CREDENTIALS_STATUS = -2 24 | Const HEALTHSTATE_UNKNOWN = "0" 25 | Const HEALTHSTATE_OK = "5" 26 | Const EXPECTED_ARGUMENTS = 6 27 | 28 | Private Host 29 | Private Username 30 | Private Password 31 | 32 | Private isConnected 'True/False 33 | 34 | Private OMCSchema 35 | Private DMTFSchema 36 | Private VMWareSchema 37 | 38 | Private oWSMan 39 | Private oOptions 40 | Private oSession 41 | 42 | Private sXmlDocContent 43 | Private fSuccess 44 | Private nFailing 45 | Private nPassing 46 | Private nUnknown 47 | Private forceFailMode 48 | 49 | Public Function Class_Initialize() 50 | fSuccess = 1 51 | nFailing = 0 52 | nPassing = 0 53 | nUnknown = 0 54 | OMCSchema = "http://schema.omc-project.org/wbem/wscim/1/cim-schema/2/" 55 | DMTFSchema = "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/" 56 | VMWareSchema = "http://schemas.vmware.com/wbem/wscim/1/cim-schema/2/" 57 | End Function 58 | 59 | Public Function setCredentials(strHost, strUsername, strPassword) 60 | Host = strHost 61 | Username = strUsername 62 | Password = strPassword 63 | End Function 64 | 65 | Public Function Connect(fSkipCA, fSkipCN) 66 | Set oWSMan = CreateObject("Wsman.Automation") 67 | Set oOptions = oWSMan.CreateConnectionOptions 68 | 69 | oOptions.userName = Username 70 | oOptions.Password = Password 71 | 72 | Dim ConnectionFlags : ConnectionFlags = oWSMan.SessionFlagUseBasic 73 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagCredUserNamePassword 74 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagUTF8 75 | 76 | On Error Resume Next 77 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagSkipRevocationCheck 78 | If fSkipCA = True Then 79 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagSkipCACheck 80 | End If 81 | If fSkipCN = True Then 82 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagSkipCNCheck 83 | End If 84 | On Error Goto 0 85 | 86 | Set oSession = oWSMan.CreateSession("https://" & Host & "/wsman",ConnectionFlags,oOptions) 87 | 88 | If oSession is Nothing Then 89 | Connect = CONNECTION_FAIL_WSMAN_STATUS 'WSMan is either not installed or credentials failed. 90 | End If 91 | 92 | End Function 93 | 94 | 95 | '{GFI-MIXINS} 96 | 97 | Private Function updateSummaryHealthCounts( healthState ) 98 | If HealthState = HEALTHSTATE_OK Then 99 | nPassing = nPassing + 1 100 | ElseIf HealthState = HEALTHSTATE_UNKNOWN Then 101 | nUnknown = nUnknown + 1 102 | Else 103 | fSuccess = 0 104 | nFailing = nFailing + 1 105 | End If 106 | End Function 107 | 108 | Public Function getPsuCheckInformation 109 | Dim Caption 110 | Dim HealthState 111 | Dim EnabledDefault 112 | Dim EnabledState 113 | Dim TotalOutputPower 114 | Dim Range1InputFrequencyHigh 115 | Dim Range1InputFrequencyLow 116 | Dim Range1InputVoltageHigh 117 | Dim Range1InputVoltageLow 118 | Dim xmlDom 119 | 120 | Dim strBase : strBase = getBaseURL("OMC_PowerSupply") 121 | Dim strQueryResource : strQueryResource = strBase & "OMC_PowerSupply" 122 | Dim oQueryResponse : Set oQueryResponse = oSession.Enumerate(strQueryResource) 123 | While Not oQueryResponse.AtEndOfStream 124 | Set xmlDom = LoadDom( oQueryResponse.ReadItem ) 125 | Caption = ParseXML(xmlDom, "/n1:OMC_PowerSupply/n1:Caption") 126 | TotalOutputPower = ParseXML(xmlDom, "/n1:OMC_PowerSupply/n1:TotalOutputPower") 127 | TotalOutputPower = Replace(ParseNumber( TotalOutputPower ) / 1000 & " W", "0 W", "-") 128 | HealthState = Replace(ParseXML(xmlDom, "/n1:OMC_PowerSupply/n1:HealthState"), "NULL", "0") 129 | EnabledDefault = ParseXML(xmlDom, "/n1:OMC_PowerSupply/n1:EnabledDefault") 130 | EnabledState = ParseXML(xmlDom, "/n1:OMC_PowerSupply/n1:EnabledState") 131 | Range1InputFrequencyHigh = Replace(ParseXML(xmlDom, "/n1:OMC_PowerSupply/n1:Range1InputFrequencyHigh") & " Hz", "NULL Hz", "-") 132 | Range1InputFrequencyLow = Replace(ParseXML(xmlDom, "/n1:OMC_PowerSupply/n1:Range1InputFrequencyLow") & " Hz", "NULL Hz", "-") 133 | Range1InputVoltageHigh = ParseXML(xmlDom, "/n1:OMC_PowerSupply/n1:Range1InputVoltageHigh") 134 | Range1InputVoltageHigh = Replace(ParseNumber( Range1InputVoltageHigh ) / 1000 & " V", "0 V", "-") 135 | Range1InputVoltageLow = ParseXML(xmlDom, "/n1:OMC_PowerSupply/n1:Range1InputVoltageLow") 136 | Range1InputVoltageLow = Replace(ParseNumber( Range1InputVoltageLow ) / 1000 & " V", "0 V", "-") 137 | 138 | updateSummaryHealthCounts HealthState 139 | 140 | sXmlDocContent = sXmlDocContent & "" 141 | 142 | WEnd 143 | 144 | End Function 145 | 146 | Public Function getBaseURL(strCIMClass) 147 | If inStr(strCIMClass, "CIM_") <> 0 Then 148 | GetBaseURL = DMTFSchema 149 | ElseIf inStr(strCIMClass, "OMC_") <> 0 Then 150 | GetBaseURL = OMCSchema 151 | ElseIf inStr(strCIMClass, "VMware_") <> 0 Then 152 | GetBaseURL = VMWareSchema 153 | Else 154 | GetBaseURL = -1 155 | End If 156 | End Function 157 | 158 | Public Function LoadDom( ByRef Response ) 159 | Dim xmlData : Set xmlData = CreateObject("MSXml2.DOMDocument.3.0") 160 | xmlData.LoadXml( Response ) 161 | Set LoadDom = xmlData 162 | End Function 163 | 164 | Public Function ParseXML( ByRef xmlData,NodeName ) 165 | If forceFailMode Then changeHealthValues xmlData 166 | Dim node : Set node = xmlData.selectSingleNode(NodeName) 167 | Dim attrib : attrib = node.getAttribute("xsi:nil") & "" 168 | If attrib = "true" Then 169 | ParseXML = "NULL" 170 | Else 171 | ParseXML = node.text 172 | End If 173 | End Function 174 | 175 | Public Function ParseNumber( inoValue ) 176 | If IsNumeric( inoValue) Then 177 | ParseNumber = CLng( inoValue ) 178 | Else 179 | ParseNumber = 0 180 | End If 181 | End Function 182 | 183 | Public Function checkArguments 184 | For nArgCount = 0 to Args.Count - 1 185 | Select Case UCase(Args(nArgCount)) 186 | Case "-FORCEFAIL" 187 | forceFailMode = True 188 | Case "-HOST" 189 | If Args.Count >= ( nArgCount + 1 ) Then 190 | sHost = Args( nArgCount + 1 ) 191 | End If 192 | Case "-USERNAME" 193 | If Args.Count >= ( nArgCount + 1 ) Then 194 | sUsername = Args( nArgCount + 1 ) 195 | End If 196 | Case "-PASSWORD" 197 | If Args.Count >= ( nArgCount + 1 ) Then 198 | sPassword = Args( nArgCount + 1 ) 199 | End If 200 | End Select 201 | Next 202 | 203 | If Args.Count < EXPECTED_ARGUMENTS Then 204 | WScript.Echo ERROR_MISSING_ARGUMENTS & "|" & "Error: Not Enough Arguments" 205 | WScript.Quit ERROR_MISSING_ARGUMENTS 206 | End If 207 | End Function 208 | 209 | Private Function changeHealthValues(ByRef xmlDoc) 210 | Dim nodes :Set nodes = xmlDoc.documentElement.selectNodes("//n1:HealthState") 211 | Dim i 212 | For i = 0 To nodes.Length -1 213 | nodes(i).Text = 6 214 | Next 215 | End Function 216 | 217 | Public Function checkConnectionState 218 | On Error Resume Next 219 | oSession.Identify 220 | If Err.Number <> 0 Then 221 | If hex(Err.Number) = "80338126" Then 222 | WScript.Echo ERROR_CONNECTION_FAIL_WSMAN_HOST & "|" & "Failed to Connect - Host Unreachable" 223 | WScript.Quit ERROR_CONNECTION_FAIL_WSMAN_HOST 224 | ElseIf hex(Err.Number) = "80072F8F" Then 225 | WScript.Echo ERROR_CONNECTION_FAIL_WSMAN_ESX & "|" & "Failed to Connect - Not an ESX Server" 226 | WScript.Quit ERROR_CONNECTION_FAIL_WSMAN_ESX 227 | ElseIf hex(Err.Number) = "80070005" Then 228 | WScript.Echo ERROR_CONNECTION_FAIL_CREDENTIALS & "|" & "Failed to connect - Ensure credentials are valid/have correct permissions" 229 | WScript.Quit ERROR_CONNECTION_FAIL_CREDENTIALS 230 | Else 231 | WScript.Echo ERROR_CONNECTION_FAIL_WSMAN_UNKNOWN & "|" & "Failed to connect - An unknown error occured. Please ensure this host is a valid ESX server" 232 | WScript.Quit ERROR_CONNECTION_FAIL_WSMAN_UNKNOWN 233 | End If 234 | End If 235 | On Error Goto 0 236 | 237 | Err.Clear 238 | 239 | isConnected = True 240 | End Function 241 | 242 | 243 | ' ----------------------------------------------------------------------------- 244 | ' Run the Script 245 | ' ----------------------------------------------------------------------------- 246 | 247 | ' Expected Arguments 248 | ' -host 249 | ' -username 250 | ' -password 251 | 252 | 253 | Dim sHost 254 | Dim sUsername 255 | Dim sPassword 256 | 257 | Dim Args 258 | Set Args = WScript.Arguments 259 | Dim nArgCount 260 | 261 | 262 | Class_Initialize 263 | checkArguments 264 | setCredentials sHost, sUsername, sPassword 265 | Connect True,True 266 | checkConnectionState 267 | 268 | ' start forming the xml string 269 | sXmlDocContent = "" 270 | sXmlDocContent = sXmlDocContent & "" 271 | ' get psu information 272 | sXmlDocContent = sXmlDocContent & "" 273 | getPsuCheckInformation 274 | sXmlDocContent = sXmlDocContent & "" 275 | ' close the xml string and return 276 | sXmlDocContent = sXmlDocContent & "" 277 | 278 | 279 | ' return pass or fail 280 | IF fSuccess = 1 Then 281 | WScript.Echo PASSED_CHECK & "|" & sXmlDocContent & "|" & nPassing & "|" & nFailing & "|" & nUnknown 282 | WScript.Quit PASSED_CHECK 283 | Else 284 | WScript.Echo FAILED_CHECK & "|" & sXmlDocContent & "|" & nPassing & "|" & nFailing & "|" & nUnknown 285 | WScript.Quit FAILED_CHECK 286 | End If -------------------------------------------------------------------------------- /Resources/script_1024_33.vbs: -------------------------------------------------------------------------------- 1 | Option Explicit 2 | ' ----------------------------------------------------------------------------- 3 | ' Sensor Information - Alert When Not OK 4 | ' ----------------------------------------------------------------------------- 5 | ' Parameters: 6 | ' script.vbs --username "Username" -password "Password" -host "111.111.111.111" 7 | ' ----------------------------------------------------------------------------- 8 | ' Version Information 9 | ' ----------------------------------------------------------------------------- 10 | ' $LastChangedDate: 2013-03-15 14:19:20 +0000 (Fri, 15 Mar 2013) $ 11 | ' $Rev: 38413 $ 12 | ' ----------------------------------------------------------------------------- 13 | 14 | Const PASSED_CHECK = 0 15 | Const ERROR_MISSING_ARGUMENTS = 1 16 | Const ERROR_CONNECTION_FAIL_CREDENTIALS = 1001 17 | Const ERROR_CONNECTION_FAIL_WSMAN_HOST = 1002 18 | Const ERROR_CONNECTION_FAIL_WSMAN_ESX = 1003 19 | Const ERROR_CONNECTION_FAIL_WSMAN_UNKNOWN = 1004 20 | Const FAILED_CHECK = 2003 21 | 22 | Const CONNECTION_FAIL_WSMAN_STATUS = -1 23 | Const CONNECTION_FAIL_CREDENTIALS_STATUS = -2 24 | Const HEALTHSTATE_UNKNOWN = "0" 25 | Const HEALTHSTATE_OK = "5" 26 | Const EXPECTED_ARGUMENTS = 6 27 | 28 | Private Host 29 | Private Username 30 | Private Password 31 | 32 | Private isConnected 'True/False 33 | 34 | Private OMCSchema 35 | Private DMTFSchema 36 | Private VMWareSchema 37 | 38 | Private oWSMan 39 | Private oOptions 40 | Private oSession 41 | 42 | Private sXmlDocContent 43 | Private fSuccess 44 | Private nFailing 45 | Private nPassing 46 | Private nUnknown 47 | Private forceFailMode 48 | 49 | Public Function Class_Initialize() 50 | fSuccess = 1 51 | nFailing = 0 52 | nPassing = 0 53 | nUnknown = 0 54 | OMCSchema = "http://schema.omc-project.org/wbem/wscim/1/cim-schema/2/" 55 | DMTFSchema = "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/" 56 | VMWareSchema = "http://schemas.vmware.com/wbem/wscim/1/cim-schema/2/" 57 | End Function 58 | 59 | Public Function setCredentials(strHost, strUsername, strPassword) 60 | Host = strHost 61 | Username = strUsername 62 | Password = strPassword 63 | End Function 64 | 65 | Public Function Connect(fSkipCA, fSkipCN) 66 | Set oWSMan = CreateObject("Wsman.Automation") 67 | Set oOptions = oWSMan.CreateConnectionOptions 68 | 69 | oOptions.userName = Username 70 | oOptions.Password = Password 71 | 72 | Dim ConnectionFlags : ConnectionFlags = oWSMan.SessionFlagUseBasic 73 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagCredUserNamePassword 74 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagUTF8 75 | 76 | On Error Resume Next 77 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagSkipRevocationCheck 78 | If fSkipCA = True Then 79 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagSkipCACheck 80 | End If 81 | If fSkipCN = True Then 82 | ConnectionFlags = ConnectionFlags Or oWSMan.SessionFlagSkipCNCheck 83 | End If 84 | On Error Goto 0 85 | 86 | Set oSession = oWSMan.CreateSession("https://" & Host & "/wsman",ConnectionFlags,oOptions) 87 | 88 | If oSession is Nothing Then 89 | Connect = CONNECTION_FAIL_WSMAN_STATUS 'WSMan is either not installed or credentials failed. 90 | End If 91 | 92 | End Function 93 | 94 | 95 | '{GFI-MIXINS} 96 | 97 | Private Function updateSummaryHealthCounts( healthState ) 98 | If HealthState = HEALTHSTATE_OK Then 99 | nPassing = nPassing + 1 100 | ElseIf HealthState = HEALTHSTATE_UNKNOWN Then 101 | nUnknown = nUnknown + 1 102 | Else 103 | fSuccess = 0 104 | nFailing = nFailing + 1 105 | End If 106 | End Function 107 | 108 | Public Function getSensorCheckInformation 109 | Dim UnitModifier, Caption, HealthState, EnabledDefault, EnabledState, CurrentReading, CurrentState, TimeOfCurrentReading, BaseUnit, RateUnit, xmlDom 110 | 111 | Dim strBase : strBase = getBaseURL("OMC_NumericSensor") 112 | Dim strQueryResource : strQueryResource = strBase & "OMC_NumericSensor" 113 | Dim oQueryResponse : Set oQueryResponse = oSession.Enumerate(strQueryResource) 114 | While Not oQueryResponse.AtEndOfStream 115 | Set xmlDom = LoadDom( oQueryResponse.ReadItem ) 116 | Caption = ParseXML(xmlDom, "/n1:OMC_NumericSensor/n1:Caption") 117 | HealthState = Replace(ParseXML(xmlDom, "/n1:OMC_NumericSensor/n1:HealthState"), "NULL", "0") 118 | EnabledDefault = ParseXML(xmlDom, "/n1:OMC_NumericSensor/n1:EnabledDefault") 119 | EnabledState = ParseXML(xmlDom, "/n1:OMC_NumericSensor/n1:EnabledState") 120 | CurrentReading = ParseXML(xmlDom, "/n1:OMC_NumericSensor/n1:CurrentReading") 121 | CurrentState = ParseXML(xmlDom, "/n1:OMC_NumericSensor/n1:CurrentState") 122 | TimeOfCurrentReading = ParseXML(xmlDom, "/n1:OMC_NumericSensor/n1:TimeOfCurrentReading") 123 | BaseUnit = ParseXML(xmlDom, "/n1:OMC_NumericSensor/n1:BaseUnits") 124 | UnitModifier = ParseXML(xmlDom, "/n1:OMC_NumericSensor/n1:UnitModifier") 125 | RateUnit = ParseXML(xmlDom, "/n1:OMC_NumericSensor/n1:RateUnits") 126 | 127 | CurrentReading = CurrentReading*10^UnitModifier 128 | CurrentReading = CurrentReading & "__" & BaseUnit & "__" & RateUnit 129 | 130 | updateSummaryHealthCounts HealthState 131 | 132 | sXmlDocContent = sXmlDocContent & "" 133 | 134 | WEnd 135 | 136 | End Function 137 | 138 | Public Function getBaseURL(strCIMClass) 139 | If inStr(strCIMClass, "CIM_") <> 0 Then 140 | GetBaseURL = DMTFSchema 141 | ElseIf inStr(strCIMClass, "OMC_") <> 0 Then 142 | GetBaseURL = OMCSchema 143 | ElseIf inStr(strCIMClass, "VMware_") <> 0 Then 144 | GetBaseURL = VMWareSchema 145 | Else 146 | GetBaseURL = -1 147 | End If 148 | End Function 149 | 150 | Public Function LoadDom( ByRef Response ) 151 | Dim xmlData : Set xmlData = CreateObject("MSXml2.DOMDocument.3.0") 152 | xmlData.LoadXml( Response ) 153 | Set LoadDom = xmlData 154 | End Function 155 | 156 | Public Function ParseXML( ByRef xmlData,NodeName ) 157 | If forceFailMode Then changeHealthValues xmlData 158 | Dim node : Set node = xmlData.selectSingleNode(NodeName) 159 | Dim attrib : attrib = node.getAttribute("xsi:nil") & "" 160 | If attrib = "true" Then 161 | ParseXML = "NULL" 162 | Else 163 | ParseXML = node.text 164 | End If 165 | End Function 166 | 167 | Public Function checkArguments 168 | For nArgCount = 0 to Args.Count - 1 169 | Select Case UCase(Args(nArgCount)) 170 | Case "-FORCEFAIL" 171 | forceFailMode = True 172 | Case "-HOST" 173 | If Args.Count >= ( nArgCount + 1 ) Then 174 | sHost = Args( nArgCount + 1 ) 175 | End If 176 | Case "-USERNAME" 177 | If Args.Count >= ( nArgCount + 1 ) Then 178 | sUsername = Args( nArgCount + 1 ) 179 | End If 180 | Case "-PASSWORD" 181 | If Args.Count >= ( nArgCount + 1 ) Then 182 | sPassword = Args( nArgCount + 1 ) 183 | End If 184 | End Select 185 | Next 186 | 187 | If Args.Count < EXPECTED_ARGUMENTS Then 188 | WScript.Echo ERROR_MISSING_ARGUMENTS & "|" & "Error: Not Enough Arguments" 189 | WScript.Quit ERROR_MISSING_ARGUMENTS 190 | End If 191 | End Function 192 | 193 | Private Function changeHealthValues(ByRef xmlDoc) 194 | Dim nodes :Set nodes = xmlDoc.documentElement.selectNodes("//n1:HealthState") 195 | Dim i 196 | For i = 0 To nodes.Length -1 197 | nodes(i).Text = 6 198 | Next 199 | End Function 200 | 201 | Public Function checkConnectionState 202 | On Error Resume Next 203 | oSession.Identify 204 | 'WScript.Echo Err.Description 205 | 'WScript.Echo hex(Err.Number) 206 | If Err.Number <> 0 Then 207 | If hex(Err.Number) = "80338126" Then 208 | WScript.Echo ERROR_CONNECTION_FAIL_WSMAN_HOST & "|" & "Failed to Connect - Host Unreachable" 209 | WScript.Quit ERROR_CONNECTION_FAIL_WSMAN_HOST 210 | ElseIf hex(Err.Number) = "80072F8F" Then 211 | WScript.Echo ERROR_CONNECTION_FAIL_WSMAN_ESX & "|" & "Failed to Connect - Not an ESX Server" 212 | WScript.Quit ERROR_CONNECTION_FAIL_WSMAN_ESX 213 | ElseIf hex(Err.Number) = "80070005" Then 214 | WScript.Echo ERROR_CONNECTION_FAIL_CREDENTIALS & "|" & "Failed to connect - Ensure credentials are valid/have correct permissions" 215 | WScript.Quit ERROR_CONNECTION_FAIL_CREDENTIALS 216 | Else 217 | WScript.Echo ERROR_CONNECTION_FAIL_WSMAN_UNKNOWN & "|" & "Failed to connect - An unknown error occured. Please ensure this host is a valid ESX server" 218 | WScript.Quit ERROR_CONNECTION_FAIL_WSMAN_UNKNOWN 219 | End If 220 | End If 221 | On Error Goto 0 222 | 223 | Err.Clear 224 | 225 | isConnected = True 226 | End Function 227 | 228 | 229 | ' ----------------------------------------------------------------------------- 230 | ' Run the Script 231 | ' ----------------------------------------------------------------------------- 232 | 233 | ' Expected Arguments 234 | ' -host 235 | ' -username 236 | ' -password 237 | 238 | 239 | Dim sHost 240 | Dim sUsername 241 | Dim sPassword 242 | 243 | Dim Args 244 | Set Args = WScript.Arguments 245 | 246 | Dim nArgCount 247 | 248 | 249 | Class_Initialize 250 | checkArguments 251 | setCredentials sHost, sUsername, sPassword 252 | 253 | Connect True,True 254 | checkConnectionState 255 | 256 | ' start forming the xml string 257 | sXmlDocContent = "" 258 | sXmlDocContent = sXmlDocContent & "" 259 | ' get sensor information 260 | sXmlDocContent = sXmlDocContent & "" 261 | getSensorCheckInformation 262 | sXmlDocContent = sXmlDocContent & "" 263 | ' close the xml string and return 264 | sXmlDocContent = sXmlDocContent & "" 265 | 266 | 267 | ' return pass or fail 268 | IF fSuccess = 1 Then 269 | WScript.Echo PASSED_CHECK & "|" & sXmlDocContent & "|" & nPassing & "|" & nFailing & "|" & nUnknown 270 | WScript.Quit PASSED_CHECK 271 | Else 272 | WScript.Echo FAILED_CHECK & "|" & sXmlDocContent & "|" & nPassing & "|" & nFailing & "|" & nUnknown 273 | WScript.Quit FAILED_CHECK 274 | End If -------------------------------------------------------------------------------- /Resources/script_1024_34.ps1: -------------------------------------------------------------------------------- 1 | ########################################################### 2 | # Script to list all VMs on a specified host device 3 | ########################################################### 4 | 5 | ########################################################### 6 | # Version Information 7 | ########################################################### 8 | # $LastChangedDate: 2012-12-13 15:17:00 +0000 (Thu, 13 Dec 2012) $ 9 | # $Rev: 36386 $ 10 | ########################################################### 11 | 12 | param( [string]$HostName = '', [string]$UserName = '', [string]$Password = '', [switch]$AllRunning = $false, [Parameter(Mandatory=$false)][string]$LogFile ) 13 | 14 | Set ERROR_INVALID_ARGS -Option Constant -Value 1 15 | Set ERROR_CANNOT_FIND_SNAPIN -Option Constant -Value 1005 16 | Set ERROR_CANNOT_CONNECT_TO_SERVER_CREDENTIALS -Option Constant -Value 1001 17 | Set ERROR_CANNOT_CONNECT_TO_SERVER_UNREACHABLE -Option Constant -Value 1002 18 | Set ERROR_A_VM_POWERED_DOWN -Option Constant -Value 1504 19 | 20 | function Get-StatRange( $inoEntity, $insStatName, $innIntervalSecs = 20, $inoStartTime = $null, $inoFinishTime = $null ) { 21 | if( $inoStartTime -eq $null ) { 22 | $inoStartTime = $global:oStartTime 23 | } 24 | if( $inoFinishTime -eq $null ) { 25 | $inoFinishTime = $global:oFinishTime 26 | } 27 | $oValue = get-stat -Entity $inoEntity -Stat $insStatName -MaxSamples 1000 -start $inoStartTime -finish $inoFinishTime -IntervalSecs 20 28 | return $oValue | Measure-Object -Property value -Average -Maximum -Minimum 29 | } 30 | 31 | function Exit-WithCode( [int]$innCode, [string]$insText = '' ) { 32 | Write-Host ( "{0}|{1}" -f $innCode, $insText ) 33 | if( $global:oVMServer -ne $null ) { 34 | Disconnect-VIServer -Server $global:oVMServer -Force -Confirm:$false -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 35 | } 36 | 37 | Exit $innCode 38 | } 39 | 40 | function Add-RequiredPSSnapin() { 41 | $sSnapInName = 'VMware.VimAutomation.Core' 42 | foreach( $oSnapIn in Get-PSSnapIn -Registered ) { 43 | if( $oSnapIn.Name -eq $sSnapInName ) { 44 | Add-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue 45 | return 46 | } 47 | } 48 | 49 | Exit-WithCode $ERROR_CANNOT_FIND_SNAPIN ( "Error: {0} Snapin does not exist" -f $sSnapInName ) 50 | } 51 | 52 | # BEGIN SCRIPT 53 | 54 | if( $HostName -eq '' -or $UserName -eq '' ) { 55 | Exit-WithCode $ERROR_INVALID_ARGS 'Error: Invalid Arguments' 56 | } 57 | 58 | $Error.Clear() 59 | 60 | Add-RequiredPSSnapIn 61 | 62 | $global:oVMServer = Connect-VIServer -Server $HostName -User $UserName -Password $Password -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 63 | if( $oVMServer -eq $null ) { 64 | if( $Error[0].Exception -match 'Cannot complete login due to an incorrect user name or password' ) { 65 | Exit-WithCode $ERROR_CANNOT_CONNECT_TO_SERVER_CREDENTIALS 'Error: Cannot connect to Server - credentials invalid' 66 | } else { # $Error[0].Exception -match 'Could not connect using the requested protocol' 67 | Exit-WithCode $ERROR_CANNOT_CONNECT_TO_SERVER_UNREACHABLE 'Error: Cannot connect to Server - unreachable' 68 | } 69 | } 70 | 71 | # Statistic time thresholds 72 | $global:oStartTime = ( Get-Date ).AddMinutes( -15 ) 73 | $global:oFinishTime = Get-Date 74 | 75 | # Get list of Virtual Machines on this host 76 | $aOutput = @( "" ) 77 | $aOutput += "" 78 | $aOutput += "" 79 | 80 | $fAllRunning = $true 81 | 82 | $aVMs = get-vm -Server $oVMServer -ErrorAction SilentlyContinue 83 | if( $aVMs -ne $null ) { 84 | $aVMs | ForEach-Object { 85 | $sVMNode = "" 88 | $fAllRunning = $false 89 | } else { 90 | $aOutput += $sVMNode + ">" 91 | $aOutput += "" -f $_.MemoryMB 92 | $aOutput += "" -f ( Get-StatRange $_ 'mem.usage.average' ).Average 93 | $aOutput += "" -f ( Get-StatRange $_ 'cpu.usage.average' ).Average 94 | $aOutput += "" -f ( ( Get-StatRange $_ 'net.usage.average' ).Average * 8 ) 95 | $aOutput += "" -f ( ( Get-StatRange $_ 'net.received.average' ).Average * 8 ) 96 | $aOutput += "" -f ( ( Get-StatRange $_ 'net.transmitted.average' ).Average * 8 ) 97 | $aOutput += "" -f ( ( Get-StatRange $_ 'net.usage.average' 7200, ( ( Get-Date ).AddDays( -7 ) ) ).Average * 8 ) 98 | 99 | $nTotalDiskCapacity = 0 100 | $nTotalDiskFree = 0 101 | $oVMGuest = Get-VMGuest -VM $_ | Where { $_.Disks } | Foreach { $_.Disks | Foreach { 102 | $nTotalDiskCapacity += $_.Capacity 103 | $nTotalDiskFree += $_.FreeSpace 104 | } } 105 | 106 | if( $nTotalDiskCapacity -gt 0 ) { 107 | $aOutput += "" -f ( $nTotalDiskCapacity / 1048576 ) 108 | $aOutput += "" -f ( ( 1.0 - $nTotalDiskFree / $nTotalDiskCapacity ) * 100 ) 109 | } 110 | 111 | $aOutput += "" 112 | } 113 | } 114 | } 115 | 116 | $aOutput += "" 117 | $aOutput += "" 118 | 119 | if( !$fAllRunning -and $AllRunning ) { 120 | Exit-WithCode $ERROR_A_VM_POWERED_DOWN ( $aOutput -join "`r`n" ) 121 | } 122 | 123 | Exit-WithCode 0 ( $aOutput -join "`r`n" ) -------------------------------------------------------------------------------- /Resources/script_1024_35.ps1: -------------------------------------------------------------------------------- 1 | ########################################################### 2 | # Script to check power state of a specified VM 3 | ########################################################### 4 | 5 | ########################################################### 6 | # Version Information 7 | ########################################################### 8 | # $LastChangedDate: 2012-12-13 15:17:00 +0000 (Thu, 13 Dec 2012) $ 9 | # $Rev: 36386 $ 10 | ########################################################### 11 | 12 | param( [string]$HostName = '', [string]$UserName = '', [string]$Password = '', [string]$VMName = '', [Parameter(Mandatory=$false)][string]$LogFile ) 13 | 14 | Set ERROR_INVALID_ARGS -Option Constant -Value 1 15 | Set ERROR_CANNOT_FIND_SNAPIN -Option Constant -Value 1005 16 | Set ERROR_CANNOT_CONNECT_TO_SERVER_CREDENTIALS -Option Constant -Value 1001 17 | Set ERROR_CANNOT_CONNECT_TO_SERVER_UNREACHABLE -Option Constant -Value 1002 18 | Set ERROR_CANNOT_FIND_VM -Option Constant -Value 1506 19 | Set ERROR_VM_POWERED_DOWN -Option Constant -Value 1505 20 | 21 | function Get-StatRange( $inoEntity, $insStatName, $innIntervalSecs = 20, $inoStartTime = $null, $inoFinishTime = $null ) { 22 | if( $inoStartTime -eq $null ) { 23 | $inoStartTime = $global:oStartTime 24 | } 25 | if( $inoFinishTime -eq $null ) { 26 | $inoFinishTime = $global:oFinishTime 27 | } 28 | $oValue = get-stat -Entity $inoEntity -Stat $insStatName -MaxSamples 1000 -start $inoStartTime -finish $inoFinishTime -IntervalSecs 20 29 | return $oValue | Measure-Object -Property value -Average -Maximum -Minimum 30 | } 31 | 32 | function Exit-WithCode( [int]$innCode, [string]$insText = '' ) { 33 | Write-Host ( "{0}|{1}" -f $innCode, $insText ) 34 | if( $global:oVMServer -ne $null ) { 35 | Disconnect-VIServer -Server $global:oVMServer -Force -Confirm:$false -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 36 | } 37 | 38 | Exit $innCode 39 | } 40 | 41 | function Add-RequiredPSSnapin() { 42 | $sSnapInName = 'VMware.VimAutomation.Core' 43 | foreach( $oSnapIn in Get-PSSnapIn -Registered ) { 44 | if( $oSnapIn.Name -eq $sSnapInName ) { 45 | Add-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue 46 | return 47 | } 48 | } 49 | 50 | Exit-WithCode $ERROR_CANNOT_FIND_SNAPIN ( "Error: {0} Snapin does not exist" -f $sSnapInName ) 51 | } 52 | 53 | # BEGIN SCRIPT 54 | 55 | if( $HostName -eq '' -or $UserName -eq '' -or $VMName -eq '' ) { 56 | Exit-WithCode $ERROR_INVALID_ARGS 'Error: Invalid Arguments' 57 | } 58 | 59 | $Error.Clear() 60 | 61 | Add-RequiredPSSnapIn 62 | 63 | $global:oStartTime = ( Get-Date ).AddMinutes( -15 ) 64 | $global:oFinishTime = Get-Date 65 | $global:oVMServer = Connect-VIServer -Server $HostName -User $UserName -Password $Password -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 66 | if( $oVMServer -eq $null ) { 67 | if( $Error[0].Exception -match 'Cannot complete login due to an incorrect user name or password' ) { 68 | Exit-WithCode $ERROR_CANNOT_CONNECT_TO_SERVER_CREDENTIALS "Error: Cannot connect to Server - credentials invalid|$VMName" 69 | } else { # $Error[0].Exception -match 'Could not connect using the requested protocol' 70 | Exit-WithCode $ERROR_CANNOT_CONNECT_TO_SERVER_UNREACHABLE "Error: Cannot connect to Server - unreachable|$VMName" 71 | } 72 | } 73 | 74 | $aVMs = Get-VM -Server $oVMServer -Name $VMName -ErrorAction SilentlyContinue 75 | if( $aVMs -eq $null ) { 76 | Exit-WithCode $ERROR_CANNOT_FIND_VM "Error: Cannot find Virtual Machine|$VMName" 77 | } 78 | 79 | $oVM = @( $aVMs )[0] 80 | $sSelectedVMName = $oVM.Name 81 | 82 | $fPoweredOn = $oVM.PowerState -eq 'PoweredOn' 83 | if( !$fPoweredOn ) { 84 | Exit-WithCode $ERROR_VM_POWERED_DOWN "Error: Virtual Machine is not running|$sSelectedVMName" 85 | } 86 | 87 | $aOutput = @( "" ) 88 | $aOutput += "" 89 | 90 | $aOutput += "" -f $oVM.MemoryMB 91 | $aOutput += "" -f ( Get-StatRange $oVM 'mem.usage.average' ).Average 92 | $aOutput += "" -f ( Get-StatRange $oVM 'cpu.usage.average' ).Average 93 | $aOutput += "" -f ( ( Get-StatRange $oVM 'net.usage.average' ).Average * 8 ) 94 | $aOutput += "" -f ( ( Get-StatRange $oVM 'net.received.average' ).Average * 8 ) 95 | $aOutput += "" -f ( ( Get-StatRange $oVM 'net.transmitted.average' ).Average * 8 ) 96 | $aOutput += "" -f ( ( Get-StatRange $oVM 'net.usage.average' 7200, ( ( Get-Date ).AddDays( -7 ) ) ).Average * 8 ) 97 | 98 | $nTotalDiskCapacity = 0 99 | $nTotalDiskFree = 0 100 | $oVMGuest = Get-VMGuest -VM $oVM | Where { $_.Disks } | Foreach { $_.Disks | Foreach { 101 | $nTotalDiskCapacity += $_.Capacity 102 | $nTotalDiskFree += $_.FreeSpace 103 | } } 104 | 105 | if( $nTotalDiskCapacity -gt 0 ) { 106 | $aOutput += "" -f ( $nTotalDiskCapacity / 1048576 ) 107 | $aOutput += "" -f ( ( 1.0 - $nTotalDiskFree / $nTotalDiskCapacity ) * 100 ) 108 | } 109 | 110 | $aOutput += "" 111 | 112 | Exit-WithCode 0 ( ( $aOutput -join "`r`n" ) + "|$sSelectedVMName" ) -------------------------------------------------------------------------------- /Resources/script_1024_38.ps1: -------------------------------------------------------------------------------- 1 | ########################################################### 2 | # Script to check free space of datastores 3 | # 4 | # Params - ESXHost ESXUser ESXPassword ESXDatastore(supports * wildcard) unit(MB/ GB / PERCENT) threshold 5 | # 6 | ########################################################### 7 | 8 | ########################################################### 9 | # Version Information 10 | ########################################################### 11 | # $LastChangedDate: 2013-03-19 13:35:43 +0000 (Tues, 19 March 2013) $ 12 | # $Rev: 36208 $ 13 | ########################################################### 14 | 15 | param( [string]$hostName = '', [string]$userName = '', [string]$password = '', [string]$datastoreName = '', [string]$units = '', [string]$threshold = '', [string]$logFile ) 16 | 17 | Set ERROR_INVALID_ARGS -Option Constant -Value 1 18 | Set ERROR_CANNOT_FIND_SNAPIN -Option Constant -Value 1005 19 | Set ERROR_CANNOT_CONNECT_TO_SERVER_CREDENTIALS -Option Constant -Value 1001 20 | Set ERROR_CANNOT_CONNECT_TO_SERVER_UNREACHABLE -Option Constant -Value 1002 21 | Set ERROR_CANNOT_FIND_DATASTORE -Option Constant -Value 1508 22 | Set CHECK_PASSED -Option Constant -Value 0 23 | Set CHECK_FAILED -Option Constant -Value 2004 24 | 25 | function Exit-WithCode( [int]$innCode, [string]$insText = '' ) { 26 | Write-Host $insText 27 | if( $global:oVMServer -ne $null ) { 28 | Disconnect-VIServer -Server $global:oVMServer -Force -Confirm:$false -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 29 | } 30 | Exit $innCode 31 | } 32 | 33 | function Add-RequiredPSSnapin() { 34 | $sSnapInName = 'VMware.VimAutomation.Core' 35 | foreach( $oSnapIn in Get-PSSnapIn -Registered ) { 36 | if( $oSnapIn.Name -eq $sSnapInName ) { 37 | Add-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue 38 | return 39 | } 40 | } 41 | Exit-WithCode $ERROR_CANNOT_FIND_SNAPIN ("{0}|{1}" -f $ERROR_CANNOT_FIND_SNAPIN, 'Snapin does not exist '+ $sSnapInName) 42 | } 43 | 44 | 45 | # BEGIN SCRIPT 46 | 47 | 48 | 49 | 50 | #params have default value so if they are not passed in they will be empty - this way we can check and provide out own exit code 51 | if( $hostName -eq '' -or $userName -eq '' -or $password -eq '' -or $datastoreName -eq '' -or $units -eq '' -or $threshold -eq '') { 52 | Exit-WithCode $ERROR_INVALID_ARGS ("{0}|{1}" -f $ERROR_INVALID_ARGS, 'Error: Invalid Arguments') 53 | } 54 | 55 | Add-RequiredPSSnapIn 56 | 57 | $Error.Clear() 58 | 59 | $global:oVMServer = Connect-VIServer -Server $hostName -User $userName -Password $password -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 60 | if( $oVMServer -eq $null ) { 61 | if( $Error[0].Exception -match 'Cannot complete login due to an incorrect user name or password' ) { 62 | Exit-WithCode $ERROR_CANNOT_CONNECT_TO_SERVER_CREDENTIALS ("{0}|{1}" -f $ERROR_CANNOT_CONNECT_TO_SERVER_CREDENTIALS, 'Error: Cannot connect to Server - credentials invalid') 63 | } else { 64 | Exit-WithCode $ERROR_CANNOT_CONNECT_TO_SERVER_UNREACHABLE ("{0}|{1}" -f $ERROR_CANNOT_CONNECT_TO_SERVER_UNREACHABLE, 'Error: Cannot connect to Server - unreachable') 65 | } 66 | } 67 | 68 | 69 | $failCount = 0 70 | $okCount = 0 71 | $output = new-object System.Text.StringBuilder 72 | [void]$output.AppendLine("" ) 73 | [void]$output.AppendLine("") 74 | [void]$output.AppendLine("") 75 | 76 | $datastores = Get-Datastore -Name $DatastoreName -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 77 | if( $datastores -eq $null ) { 78 | Exit-WithCode $ERROR_CANNOT_FIND_DATASTORE ("{0}|{1}" -f $ERROR_CANNOT_FIND_DATASTORE, 'Error: Cannot find datastore') 79 | } 80 | 81 | ForEach ( $dataStore in $datastores ){ 82 | $nCapacityMB = $dataStore.CapacityMB 83 | $nCapacityGB = $dataStore.CapacityGB 84 | $nFreeSpaceMB = $dataStore.FreeSpaceMB 85 | $nFreeSpaceGB = $dataStore.FreeSpaceGB 86 | 87 | # PowerCli 4.x does not provide GB values, only MB 88 | If ($nCapacityGB -eq 0) { $nCapacityGB = $nCapacityMB/1024 } 89 | If ($nFreeSpaceGB -eq 0) { $nFreeSpaceGB = $nFreeSpaceMB/1024 } 90 | 91 | #prepare values not provided by api 92 | $usedMB = $nCapacityMB - $nFreeSpaceMB 93 | 94 | #PowerCLI 5.0 has a known issue whereby free and capacity is mixed up - therefore if used value is negative, switch the core values around 95 | if( $usedMB -lt 0 ){ 96 | $nCapacityMB = $dataStore.FreeSpaceMB 97 | $nFreeSpaceMB = $dataStore.CapacityMB 98 | $usedMB = $nCapacityMB - $nFreeSpaceMB 99 | } 100 | 101 | $usedGB = $nCapacityGB - $nFreeSpaceGB 102 | if( $usedGB -lt 0 ){ 103 | $nCapacityGB = $dataStore.FreeSpaceGB 104 | $nFreeSpaceGB = $dataStore.CapacityGB 105 | $usedGB = $nCapacityGB - $nFreeSpaceGB 106 | } 107 | 108 | $percentFree = [math]::Round( ( 100 * $nFreeSpaceMB / $nCapacityMB ) ,0) 109 | 110 | #prepare value to check based on units passed in 111 | $valueToCheck = 0 112 | if($units -ieq "MB"){ 113 | $valueToCheck = $nFreeSpaceMB 114 | }elseif($units -ieq "GB"){ 115 | $valueToCheck = $nFreeSpaceGB 116 | }elseif($units -ieq "PERCENT"){ 117 | $valueToCheck = $percentFree 118 | } 119 | 120 | #check if threshold has been breached 121 | [Bool]$thresholdBreached = $false #assume false 122 | if( $valueToCheck -lt $threshold){ 123 | $thresholdBreached = $true 124 | $failCount += 1 125 | }else{ 126 | $okCount += 1 127 | } 128 | 129 | [void]$output.AppendLine("") 138 | } 139 | 140 | [void]$output.AppendLine("") 141 | [void]$output.AppendLine("") 142 | 143 | if ($failCount -eq 0){ 144 | Exit-WithCode $CHECK_PASSED ("{0}|{1}|{2}|{3}" -f $CHECK_PASSED, $output.ToString(), $okCount, $failCount) 145 | }else{ 146 | Exit-WithCode $CHECK_FAILED ("{0}|{1}|{2}|{3}" -f $CHECK_FAILED, $output.ToString(), $okCount, $failCount) 147 | } 148 | -------------------------------------------------------------------------------- /Resources/script_1024_39.ps1: -------------------------------------------------------------------------------- 1 | ########################################################### 2 | # Script to gather healthstatus of disk sensors 3 | # 4 | # Parameters - ESXHost ESXUSer ESXPassword 5 | # 6 | ########################################################### 7 | 8 | ########################################################### 9 | # Version Information 10 | ########################################################### 11 | # $LastChangedDate: 2013-03-19 13:35:43 +0000 (Tues, 19 March 2013) $ 12 | # $Rev: 36208 $ 13 | ########################################################### 14 | 15 | param( [string]$hostName = '', [string]$userName = '', [string]$password = '',[string]$logFile ) 16 | 17 | Set ERROR_INVALID_ARGS -Option Constant -Value 1 18 | Set ERROR_CANNOT_FIND_SNAPIN -Option Constant -Value 1005 19 | Set ERROR_CANNOT_CONNECT_TO_SERVER_CREDENTIALS -Option Constant -Value 1001 20 | Set ERROR_CANNOT_CONNECT_TO_SERVER_UNREACHABLE -Option Constant -Value 1002 21 | Set ERROR_DOES_NOT_EXIST -Option Constant -Value 2005 22 | Set CHECK_PASSED -Option Constant -Value 0 23 | Set CHECK_FAILED -Option Constant -Value 2003 24 | 25 | function Exit-WithCode( [int]$innCode, [string]$insText = '' ) { 26 | Write-Host $insText 27 | if( $global:oVMServer -ne $null ) { 28 | Disconnect-VIServer -Server $global:oVMServer -Force -Confirm:$false -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 29 | } 30 | Exit $innCode 31 | } 32 | 33 | function Add-RequiredPSSnapin() { 34 | $sSnapInName = 'VMware.VimAutomation.Core' 35 | foreach( $oSnapIn in Get-PSSnapIn -Registered ) { 36 | if( $oSnapIn.Name -eq $sSnapInName ) { 37 | Add-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue 38 | return 39 | } 40 | } 41 | Exit-WithCode $ERROR_CANNOT_FIND_SNAPIN ("{0}|{1}" -f $ERROR_CANNOT_FIND_SNAPIN, 'Snapin does not exist '+ $sSnapInName) 42 | } 43 | 44 | # HELPER FUNCTIONS 45 | 46 | function Add-Record( [REF]$sbXml, $name, $healthstateKey, $healthstateSummary ){ 47 | [void]$sbXml.value.Append( "" ) 53 | } 54 | 55 | function Record-Healthstate( $healthKey ){ 56 | if( $healthKey -eq 'green' ){ 57 | $global:okCount += 1 58 | }elseif( $healthKey -eq 'unknown' ){ 59 | $global:unknownCount += 1 60 | }else{ 61 | $global:failCount += 1 62 | } 63 | } 64 | 65 | 66 | # BEGIN SCRIPT 67 | 68 | if( $hostName -eq '' -or $userName -eq '' -or $password -eq '') { 69 | Exit-WithCode $ERROR_INVALID_ARGS ("{0}|{1}" -f $ERROR_INVALID_ARGS, 'Error: Invalid Arguments') 70 | } 71 | 72 | Add-RequiredPSSnapIn 73 | 74 | $Error.Clear() 75 | 76 | $global:oVMServer = Connect-VIServer -Server $hostName -User $userName -Password $password -ErrorAction SilentlyContinue -WarningAction SilentlyContinue 77 | if( $oVMServer -eq $null ) { 78 | if( $Error[0].Exception -match 'Cannot complete login due to an incorrect user name or password' ) { 79 | Exit-WithCode $ERROR_CANNOT_CONNECT_TO_SERVER_CREDENTIALS ("{0}|{1}" -f $ERROR_CANNOT_CONNECT_TO_SERVER_CREDENTIALS, 'Error: Cannot connect to Server - credentials invalid') 80 | } else { 81 | Exit-WithCode $ERROR_CANNOT_CONNECT_TO_SERVER_UNREACHABLE ("{0}|{1}" -f $ERROR_CANNOT_CONNECT_TO_SERVER_UNREACHABLE, 'Error: Cannot connect to Server - unreachable') 82 | } 83 | } 84 | 85 | #get health status system view 86 | $hostView = Get-VMHost | Get-View 87 | $healthStatusSystem = Get-View $hostView.ConfigManager.HealthStatusSystem 88 | 89 | $global:failCount = 0 90 | $global:okCount = 0 91 | $global:unknownCount = 0 92 | 93 | $output = new-object System.Text.StringBuilder 94 | [void]$output.AppendLine( "" ) 95 | [void]$output.AppendLine( "" ) 96 | [void]$output.AppendLine( "" ) 97 | 98 | ForEach ( $entry in $healthStatusSystem.Runtime.HardwareStatusInfo.storageStatusInfo) { 99 | if( $entry.name ){ 100 | Add-Record([REF]$output) $entry.name $entry.status.key $entry.status.summary 101 | Record-Healthstate $entry.status.key 102 | } 103 | } 104 | 105 | #some esx versions / hardware does not show anything under storagestatusinfo, so query numericsensor info 106 | ForEach ( $entry in $healthStatusSystem.Runtime.SystemHealthInfo.numericSensorInfo) { 107 | if( ( $entry.name.ToLower().Contains("disk") -or ( $entry.sensorType.ToLower() -eq "storage" ) ) -and $entry.name ){ #show items containing "disk" - may be disk, disk cable, disk battery etc sensors, and any sensors with type "Storage" 108 | Add-Record([REF]$output) $entry.name $entry.healthState.key $entry.healthState.summary 109 | Record-Healthstate $entry.healthState.key 110 | } 111 | } 112 | 113 | [void]$output.AppendLine( "" ) 114 | [void]$output.AppendLine( "" ) 115 | 116 | if( $global:okCount + $global:failCount + $global:unknownCount -eq 0 ){ 117 | Exit-WithCode $ERROR_DOES_NOT_EXIST ("{0}|{1}" -f $ERROR_DOES_NOT_EXIST, 'Error: No Storage sensors') 118 | } 119 | 120 | if ( $global:failCount -eq 0 ){ 121 | Exit-WithCode $CHECK_PASSED ("{0}|{1}|{2}|{3}|{4}" -f $CHECK_PASSED, $output.ToString(), $global:okCount, $global:failCount, $global:unknownCount) 122 | }else{ 123 | Exit-WithCode $CHECK_FAILED ("{0}|{1}|{2}|{3}|{4}" -f $CHECK_FAILED, $output.ToString(), $global:okCount, $global:failCount, $global:unknownCount) 124 | } -------------------------------------------------------------------------------- /SNMP/MAXFocus_SNMP_Checks.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .DESCRIPTION 3 | Scan an SNMP target for known OIDs with values. 4 | Add SNMP checks to agent. 5 | 6 | .AUTHOR 7 | Hugo L. Klemmestad 8 | .DATE 9 | 03.11.2014 10 | .LINK 11 | http://klemmestad.com/2014/12/10/add-snmp-checks-to-maxfocus-automatically/ 12 | .VERSION 13 | 1.14 14 | #> 15 | 16 | # Using [string] for almost all parameters to avoid parameter validation fail 17 | Param ( 18 | [string]$Community = "public", 19 | 20 | [array]$Target = "localhost", 21 | 22 | [string]$UDPport = 161, 23 | 24 | [switch]$Apply = $false, 25 | 26 | [string]$ReportMode = "On", 27 | 28 | [string]$Name, 29 | 30 | # We must accept -logfile, because it is always given by task_start.js 31 | # Not accepting it will make the script fail with not output to Dashboard 32 | # Put it in %TEMP% if script is run interactively 33 | [string]$logfile = "{0}\logfile.log" -f $env:TEMP, 34 | 35 | [switch]$Debug = $false, 36 | [switch]$Verbose = $false 37 | 38 | ) 39 | 40 | 41 | 42 | # Enhanced Output-Host function to capture log info 43 | function Output-Host { 44 | [string]$Text = "" 45 | Foreach ($arg in $args) { $Text += $arg } 46 | Write-Host $Text 47 | # Include normal output in debug log 48 | Output-Debug $Text 49 | } 50 | 51 | 52 | # Output text to $logfile if Debug set 53 | function Output-Debug { 54 | If ($Debug) { 55 | [string]$Text = "" 56 | Foreach ($arg in $args) { $Text += $arg } 57 | ('{0}: {1}' -f (Get-Date),$Text) | Out-File -Append $logfile 58 | } 59 | } 60 | 61 | # Output text to STDOUT if Verbose set 62 | function Output-Verbose { 63 | If ($Verbose) { 64 | [string]$Text = "VERBOSE: " 65 | Foreach ($arg in $args) { $Text += $arg } 66 | Output-Host $Text 67 | } 68 | } 69 | 70 | # Print to STDOUT to make sure task_start.js gets some output 71 | Output-Host "Result: " 72 | 73 | # Require version 2.0 74 | If (!($PSVersionTable)) { 75 | Output-Host "Error: Script requires Powershell version 2.0 or greater." 76 | Output-Host "Aborting.." 77 | #Exit 0 78 | } 79 | 80 | Output-Verbose ("Hostname: {0}" -f $env:COMPUTERNAME) 81 | Output-Verbose ("PowerShell PSVersion: {0}" -f $PSVersionTable.PSVersion) 82 | Output-Verbose ("PowerShell CLRVersion: {0}" -f $PSVersionTable.CLRVersion) 83 | Output-Verbose ("PowerShell BuildVersion: {0}" -f $PSVersionTable.BuildVersion) 84 | 85 | # Validate $Community 86 | If ($Community.Length -eq 0) { 87 | Output-Verbose "-Community has Zero length. Using Default value of public." 88 | $Community = "public" 89 | } 90 | Output-Verbose ("Using {0} as value for Community string." -f $Community) 91 | 92 | # Give early feedback on Target 93 | Output-Verbose ("Number of Targets: {0}" -f $Target.Count) 94 | [int]$Count = 1 95 | Foreach ($element in $Target) { 96 | Output-Verbose ("Target {0}: {1}" -f $Count,$element) 97 | $Count++ 98 | } 99 | 100 | # Validate $UDPport 101 | $x2 = 0 102 | $isNum = [System.Int32]::TryParse($UDPport, [ref]$x2) 103 | If ($isNUM) { 104 | [int]$UDPport = $UDPport 105 | If ($UDPport -lt 1 -or $UDPport -gt 65535) { 106 | Output-Verbose "-UDPport $UDPport is out of bounds. Using Default value of 161." 107 | [int]$UDPport = 161 108 | } 109 | } Else { 110 | Output-Verbose "-UDPport cannot be converted to Integer. Using Default value of 161." 111 | [int]$UDPport = 161 112 | } 113 | Output-Verbose "Using $UDPport for -UDPport." 114 | 115 | # Invert Reportmode 116 | If ($ReportMode -match 'Off' -or $ReportMode -match 'false') { 117 | [bool]$ReportMode = $false 118 | Output-Verbose "Report Mode is OFF" 119 | } Else { 120 | [bool]$ReportMode = $true 121 | Output-Verbose "Report Mode is ON" 122 | } 123 | Output-Verbose "Using $ReportMode as value for -ReportMode." 124 | 125 | ## VARIUS FUNCTIONS 126 | 127 | # Downloaded from 128 | # http://blogs.technet.com/b/heyscriptingguy/archive/2011/08/20/use-powershell-to-work-with-any-ini-file.aspx 129 | # modified to use ordered list by me 130 | function Get-IniContent ($filePath) { 131 | $ini = New-Object System.Collections.Specialized.OrderedDictionary 132 | switch -regex -file $FilePath 133 | { 134 | "^\[(.+)\]" # Section 135 | { 136 | $section = $matches[1] 137 | $ini[$section] = New-Object System.Collections.Specialized.OrderedDictionary 138 | $CommentCount = 0 139 | } 140 | "^(;.*)$" # Comment 141 | { 142 | $value = $matches[1] 143 | $CommentCount = $CommentCount + 1 144 | $name = "Comment" + $CommentCount 145 | $ini[$section][$name] = $value 146 | } 147 | "(.+?)\s*=(.*)" # Key 148 | { 149 | $name,$value = $matches[1..2] 150 | $ini[$section][$name] = $value 151 | } 152 | } 153 | return $ini 154 | } 155 | 156 | # Downloaded from 157 | # http://blogs.technet.com/b/heyscriptingguy/archive/2011/08/20/use-powershell-to-work-with-any-ini-file.aspx 158 | # Modified to force overwrite by me 159 | function Out-IniFile($InputObject, $FilePath) { 160 | $outFile = New-Item -ItemType file -Path $Filepath -Force 161 | foreach ($i in $InputObject.keys) 162 | { 163 | if ("Hashtable","OrderedDictionary" -notcontains $($InputObject[$i].GetType().Name)) 164 | { 165 | #No Sections 166 | Add-Content -Path $outFile -Value "$i=$($InputObject[$i])" 167 | } else { 168 | #Sections 169 | Add-Content -Path $outFile -Value "[$i]" 170 | Foreach ($j in ($InputObject[$i].keys | Sort-Object)) 171 | { 172 | if ($j -match "^Comment[\d]+") { 173 | Add-Content -Path $outFile -Value "$($InputObject[$i][$j])" 174 | } else { 175 | Add-Content -Path $outFile -Value "$j=$($InputObject[$i][$j])" 176 | } 177 | 178 | } 179 | Add-Content -Path $outFile -Value "" 180 | } 181 | } 182 | } 183 | 184 | Function New-GenericObject { 185 | param( 186 | ## The generic type to create 187 | [Parameter(Mandatory = $true)] 188 | [string] $TypeName, 189 | 190 | ## The types that should be applied to the generic object 191 | [Parameter(Mandatory = $true)] 192 | [string[]] $TypeParameters, 193 | 194 | ## Arguments to be passed to the constructor 195 | [object[]] $ConstructorParameters 196 | ) 197 | 198 | Set-StrictMode -Version Latest 199 | 200 | ## Create the generic type name 201 | $genericTypeName = $typeName + '`' + $typeParameters.Count 202 | $genericType = [Type] $genericTypeName 203 | 204 | if(-not $genericType) 205 | { 206 | throw "Could not find generic type $genericTypeName" 207 | } 208 | 209 | ## Bind the type arguments to it 210 | [type[]] $typedParameters = $typeParameters 211 | $closedType = $genericType.MakeGenericType($typedParameters) 212 | if(-not $closedType) 213 | { 214 | throw "Could not make closed type $genericType" 215 | } 216 | 217 | ## Create the closed version of the generic type 218 | ,[Activator]::CreateInstance($closedType, $constructorParameters) 219 | } 220 | 221 | function Invoke-SNMPget ([string]$sIP, $sOIDs, [string]$Community = "public", [int]$UDPport = 161, [int]$TimeOut=3000) { 222 | # $OIDs can be a single OID string, or an array of OID strings 223 | # $TimeOut is in msec, 0 or -1 for infinite 224 | If ($Verbose) { 225 | Output-Debug ('Invoke-SNMPget called with $sIP={0}, $sOIDs={1}, $Community={2}, $UDPport={3}, $TimeOut={4}' -f $sIP, $sOIDs, $Community, $UDPport, $TimeOut) 226 | } 227 | # Create OID variable list 228 | If ($PSVersionTable.PSVersion.Major -lt 3) { 229 | $vList = New-GenericObject System.Collections.Generic.List Lextm.SharpSnmpLib.Variable # PowerShell v1 and v2 230 | } Else { 231 | $vList = New-Object 'System.Collections.Generic.List[Lextm.SharpSnmpLib.Variable]' # PowerShell v3 232 | } 233 | foreach ($sOID in $sOIDs) { 234 | $oid = New-Object Lextm.SharpSnmpLib.ObjectIdentifier ($sOID) 235 | $vList.Add($oid) 236 | } 237 | 238 | # Create endpoint for SNMP server 239 | $ip = [System.Net.IPAddress]::Parse($sIP) 240 | $svr = New-Object System.Net.IpEndPoint ($ip, $UDPport) 241 | 242 | # Use SNMP v2 243 | $ver = [Lextm.SharpSnmpLib.VersionCode]::V2 244 | 245 | # Perform SNMP Get 246 | try { 247 | $msg = [Lextm.SharpSnmpLib.Messaging.Messenger]::Get($ver, $svr, $Community, $vList, $TimeOut) 248 | } catch { 249 | $line = "" | Select OID, Data 250 | $line.OID = $oid 251 | $line.Data = "Error" 252 | Return $line 253 | } 254 | 255 | $res = @() 256 | foreach ($var in $msg) { 257 | $line = "" | Select OID, Data 258 | $line.OID = $var.Id.ToString() 259 | $line.Data = $var.Data.ToString() 260 | $res += $line 261 | } 262 | 263 | $res 264 | } 265 | 266 | Function Get-IPV4NetworkStartIP ($strNetwork) { 267 | $StrNetworkAddress = ($strNetwork.split("/"))[0] 268 | $NetworkIP = ([System.Net.IPAddress]$StrNetworkAddress).GetAddressBytes() 269 | [Array]::Reverse($NetworkIP) 270 | $NetworkIP = ([System.Net.IPAddress]($NetworkIP -join ".")).Address 271 | $StartIP = $NetworkIP +1 272 | #Convert To Double 273 | If (($StartIP.Gettype()).Name -ine "double") { 274 | $StartIP = [Convert]::ToDouble($StartIP) 275 | } 276 | $StartIP = [System.Net.IPAddress]$StartIP 277 | Return $StartIP 278 | } 279 | 280 | Function Get-IPV4NetworkEndIP ($strNetwork) { 281 | $StrNetworkAddress = ($strNetwork.split("/"))[0] 282 | [int]$NetworkLength = ($strNetwork.split("/"))[1] 283 | $IPLength = 32-$NetworkLength 284 | $NumberOfIPs = ([System.Math]::Pow(2, $IPLength)) -1 285 | $NetworkIP = ([System.Net.IPAddress]$StrNetworkAddress).GetAddressBytes() 286 | [Array]::Reverse($NetworkIP) 287 | $NetworkIP = ([System.Net.IPAddress]($NetworkIP -join ".")).Address 288 | $EndIP = $NetworkIP + $NumberOfIPs 289 | If (($EndIP.Gettype()).Name -ine "double") { 290 | $EndIP = [Convert]::ToDouble($EndIP) 291 | } 292 | $EndIP = [System.Net.IPAddress]$EndIP 293 | Return $EndIP 294 | } 295 | 296 | ## SETUP ENVIRONMENT 297 | # Find "Advanced Monitoring Agent" service and use path to locate files 298 | Output-Verbose "Locating Advanced Monitoring service and setting up variables." 299 | $gfimaxagent = Get-WmiObject Win32_Service | Where-Object { $_.Name -eq 'Advanced Monitoring Agent' } 300 | $gfimaxexe = $gfimaxagent.PathName 301 | $gfimaxpath = Split-Path $gfimaxagent.PathName.Replace('"',"") -Parent 302 | 303 | # XML Document objects 304 | $snmp_presets = New-Object -TypeName XML 305 | $XmlConfig = @{} 306 | 307 | # XML Document Pathnames 308 | $snmp_sys = $gfimaxpath + "\snmp_sys.xml" 309 | $XmlFile = @{} 310 | 311 | # We need an array of hashes to remember which checks to add 312 | $NewChecks = @() 313 | 314 | $Sets = @("247") 315 | 316 | # Other Pathnames 317 | $IniFile = $gfimaxpath + "\settings.ini" 318 | $ScriptLib = $gfimaxpath + "\scripts\lib" 319 | $LastChangeFile = $gfimaxpath + "\LastSNMPChange.log" 320 | $ConfigChanged = $false 321 | 322 | # Read ini-files 323 | $settingsContent = Get-IniContent($IniFile) 324 | 325 | # Load SNMP Library. Download file if it does not exist 326 | $SNMP_lib = $ScriptLib + "\SharpSnmpLib.dll" 327 | $SNMP_lib_URL = "https://github.com/klemmestad/PowerShell/raw/master/SNMP/lib/SharpSnmpLib.dll" 328 | 329 | # Catch and output any errors 330 | $ErrorActionPreference = 'STOP' 331 | Try { 332 | If (!(Test-Path $SNMP_lib)) { 333 | Output-Verbose "SharpSnmpLib.dll not found. Trying to download." 334 | If (!(Test-Path -PathType Container $ScriptLib)) { 335 | Output-Verbose "Creating directory $Scriptlib" 336 | New-Item -ItemType Directory -Force -Path $ScriptLib 337 | } 338 | 339 | $webclient = New-Object System.Net.WebClient 340 | Output-Verbose ("Starting download from {0}" -f $SNMP_lib_URL) 341 | $webclient.DownloadFile($SNMP_lib_URL,$SNMP_lib) 342 | Output-Verbose "SNMP library not found. Downloaded from web." 343 | If ($PSVersionTable.PSVersion.Major -gt 2) { 344 | Unblock-File -Path $SNMP_lib 345 | } 346 | } 347 | 348 | $null = [reflection.assembly]::LoadFrom($SNMP_lib) 349 | 350 | # Read configuration of checks. Create an XML object if they do not exist yet. 351 | ForEach ($Set in $Sets) { 352 | $XmlConfig[$Set] = New-Object -TypeName XML 353 | $XmlFile[$Set] = $gfimaxpath + "\{0}_Config.xml" -f $Set 354 | If (Test-Path $XmlFile[$Set]) { 355 | $XmlConfig[$Set].Load($XmlFile[$Set]) 356 | $XmlConfig[$Set].DocumentElement.SetAttribute("modified","1") 357 | } Else { 358 | $decl = $XmlConfig[$Set].CreateXmlDeclaration("1.0", "ISO-8859-1", $null) 359 | $rootNode = $XmlConfig[$Set].CreateElement("checks") 360 | $result = $rootNode.SetAttribute("modified", "1") 361 | $result = $XmlConfig[$Set].InsertBefore($decl, $XmlConfig[$Set].DocumentElement) 362 | $result = $XmlConfig[$Set].AppendChild($rootNode) 363 | } 364 | } 365 | 366 | # Check Agent mode, workstation or server 367 | $AgentMode = $AgentConfig.agentconfiguration.agentmode 368 | 369 | If (Test-Path $snmp_sys) { 370 | $snmp_presets.Load($snmp_sys) 371 | } 372 | 373 | $System = ".1.3.6.1.2.1.1.2.0" 374 | $SNMPhosts = @() 375 | 376 | If ($Target -match "/") { 377 | $FirstIP = @((Get-IPV4NetworkStartIP ($Target[0])).ToString().Split(".")) 378 | $LastIP = @((Get-IPV4NetworkEndIP ($Target[0])).ToString().Split(".")) 379 | 380 | ForEach ($Byte1 in $FirstIP[0]..$LastIP[0]) { 381 | ForEach ($Byte2 in $FirstIP[1]..$LastIP[1]) { 382 | ForEach ($Byte3 in $FirstIP[2]..$LastIP[2]) { 383 | ForEach ($Byte4 in $FirstIP[3]..$LastIP[3]) { 384 | $SNMPhost = "{0}.{1}.{2}.{3}" -f $Byte1, $Byte2, $Byte3, $Byte4 385 | 386 | # Test if Target responds on SNMP port 387 | Output-Verbose ('Trying to read value of "System" on {0}.' -f $SNMPhost) 388 | $oidValue = Invoke-SNMPget $SNMPhost $System $Community $UDPport 389 | 390 | If ($oidValue.Data -notmatch "Error") { 391 | Output-Verbose ('Host {0} responded with {1}' -f $SNMPhost, $oidValue.Data) 392 | $SNMPhosts += $SNMPhost 393 | } Else { 394 | Output-Verbose ('Host {0} did not respond.' -f $SNMPhost) 395 | } 396 | } 397 | } 398 | } 399 | } 400 | } Else { 401 | $SNMPhosts = $Target 402 | } 403 | } Catch { 404 | Output-Host ("ERROR: Script failed on item: {0}" -f $_.Exception.ItemName) 405 | Output-Host $_.Exception.Message 406 | Exit 1000 407 | } 408 | 409 | ForEach ($SNMPhost in $SNMPhosts) { 410 | # Create REF variable of correct type 411 | $ip = [System.Net.IPAddress]::Parse("127.0.0.1") 412 | # Try to parse $SNMPhost as IP address 413 | If (!([System.Net.IPAddress]::TryParse($SNMPhost, [ref] $ip))) { 414 | Output-Verbose ('Tried to parse {0} as IP address. Assuming it is a DNS name.' -f $SNMPhost) 415 | # $SNMPhost is not a valid IP address. Maybe it is a hostname? 416 | Try { 417 | $ip = [System.Net.Dns]::GetHostAddresses($SNMPhost)[0] 418 | If ($ip -eq "::1") { $ip = [System.Net.IPAddress]::Parse("127.0.0.1") } 419 | } Catch { 420 | Output-Host ("ERROR: Could not resolve hostname ""{0}""" -f $SNMPhost) 421 | Continue 422 | } 423 | Output-Verbose ('Resolved {0} to IP address {1}' -f $SNMPhost, $ip) 424 | } Else { 425 | Output-Verbose ('Current Target is an IP address: {0}' -f $ip) 426 | } 427 | Output-Verbose ('Using {0} as IP address of current SNMPhost' -f $ip) 428 | Try { 429 | # Test if Target responds on SNMP port 430 | Output-Verbose ('Trying to read value of "System" on {0}.' -f $SNMPhost) 431 | $oidValue = Invoke-SNMPget $ip $System $Community $UDPport 432 | 433 | If ($oidValue.Data -notmatch "Error") { 434 | Output-Verbose ('Host {0} responded to SNMP. Testing presets.' -f $SNMPhost) 435 | } Else { 436 | Output-Verbose ('Host {0} did not respond to SNMP using {1} as Community String.' -f $SNMPhost,$Community) 437 | Continue 438 | } 439 | Output-Verbose "Looping through all presets. Use -Debug for full details." 440 | ForEach ($preset in $snmp_presets.presets.preset) { 441 | $NewCheck = @{} 442 | $oidValue = Invoke-SNMPget $ip $preset.oid $Community $UDPport 443 | If ("NoSuchObject","NoSuchInstance","Error" -notcontains $oidValue.Data) { 444 | If ($Name) { 445 | $Description = '{0} ({1}) - {3} {4} - {2}' -f $Name, $SNMPhost, $preset.description, $preset.vendor, $preset.product 446 | } Else { 447 | $Description = '{0} - {2} {3} - {1}' -f $SNMPhost, $preset.description, $preset.vendor, $preset.product 448 | } 449 | $oid = $preset.oid 450 | $CheckExists = $XmlConfig["247"].checks.SelectSingleNode("SnmpCheck[host=""$SNMPhost"" and oid=""$oid""]") 451 | If(!($CheckExists)) { 452 | Output-Verbose ("Valid check {0}" -f $Description) 453 | $NewCheck = @{ 454 | "checktype" = "SnmpCheck"; 455 | "checkset" = "247"; 456 | "product" = $Description; 457 | "host" = $SNMPhost; 458 | "port" = $UDPport; 459 | "community" = $Community; 460 | "oid" = $oid; 461 | "op" = $preset.op; 462 | "testvalue" = $preset.testvalue; 463 | "snmpversion" = 2 464 | } 465 | 466 | $NewChecks += $NewCheck 467 | } Else { 468 | Output-Debug ('Testing {0}' -f $Description) 469 | If ($CheckExists.product -is [System.Xml.XmlElement]) { $Checkname = $CheckExists.product.InnerText} 470 | Else { $Checkname = $CheckExists.product} 471 | Output-Verbose ("This check already exist with name '{0}'" -f $Checkname ) 472 | } 473 | } 474 | } 475 | } Catch { 476 | Output-Host ("ERROR: Script failed on item: {0}" -f $_.Exception.ItemName) 477 | Output-Host $_.Exception.Message 478 | Exit 1000 479 | } 480 | } 481 | 482 | If($NewChecks[0]) 483 | { 484 | Foreach ($Check in $NewChecks) { 485 | $xmlCheck = $XmlConfig[$Check.checkset].CreateElement($Check.checktype) 486 | $xmlCheck.SetAttribute('modified', '1') 487 | 488 | Foreach ($property in $Check.Keys) { 489 | If ("checkset", "checktype" -notcontains $property) { 490 | $xmlProperty = $XmlConfig[$Check.checkset].CreateElement($property) 491 | $propertyValue = $Check.get_Item($property) 492 | If ([bool]($propertyValue -as [int]) -or $propertyValue -eq "0") # Is this a number? 493 | { # If its a number we just dump it in there 494 | $xmlProperty.set_InnerText($propertyValue) 495 | } Else { # If it is text we encode it in CDATA 496 | $rs = $xmlProperty.AppendChild($XmlConfig[$Check.checkset].CreateCDataSection($propertyValue)) 497 | } 498 | # Add Property to Check element 499 | $rs = $xmlCheck.AppendChild($xmlProperty) 500 | } 501 | } 502 | # Add Check to file in check section 503 | $rs = $XmlConfig[$Check.checkset].checks.AppendChild($xmlCheck) 504 | 505 | } 506 | $XmlConfig[$Check.checkset].checks.SetAttribute("modified", "1") 507 | $ConfigChanged = $true 508 | 509 | If ($Apply) { 510 | 511 | # Save all config files 512 | $XmlConfig["247"].Save($XmlFile["247"]) 513 | 514 | # Check if PSScheduledJob module is available. Use delayed restart of agent if it does. 515 | Try { 516 | Output-Debug 'Trying to restart agent using PSScheduledJob' 517 | $ErrorActionPreference = 'Stop' 518 | # Restart monitoring agent with a scheduled task with 2 minutes delay. 519 | # Register a new task if it does not exist, set a new trigger if it does. 520 | Import-Module PSScheduledJob 521 | $JobTime = (Get-Date).AddMinutes(2) 522 | $JobTrigger = New-JobTrigger -Once -At $JobTime.ToShortTimeString() 523 | $JobOption = New-ScheduledJobOption -StartIfOnBattery -RunElevated 524 | $RegisteredJob = Get-ScheduledJob -Name RestartAdvancedMonitoringAgent -ErrorAction SilentlyContinue 525 | If ($RegisteredJob) { 526 | Set-ScheduledJob $RegisteredJob -Trigger $JobTrigger 527 | } Else { 528 | Register-ScheduledJob -Name RestartAdvancedMonitoringAgent -ScriptBlock { Restart-Service 'Advanced Monitoring Agent' } -Trigger $JobTrigger -ScheduledJobOption $JobOption 529 | } 530 | $RestartMethod = 'PSScheduledJob' 531 | } Catch { 532 | Output-Debug 'EXCEPTION: PSScheduledJob not available. Using Restart-Service.' 533 | # No scheduled job control available 534 | # Restart the hard way 535 | Restart-Service 'Advanced Monitoring Agent' 536 | $RestartMethod = 'Restart-Service' 537 | } Finally { 538 | $ErrorActionPreference = 'Continue' 539 | } 540 | # Write output to $LastChangeFile 541 | # Overwrite file with first command 542 | "Last Change applied {0} (Restarted using {1}):" -f $(Get-Date), $RestartMethod | Out-File $LastChangeFile 543 | "------------------------------------------------------" | Out-File -Append $LastChangeFile 544 | If ($NewChecks) { 545 | "`nAdded the following checks to configuration file:" | Out-File -Append $LastChangeFile 546 | ForEach ($Check in $NewChecks) { 547 | $Check["product"] | Out-File -Append $LastChangeFile 548 | } 549 | } 550 | 551 | If ($ReportMode) { 552 | Exit 0 # Needed changes have been reported, but do not fail the check 553 | } Else { 554 | Exit 1001 # Internal status code: Suggested changes, but nothing has been touched 555 | } 556 | } Else { 557 | Output-Host "New SNMP Checks Available:" 558 | If ($NewChecks) 559 | { 560 | ForEach ($Check in $NewChecks) { 561 | Output-Host $Check["product"] 562 | } 563 | } 564 | If (Test-Path $LastChangeFile) { 565 | # Print last change to STDOUT 566 | Output-Host "------------------------------------------------------" 567 | Get-Content $LastChangeFile 568 | Output-Host "------------------------------------------------------" 569 | } 570 | If ($ReportMode) { 571 | Exit 0 # Needed changes have been reported, but do not fail the check 572 | } Else { 573 | Exit 1001 # Internal status code: Suggested changes, but nothing has been touched 574 | } 575 | } 576 | } Else { 577 | # We have nothing to do. 578 | Output-Host "Nothing to do." 579 | If (Test-Path $LastChangeFile) { 580 | # Print last change to STDOUT 581 | Output-Host "------------------------------------------------------" 582 | Get-Content $LastChangeFile 583 | Output-Host "------------------------------------------------------" 584 | } 585 | Exit 0 # SUCCESS 586 | } 587 | -------------------------------------------------------------------------------- /SNMP/README.txt: -------------------------------------------------------------------------------- 1 | VERSION HISTORY 2 | 1.0 INITIAL RELEASE 3 | Initial release posted on LinkedIn. Last modification before release was to 4 | include native parameter validation. The $Target parameter was changed from 5 | [String] to [Array] to catch multiple targets correctly. 6 | 7 | 1.01 BUGFIX 8 | The type change in parameter $Target in previous release introduced a bug for 9 | any scenario where $Target was NOT an array. This is fixed in this release. 10 | 11 | 1.10 FEATURE 12 | The script now accepts a -Name parameter. If -Name is used the script will 13 | use this name to mark each check added with a friendly name. Target is 14 | included, too, as the script may have more than 1 target. 15 | 16 | Warning! Do NOT use a name with spaces, even if you use quotes. It will break 17 | parameter validation because of parameters passing from script to script 18 | and powershell being invoked as a command line from Windows scripting host. 19 | 20 | If -Verbose is used the script now outputs detailed information. 21 | 22 | If -Debug is used the script outputs everything to a local logfile. 23 | Logfile name is supplied by agent automatically and cannot be changed. 24 | It is located in the agent directory and is named task_XX.log whree 25 | 26 | BUGFIX 27 | By trial and error I have learnt that a MAX powershell script must ALWAYS 28 | accept positional paramerers and NEVER perform native parameter validation. 29 | A Powershell parameter error can easily be caused by task_start.js mungling 30 | your parameters. A Powershell parameter error will result in no output 31 | whatsoever (errors are written to the Error stream, not STDOUT). 32 | 33 | The script now accepts positional parameters (but do not use them) and 34 | tries to feed problems back to you as well as task_start.js permits. 35 | 36 | The script now accepts -logfile parameter explicitly. It is used if running 37 | with -Debug. When an agent runs a script it embeds it in task_start.js to 38 | capture output. It always appends a parameter -logfile. This parameter MUST 39 | be accepted by the script, or the script will fail silently (no output to 40 | Dashboard). 41 | 1.11 FEATURE 42 | Fall back to Restart-Service if Powershell version < v3 43 | 44 | 1.12 BUGFIX 45 | Not all machines with powershell version 3 has PSScheduledJob! Switched from 46 | version check to Try-Catch. 47 | -------------------------------------------------------------------------------- /SNMP/lib/SNMP-Funcs.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-SNMPget ([string]$sIP, $sOIDs, [string]$Community = "public", [int]$UDPport = 161, [int]$TimeOut=3000) { 2 | # $OIDs can be a single OID string, or an array of OID strings 3 | # $TimeOut is in msec, 0 or -1 for infinite 4 | 5 | # Create OID variable list 6 | # $vList = New-GenericObject System.Collections.Generic.List Lextm.SharpSnmpLib.Variable # PowerShell v1 and v2 7 | $vList = New-Object 'System.Collections.Generic.List[Lextm.SharpSnmpLib.Variable]' # PowerShell v3 8 | foreach ($sOID in $sOIDs) { 9 | $oid = New-Object Lextm.SharpSnmpLib.ObjectIdentifier ($sOID) 10 | $vList.Add($oid) 11 | } 12 | 13 | # Create endpoint for SNMP server 14 | $ip = [System.Net.IPAddress]::Parse($sIP) 15 | $svr = New-Object System.Net.IpEndPoint ($ip, 161) 16 | 17 | # Use SNMP v2 18 | $ver = [Lextm.SharpSnmpLib.VersionCode]::V2 19 | 20 | # Perform SNMP Get 21 | try { 22 | $msg = [Lextm.SharpSnmpLib.Messaging.Messenger]::Get($ver, $svr, $Community, $vList, $TimeOut) 23 | } catch { 24 | Write-Host "SNMP Get error: $_" 25 | Return $null 26 | } 27 | 28 | $res = @() 29 | foreach ($var in $msg) { 30 | $line = "" | Select OID, Data 31 | $line.OID = $var.Id.ToString() 32 | $line.Data = $var.Data.ToString() 33 | $res += $line 34 | } 35 | 36 | $res 37 | } 38 | 39 | function Invoke-SnmpWalk ([string]$sIP, $sOIDstart, [string]$Community = "public", [int]$UDPport = 161, [int]$TimeOut=3000) { 40 | # $sOIDstart 41 | # $TimeOut is in msec, 0 or -1 for infinite 42 | 43 | # Create OID object 44 | $oid = New-Object Lextm.SharpSnmpLib.ObjectIdentifier ($sOIDstart) 45 | 46 | # Create list for results 47 | # $results = New-GenericObject System.Collections.Generic.List Lextm.SharpSnmpLib.Variable # PowerShell v1 and v2 48 | $results = New-Object 'System.Collections.Generic.List[Lextm.SharpSnmpLib.Variable]' # PowerShell v3 49 | 50 | # Create endpoint for SNMP server 51 | $ip = [System.Net.IPAddress]::Parse($sIP) 52 | $svr = New-Object System.Net.IpEndPoint ($ip, 161) 53 | 54 | # Use SNMP v2 and walk mode WithinSubTree (as opposed to Default) 55 | $ver = [Lextm.SharpSnmpLib.VersionCode]::V2 56 | $walkMode = [Lextm.SharpSnmpLib.Messaging.WalkMode]::WithinSubtree 57 | 58 | # Perform SNMP Get 59 | try { 60 | [Lextm.SharpSnmpLib.Messaging.Messenger]::Walk($ver, $svr, $Community, $oid, $results, $TimeOut, $walkMode) 61 | } catch { 62 | Write-Host "SNMP Walk error: $_" 63 | Return $null 64 | } 65 | 66 | $res = @() 67 | foreach ($var in $results) { 68 | $line = "" | Select OID, Data 69 | $line.OID = $var.Id.ToString() 70 | $line.Data = $var.Data.ToString() 71 | $res += $line 72 | } 73 | 74 | $res 75 | } 76 | 77 | $oidValue = Invoke-SNMPget $SNMPhost 1.3.6.1.4.1.674.10893.1.20.140.1.1.4.10 -------------------------------------------------------------------------------- /SNMP/lib/SharpSnmpLib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klemmestad/PowerShell/e3345d374f200842fc17b03b6221b03647d2e285/SNMP/lib/SharpSnmpLib.dll -------------------------------------------------------------------------------- /XML/Remove-XMLDuplicates.ps1: -------------------------------------------------------------------------------- 1 | ## SETUP ENVIRONMENT 2 | # Find "Advanced Monitoring Agent" service and use path to locate files 3 | $gfimaxagent = Get-WmiObject Win32_Service | Where-Object { $_.Name -eq 'Advanced Monitoring Agent' } 4 | $gfimaxexe = $gfimaxagent.PathName 5 | $gfimaxpath = Split-Path $gfimaxagent.PathName.Replace([char]34,"") -Parent 6 | $XmlFile = $gfimaxpath + [char]92 + "247_Config_new.xml" 7 | 8 | [xml]$XmlContent = Get-Content $XmlFile 9 | $XmlPath = "checks" 10 | $Property = "uid" 11 | $XmlValues = @{} 12 | Foreach ($XmlElement in $XmlContent.$XmlPath.ChildNodes) 13 | { 14 | $ElementValues = "" 15 | Foreach($XmlValue in $XmlElement.ChildNodes | Sort-Object name) 16 | { 17 | $ElementValues = $ElementValues + $XmlValue.Name + $XmlValue.InnerText 18 | } 19 | $XmlValues[$XmlElement.$Property] = $ElementValues 20 | } 21 | 22 | $XmlDuplicates = @{} 23 | Foreach ($XmlValue in $XmlValues.Values) 24 | { 25 | $Items = @($XmlValues.Keys | Where { $XmlValues[$_] -eq $XmlValue}) 26 | If ($Items.Count -gt 1) 27 | { 28 | If (!($XmlDuplicates[$Items[0]])) { $XmlDuplicates[$Items[0]] = $Items } 29 | } 30 | 31 | } 32 | 33 | Foreach ($XmlDuplicate in $XmlDuplicates.Keys) 34 | { 35 | 36 | For ($i = 1; $i -lt $XmlDuplicates[$XmlDuplicate].Count; $i++) 37 | { 38 | $XPath = "//" + $XmlPath + "/*[@" + $Property +"=" + $XmlDuplicates[$XmlDuplicate][$i]+"]" 39 | $ChildToBeRemoved = $XmlContent.SelectSingleNode($XPath) 40 | $ChildToBeRemoved.ParentNode.RemoveChild($ChildToBeRemoved) 41 | } 42 | } 43 | 44 | $XmlContent.Save($XmlFile) 45 | -------------------------------------------------------------------------------- /klemmestad.no/Get-ValutaKurser.ps1: -------------------------------------------------------------------------------- 1 | # Velg formater 2 | $Valutakode = '' # Blank for ALLE. Eks. 'USD' for kun amerikanske dollar mot NOK 3 | $lastNObservations = 1 # Hvor mange kurser bakover i tid vil du ha data for 4 | $Skilletegn = 'semicolon' # 'comma', 'semicolon', 'tab' eller 'space' 5 | $Tidsakse = 'flat' # 'flat', 'x' eller 'y' 6 | $FulleNavn = 'false' # 'false' eller 'true'. Eks: 'false' = NOK, 'true' = Norske kroner 7 | 8 | # Sett sammen valgene til riktig URL 9 | $Uri = 'https://data.norges-bank.no/api/data/EXR/B.{0}.NOK.SP?lastNObservations={1}&format=csv-:-{2}-{3}-{4}' -F $Valutakode, $lastNObservations, $Skilletegn, $FulleNavn, $Tidsakse 10 | 11 | # Kolonnenavn 12 | $Valutakurser = "APIversjon;Frekvens;Valuta;NOK;Kurstype;Dato;Kurs;Desimaler;Ukjent;Enhet;Tidspunkt`n" 13 | 14 | # Hent CSV data og legg dem til etter kolonnenavnene + gjør om på desimalpunktum 15 | $Valutakurser += (Invoke-RestMethod -Uri $Uri -Method GET) -replace '(;\d+)\.(\d+;)', '$1,$2' 16 | 17 | $Filnavn = '{0}\Downloads\valutakurser.csv' -F $Env:USERPROFILE 18 | 19 | $Valutakurser | Set-Content -Path $Filnavn -Encoding UTF8 20 | --------------------------------------------------------------------------------