├── 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 |
--------------------------------------------------------------------------------