Wer zum Veeam Cloud Connect Monitoring keinen eigenen Veeam ONE Server im Einsatz hat, was nicht sehr ungewöhnlich ist, muss sich eine eigene Lösungen schaffen. In jedem Fall ist es als Veeam Service Provider notwendig die Ressourcen seiner Kunden im Auge zu behalten. Alleine schon für das Korrekte Reporting an Veeam (v9 Update 2 bietet hier allerdings enorme Verbesserungen. Siehe VCSP Forum) aber auch um frühzeitig auf Engpässe bei den Quotas reagieren zu können.
Alle nötigen Informationen für das Monitoring und Reporting der Veeam Cloud Connect Mandanten finden sich bereits im Veeam Enterprise Manager. Leider findet man diese nicht direkt in der Web Oberfläche, sondern nur per RESTful API. Die Schnittstelle ist aber sauber dokumentiert und sehr strukturiert aufgebaut (Siehe RESTful API Reference).
Somit ist es also möglich sich mit etwas PowerShell alle nötigen Informationen per EXE/Script Advanced Sensor in PRTG anzuzeigen. Damit ist ganz nebenbei auch für eine saubere Aufbewahrung der statistischen Daten gesorgt.
Welche Daten sind von Relevanz:
- Anzahl gesicherter VMs
- Konfiguriertes Backup Storage Quota
- Genutztes Backup Storage Quota
- Anzahl Replizierter VMs
- Genutzte Replika vCPUs
- Genutzter Replika Arbeitsspeicher
- Konfiguriertes Replika Storage Quota
- Genutztes Replika Storage Quota
Zusätzlich ist für das Veeam Cloud Connect Monitoring ein prozentualer Storage Quota sinnvoll, somit kann ein Alert auf diesen Wert pro Mandant gebunden werden.
So könnte der Sensor mit seinen Channels aussehen:
Die oben hervorgehobenen Channel, in meinen Augen die kritischen Werte, können zusätzlich noch mit Schwellwerten für Alerts versehen werden:
Veeam Cloud Connect Monitoring – Das Script
Bevor das PowerShell Script als Advanced Sensor in PRTG eingebunden werden kann, sind ein paar manuelle Tests sinnvoll.
Vorbereitung
Für den Zugriff auf die RESTful API ist im ersten Schritt eine Authentifizierung der Session erforderlich (Mehr Details). Hierfür ist nur „Basic Authorization“ mit einem Base64 Hash möglich (siehe auch RFC2617).
Dieses kurze Script erzeugt den Base64 Hash:
[String] $User = "DOM\User" [String] $Password = "Passw0rd!" Write-Host "Basic String: " $([Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("$($User):$($Password)")))
Test
Mit dem vorher erzeigten Base64 Hash kann nun das Script in einer beliebigen PowerShell Konsole (auch x86) aufgerufen werden.
Hier ein Beispiel des Aufrufes mit den Standard Einstellungen (https auf Port 9398):
PRTG-Veeam-CloudVMs.ps1 -Server VeeamEM.lan.local -HTTPS:$True -Port 9398 -Authentication Vk9QXHN2Yy12cm6tY2MwMTp2XltKNUNiS2dlIUp6dkQxbkdiZnky -Debug
Mit dem -Debug Schalter wird am Ende des Scripts zu besseren Kontrolle eine zusätzliche Tabelle ausgegeben:
Parameter
Alle Parameter sind in dem Script mit Default Werten hinterlegt, Server und Authentication müssen natürlich auf die Umgebung angepasst werden.
-Server
Der Veeam Enterprise Manager FQDN.
-HTTPS
$True oder $False
! Vorsicht ! Es sollte nach Möglichkeit immer eine SSL gesicherte Verbindung verwendet werden!
-Port
9398 -> https
9399 -> httpFalls nicht während dem Setup angepasst.
-Authentication
Der Base64 Hash zu Authentifizierung.
-TenantName (Optional)
Filter auf einen oder mehrere Tenants (Danke für die Idee Chris!).
PowerShell Script
<# .SYNOPSIS PRTG Veeam Cloud Connect Usage Sensor .DESCRIPTION Advanced Sensor will Report Cloud Connect Tenant Statistics .EXAMPLE PRTG-Veeam-CloudVMs.ps1 -Server VeeamEM.lan.local -HTTPS:$True -Port 9398 -Authentication <dummy> .EXAMPLE PRTG-Veeam-CloudVMs.ps1 -Server VeeamEM.lan.local -HTTPS:$False -Port 9399 -Authentication <dummy> .EXAMPLE PRTG-Veeam-CloudVMs.ps1 -Server VeeamEM.lan.local -HTTPS:$False -Port 9399 -Authentication <dummy> -TenantName "myTenant*" .EXAMPLE PRTG-Veeam-CloudVMs.ps1 -Server VeeamEM.lan.local -Authentication <dummy> -TenantName "myTenant*" -debug .Notes NAME: PRTG-Veeam-CloudVMs.ps1 LASTEDIT: 17/02/2017 VERSION: 1.5 KEYWORDS: Veeam, Cloud Connect, PRTG .Link http://mycloudrevolution.com/ #Requires PS -Version 3.0 #> [cmdletbinding()] param( [Parameter(Position=0, Mandatory=$false)] [String] $Server = "veeam01.lan.local", [Parameter(Position=1, Mandatory=$false)] [Boolean] $HTTPS = $True, [Parameter(Position=2, Mandatory=$false)] [String] $Port = "9398", [Parameter(Position=3, Mandatory=$false)] [String] $Authentication = "<dummy>", [Parameter(Position=4, Mandatory=$false)] [String] $TenantName ) #region: Workaround for SelfSigned Cert add-type @" using System.Net; using System.Security.Cryptography.X509Certificates; public class TrustAllCertsPolicy : ICertificatePolicy { public bool CheckValidationResult( ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) { return true; } } "@ [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy #endregion #region: Switch Http/s if ($HTTPS -eq $True) {$Proto = "https"} else {$Proto = "http"} #endregion #region: POST - Authorization [String] $URL = $Proto + "://" + $Server + ":" + $Port + "/api/sessionMngr/?v=v1_2" Write-Verbose "Authorization Url: $URL" $Auth = @{uri = $URL; Method = 'POST'; Headers = @{Authorization = 'Basic ' + $Authentication; } } try {$AuthXML = Invoke-WebRequest @Auth -ErrorAction Stop} catch {Write-Error "`nERROR: Authorization Failed!";Exit 1} #endregion #region: GET - Session Statistics [String] $URL = $Proto + "://" + $Server + ":" + $Port + "/api/cloud/tenants" Write-Verbose "Session Statistics Url: $URL" $Tenants = @{uri = $URL; Method = 'GET'; Headers = @{'X-RestSvcSessionId' = $AuthXML.Headers['X-RestSvcSessionId']; } } try {$TenantsXML = Invoke-RestMethod @Tenants -ErrorAction Stop} catch {Write-Error "`nERROR: Get Session Statistics Failed!";Exit 1} #endregion #region: Get Tenant Details [Array] $Hrefs = $TenantsXML.EntityReferences.Ref.Href $VCCBillings = @() for ( $i = 0; $i -lt $Hrefs.Count; $i++){ [String] $URL = $Hrefs[$i] + "?format=Entity" Write-Verbose "Tenant Detail Url: $URL" $TenantsDetails = @{uri = $URL; Method = 'GET'; Headers = @{'X-RestSvcSessionId' = $AuthXML.Headers['X-RestSvcSessionId']; } } try {$TenantsDetailsXML = Invoke-RestMethod @TenantsDetails -ErrorAction Stop} catch {Write-Error "`nERROR: Get Tenant Details Failed!";Exit 1} #endregion #region: Build Report # Customer Name [String] $CustomerName = $TenantsDetailsXML.CloudTenant.Name # Customer BaaS and DRaaS Objects [Int] $BackupCount = $TenantsDetailsXML.CloudTenant.BackupCount [Int] $ReplicaCount = $TenantsDetailsXML.CloudTenant.ReplicaCount # Customer BaaS Quotas [Array] $BackupUsedQuota = $TenantsDetailsXML.CloudTenant.Resources.CloudTenantResource.RepositoryQuota.UsedQuota [Int] $BackupUsedQuota = (($BackupUsedQuota) | Measure-Object -Sum).Sum [Array] $BackupQuota = $TenantsDetailsXML.CloudTenant.Resources.CloudTenantResource.RepositoryQuota.Quota [Int] $BackupQuota = (($BackupQuota) | Measure-Object -Sum).Sum # Customer DRaaS Quotas [Array] $ReplicaMemoryUsageMb = $TenantsDetailsXML.CloudTenant.ComputeResources.CloudTenantComputeResource.ComputeResourceStats.MemoryUsageMb if ($ReplicaMemoryUsageMb -eq $null) {$ReplicaMemoryUsageMb = 0} [Int] $ReplicaMemoryUsageMb = (($ReplicaMemoryUsageMb) | Measure-Object -Sum).Sum [Array] $ReplicaCPUCount = $TenantsDetailsXML.CloudTenant.ComputeResources.CloudTenantComputeResource.ComputeResourceStats.CPUCount if ($ReplicaCPUCount -eq $null) {$ReplicaCPUCount = 0} [Int] $ReplicaCPUCount = (($ReplicaCPUCount) | Measure-Object -Sum).Sum [Array] $ReplicaStorageUsageGb = $TenantsDetailsXML.CloudTenant.ComputeResources.CloudTenantComputeResource.ComputeResourceStats.StorageResourceStats.StorageResourceStat.StorageUsageGb if ($ReplicaStorageUsageGb -eq $null) {$ReplicaStorageUsageGb = 0} [Int] $ReplicaStorageUsageGb = (($ReplicaStorageUsageGb) | Measure-Object -Sum).Sum [Array] $ReplicaStorageLimitGb = $TenantsDetailsXML.CloudTenant.ComputeResources.CloudTenantComputeResource.ComputeResourceStats.StorageResourceStats.StorageResourceStat.StorageLimitGb if ($ReplicaStorageLimitGb -eq $null) {$ReplicaStorageLimitGb = 0; $ReplicaStorageUsedPerc = 0} [Int] $ReplicaStorageLimitGb = (($ReplicaStorageLimitGb) | Measure-Object -Sum).Sum if ($ReplicaStorageLimitGb -gt 0) { $ReplicaStorageUsedPerc = [Math]::Round(($ReplicaStorageUsageGb / $ReplicaStorageLimitGb) * 100,0) } $VCCObject = [PSCustomObject] @{ CustomerName = $CustomerName BackupCount = $BackupCount ReplicaCount = $ReplicaCount BackupQuotaGb = $BackupQuota BackupUsedQuotaGb = $BackupUsedQuota BackupQuotaUsedPerc = [Math]::Round(($BackupUsedQuota / $BackupQuota) * 100,0) ReplicaMemoryUsageMb = $ReplicaMemoryUsageMb ReplicaCPUCount = $ReplicaCPUCount ReplicaStorageLimitGb = $ReplicaStorageLimitGb ReplicaStorageUsageGb = $ReplicaStorageUsageGb ReplicaStorageUsedPerc = $ReplicaStorageUsedPerc } $VCCBillings += $VCCObject } #endregion #region: Filter Tenant Name if ($TenantName) { $VCCBillings = $VCCBillings | where {$_.CustomerName -like $TenantName} } #endregion #region: XML Output for PRTG Write-Host "<prtg>" foreach ($VCCBilling in $VCCBillings){ $BackupCount_Name = "BackupCount - " + $VCCBilling.CustomerName $BackupCount_Value = $VCCBilling.BackupCount Write-Host "<result>" "<channel>$BackupCount_Name</channel>" "<value>$BackupCount_Value</value>" "<showChart>1</showChart>" "<showTable>1</showTable>" "</result>" $ReplicaCount_Name = "ReplicaCount - " + $VCCBilling.CustomerName $ReplicaCount_Value = $VCCBilling.ReplicaCount Write-Host "<result>" "<channel>$ReplicaCount_Name</channel>" "<value>$ReplicaCount_Value</value>" "<showChart>1</showChart>" "<showTable>1</showTable>" "</result>" $BackupQuotaGb_Name = "BackupQuotaGb - " + $VCCBilling.CustomerName $BackupQuotaGb_Value = $VCCBilling.BackupQuotaGb Write-Host "<result>" "<channel>$BackupQuotaGb_Name</channel>" "<value>$BackupQuotaGb_Value</value>" "<unit>Custom</unit>" "<customUnit>GB</customUnit>" "<showChart>1</showChart>" "<showTable>1</showTable>" "</result>" $BackupUsedQuotaGb_Name = "BackupUsedQuotaGb - " + $VCCBilling.CustomerName $BackupUsedQuotaGb_Value = $VCCBilling.BackupUsedQuotaGb Write-Host "<result>" "<channel>$BackupUsedQuotaGb_Name</channel>" "<value>$BackupUsedQuotaGb_Value</value>" "<unit>Custom</unit>" "<customUnit>GB</customUnit>" "<showChart>1</showChart>" "<showTable>1</showTable>" "</result>" $BackupQuotaUsed_Name = "BackupQuotaUsed - " + $VCCBilling.CustomerName $BackupQuotaUsed_Value = $VCCBilling.BackupQuotaUsedPerc Write-Host "<result>" "<channel>$BackupQuotaUsed_Name</channel>" "<value>$BackupQuotaUsed_Value</value>" "<unit>Percent</unit>" "<mode>Absolute</mode>" "<showChart>1</showChart>" "<showTable>1</showTable>" "<LimitMaxWarning>80</LimitMaxWarning>" "<LimitMaxError>90</LimitMaxError>" "<LimitMode>1</LimitMode>" "</result>" $ReplicaMemoryUsageMb_Name = "ReplicaMemoryUsageMb - " + $VCCBilling.CustomerName $ReplicaMemoryUsageMb_Value = $VCCBilling.ReplicaMemoryUsageMb Write-Host "<result>" "<channel>$ReplicaMemoryUsageMb_Name</channel>" "<value>$ReplicaMemoryUsageMb_Value</value>" "<unit>Custom</unit>" "<customUnit>MB</customUnit>" "<showChart>1</showChart>" "<showTable>1</showTable>" "</result>" $ReplicaCPUCount_Name = "ReplicaCPUCount - " + $VCCBilling.CustomerName $ReplicaCPUCount_Value = $VCCBilling.ReplicaCPUCount Write-Host "<result>" "<channel>$ReplicaCPUCount_Name</channel>" "<value>$ReplicaCPUCount_Value</value>" "<showChart>1</showChart>" "<showTable>1</showTable>" "</result>" $ReplicaStorageLimitGb_Name = "ReplicaStorageLimitGb - " + $VCCBilling.CustomerName $ReplicaStorageLimitGb_Value = $VCCBilling.ReplicaStorageLimitGb Write-Host "<result>" "<channel>$ReplicaStorageLimitGb_Name</channel>" "<value>$ReplicaStorageLimitGb_Value</value>" "<unit>Custom</unit>" "<customUnit>GB</customUnit>" "<showChart>1</showChart>" "<showTable>1</showTable>" "</result>" $ReplicaStorageUsageGb_Name = "ReplicaStorageUsageGb - " + $VCCBilling.CustomerName $ReplicaStorageUsageGb_Value = $VCCBilling.ReplicaStorageUsageGb Write-Host "<result>" "<channel>$ReplicaStorageUsageGb_Name</channel>" "<value>$ReplicaStorageUsageGb_Value</value>" "<unit>Custom</unit>" "<customUnit>GB</customUnit>" "<showChart>1</showChart>" "<showTable>1</showTable>" "</result>" $ReplicaStorageUsed_Name = "ReplicaStorageUsed - " + $VCCBilling.CustomerName $ReplicaStorageUsed_Value = $VCCBilling.ReplicaStorageUsedPerc Write-Host "<result>" "<channel>$ReplicaStorageUsed_Name</channel>" "<value>$ReplicaStorageUsed_Value</value>" "<unit>Percent</unit>" "<mode>Absolute</mode>" "<showChart>1</showChart>" "<showTable>1</showTable>" "<LimitMaxWarning>80</LimitMaxWarning>" "<LimitMaxError>90</LimitMaxError>" "<LimitMode>1</LimitMode>" "</result>" } $BackupCount_Total = (($VCCBillings) | Measure-Object 'BackupCount' -Sum).Sum Write-Host "<result>" "<channel>BackupCount - Total</channel>" "<value>$BackupCount_Total</value>" "<showChart>1</showChart>" "<showTable>1</showTable>" "</result>" $ReplicaCount_Total = (($VCCBillings) | Measure-Object 'ReplicaCount' -Sum).Sum Write-Host "<result>" "<channel>ReplicaCount - Total</channel>" "<value>$ReplicaCount_Total</value>" "<showChart>1</showChart>" "<showTable>1</showTable>" "</result>" Write-Host "</prtg>" #endregion #region: Debug if ($DebugPreference -eq "Inquire") { $VCCBillings | ft * -Autosize } #endregion
Advanced PRTG Sensors GitHub Repository
Wegen der großen Nachfrage, habe ich nun ein GitHub Repositoy der aktuellen Skripte erstellt.
Ich freue mich über jede Teilnahme an diesem kleinen Projekt. Egal ob Pull Request, Bug Report oder Feature Request, alles ist willkommen.
Hallo Markus,
vielen Dank zunächst einmal für den Tipp der UAC. Das war der Auslöser.
Zukunftsorientiert müssen wir aber noch einmal nach einer Alternativlösung suchen.
Zu Diesem Sensor:
Den Base64 String haben wir auf dem Veeam Server erstellt und entsprechend in das Scriptm hereinkopiert, damit wir innerhalb der Windows Powershell die Anzeige herausbekommen, bevor wir in PRTG aktiv werden.
Allerdings werden wir hier durch die Fehlermeldung „Session Statistics Failed“ ausgebremst.
Veeam Umgebung ist komplett auf Standard belassen (HTTPS mit Port 9398).
Administrator bin ich mit ein und demselben Acc im Veeam B&R, sowie in der Enterprise Console.
Wenn ich im Script nach der Fehlermeldung suche, gibt es dort auch eine URL …/api/cloud/tenants Hier wird dann im Browser nach einer Authentifizierung gefragt. Dabei gebe ich hier den Benutzernamen (inkl. Passwort) ein, welches ich für meine gesamte Umgebung benutze (Erstellung d. Base64, Veeam Enterprise Manager, Windows Credentials im PRTG). Allerdings werden diese Benutzerdaten nicht angenommen. (Identity was not authenticated)
Hat dies überhaupt mit meiner Fehlermeldung etwas zu tun?
Hallo,
du hast aber Cloud Connect Tenants in einem vom Ent. Manager verwaltetem Veeam Server oder? Ich habe es leider nicht abgefangen wenn gar keine Tenants vorhanden sind…
Bis du mit der Nutzung von einem REST Client Rest wie z.B. Postman vertraut? Dann könnten wir mal in etwas genauer schauen wo das Problem liegt.
Hier würde ich mal anfangen zu suchen:
GET http://:9399/api/cloud/tenants
Eventuell macht es Sinn die Diskussion in das Veeam VCSP Forum zu verlegen:
https://forums.veeam.com/veeam-cloud-service-providers-forum-f34/veeam-cloud-connect-monitoring-and-reporting-t37091.html
My test with Veeam Backup & Replication 9.5 was successful!
If you find any issues, please let me know.
Hallo, danke – der Sensor funktioniert prinzipiell super. Aber nach ca. 1 Stunde kommt immer ein Fehler, dass die Authentifizierung fehlschlägt. Wenn man das Script einmal manuell aus der Powershell heraus ausführt geht es wieder für eine Weile. Irgendeinen Tipp? (Veeam 9.5)
Hallo Felix,
Ich verwende das Skript seit kurzem ebenfalls mit 9.5. Konnte dieses Verhalten allerdings noch nicht feststellen.
Hast du 9.5 frisch installiert oder aktualisiert?
Hallo Markus,
es wurde auf 9.5 aktualisiert. Davor war das Skript allerdings nicht im Einsatz. Nach ca. 1 Stunde liefert mir PRTG folgenden output (Sensor Log):
C:-PFAD-ZUM-SCRIPT- :
ERROR: Authorization Failed!
In Zeile:1 Zeichen:137
+ if ($PSVersionTable.PSVersion.Major -ge 5) { Import-Module
Microsoft.PowerShell. …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorExcep
tion
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorExceptio
n,veeam-cloudrep.ps1
Gehe also eher von einem Powershell-Problem aus.
Hallo,
Siehst auf dem IIS oder Eventlog des Ent. Server irgend welche Fehler? Sieht für mich nach einer abgelaufenen Session aus. Habe das aber so aber noch nicht gesehen.
Du könntest folgendes tun:
Ersetzte diese Zeile:
try {$AuthXML = Invoke-WebRequest @Auth -ErrorAction Stop} catch {Write-Error „`nERROR: Authorization Failed!“;Exit 1}
mit der
$AuthXML = Invoke-WebRequest @Auth -ErrorAction Stop
Eventuell sehen wir dann mehr.
Hallo Markus,
in den IIS Logs habe ich nichts aufregendes gefunden. Allerdings der Tip das ganze fix ausführen zu lassen hat mir folgenden Fehler gebracht:
Invoke-WebRequest : Der Antwortinhalt kann nicht analysiert werden, da das
Internet Explorer-Modul nicht verfgbar ist, oder die Konfiguration beim
ersten Start von Internet Explorer ist nicht abgeschlossen. Geben Sie den
UseBasicParsing-Parameter an, und wiederholen Sie den Vorgang.
Habe daraufhin die IE-Einstellungen zurückgesetzt und jetzt funktioniert der Sensor wieder. Mal sehen ob es so bleibt. 🙂
Ich gebe auf jeden Fall nochmal eine Rückmeldung.
Danke für Deine Bemühungen!
Sehr schön.
Ich würde zur Sicherheit noch zusätzlich den IE FirsRun Deaktivieren:
IE First-Run deaktivieren (wegen „Invoke-WebReques“ und „Invoke-RestMethod„)
[HKEY_LOCAL_MACHINESOFTWAREPoliciesMicrosoftInternet ExplorerMain]
„DisableFirstRunCustomize“=dword:00000001
Hallo,
genau nach 1 Stunde wieder das selbe Problem… 🙁
Sorry, das mit dem Registry-Eintrag habe ich erst nach meiner letzten Antwort gelesen. Habe diesen nun gesetzt und warte mal wieder eine Stunde… Update folgt. Danke! 🙂
Will den Tag nicht vor dem Abend loben, aber ich glaube ich konnte das Problem folgendermaßen lösen:
$AuthXML = Invoke-WebRequest @Auth -UseBasicParsing -ErrorAction Stop
Der Trick dürfte -UseBasicParsing sein. Hierzu aus dem MSDN:
-UseBasicParsing
Indicates that the cmdlet uses the response object for HTML content without Document Object Model (DOM) parsing.
This parameter is required when Internet Explorer is not installed on the computers, such as on a Server Core installation of a Windows Server operating system.
Warum das so ist, obwohl ein IE installiert, und auch der entsprechende Registry Key gesetzt ist, ist mir unklar. Aber so lange es so funktioniert 🙂
Danke nochmals!
Seit dem Hinzufügen von -UseBasicParsing funktioniert der Sensor einwandfrei!
Top. Danke für die Rückmeldung!
Hi Markus,
Love the scripts, you are a life saver with these things. Works perfectly every time.
I was wondering how difficult it would be for you to edit this script to only show the output of a specific tenant. While the script it awesome I would almost prefer have a separate EXE/XML sensor per tenant?
Any chance this is easy to do?
Thanks
Hi Chris,
you are welcome. Thats a great idea with the Filter!
I added another parameter to the Script:
PRTG-Veeam-CloudVMs.ps1 -Server VeeamEM.lan.local -Authentication -TenantName "myTenant*" -debug
The modified script is no yet in the master branch. Might you please test the new version and reply your findings?
Links: https://github.com/mycloudrevolution/Advanced-PRTG-Sensors/blob/CloudVMs-with-filter/Veeam/PRTG-Veeam-CloudVMs.ps1
Please note: -debug switch is only for tests without PRTG integration.
Works perfectly Markus, great work! Thanks a million.
Are you also able to possibly look at reporting on the last successful sync time?
Hello Chris,
currently I do not have a sufficient test environment to extend the Script in that way. Sorry.
Hi Markus, thanks for the script, however it works on Powershell running the suggested test phase, but in PRTG I got this error when in the custom EXE
XML: The returned XML does not match the expected schema. (code: PE233) — JSON: The returned JSON does not match the expected structure (Invalid JSON.). (code: PE231)
Any help is appreciated.
Regards
Hi Francisco,
Have you also tried the script via the exe in normal cmd shell?
Do you pass any parameters or have you modified the defaults?
BTW. Pretty cool that the script still works…
Best wishes
Markus