What is this?

This knowledgebase contains questions and answers about PRTG Network Monitor and network monitoring in general. You are invited to get involved by asking and answering questions!

Learn more

PRTG Network Monitor

Intuitive to Use. Easy to manage.
300.000 administrators have chosen PRTG to monitor their network. Find out how you can reduce cost, increase QoS and ease planning, as well.

Free Download

Top Tags


View all Tags

How can I monitor SCVMM hosts and VMs with PRTG?

Votes:

0

Your Vote:

Up

Down

I would like to monitor hosts and virtual machines that are managed by a Microsoft SCVMM. In previous PRTG versions, there were the sensor types SCVMM Host sensor and SCVMM Virtual Machine sensor. As announced in PRTG version 16.1.23, these sensor types are now deprecated and were removed with version 16.x.25.

Is there still a way to include SCVMM hosts and SCVMM VMs into my monitoring with PRTG?

cleanup custom-script-exe custom-sensor deprecated device-template lookups prtg remove scvmm sensor

Created on Mar 10, 2016 1:47:21 PM by  Gerald Schoch [Paessler Support]

Last change on Jul 24, 2019 7:47:20 AM by  Maike Guba [Paessler Support]



45 Replies

Accepted Answer

Votes:

0

Your Vote:

Up

Down

This article applies to PRTG Network Monitor 19 or later

Monitoring SCVMM hosts and SCVMM virtual machines

The SCVMM Host sensor and the SCVMM Virtual Machine sensor are two sensor types that we removed in the context of the PRTG Sensor Cleanup. You could use these sensors to monitor hosts and virtual machines (VM) managed by a Microsoft System Center Virtual Machine Manager (SCVMM) like Hyper-V, VMware, or XenServer hosts and VMs. As of PRTG version 16.1.23, you cannot add these sensors anymore and running SCVMM sensors were removed from PRTG with version 16.x.25.

Nevertheless, you can still continue (or start) monitoring your SCVMM. For example, you can use an EXE/Script sensor that runs an according PowerShell (ps1) script.

We provide a custom script for SCVMM monitoring for download and you can additionally use a device template to automatically add SCVMM sensors to an SCVMM device. Follow the steps below to add sensors that monitor SCVMM hosts and SCVMM virtual machines to your PRTG installation.

Using the PowerShell script, you can monitor the following values on a SCVMM host:

  • Overall State
  • Communication State
  • CPU Utilization
  • Total Memory
  • Available Memory
  • Cluster Node Status
  • Virtual Server State
  • Computer State
  • Host Cluster

For an SCVMM virtual machine, the custom sensor can show the following values:

  • Status
  • CPU Usage
  • PerfDiskBytesRead
  • PerfDiskBytesWrite

Requirements

To use the custom sensors for SCVMM monitoring, you need to fulfill the following requirements. These are the same as for the SCVMM sensors that were available in previous PRTG versions:

  • PowerShell 4.0 installed on the computer running the PRTG probe (locally or on the remote probe system)
  • .NET 4.0 installed on the computer running the PRTG probe
  • Windows credentials in the settings of the device that represents your SCVMM
  • Remote PowerShell 2.0 enabled on the target SCVMM device
  • VMM PowerShell Plugin installed on the target SCVMM device (under Windows 2008/2012, it is part of the VMM 2008/2012 Administrator Console)
  • Windows Management Framework 1.0 or later installed on the computer running the PRTG probe (because the included System.Management.Automation namespace is required by the SCVMM sensors)
  • Requirements for Windows Server 2012 compatibility:
    • The SCVMM PowerShell module has to be in the directory C:\Program Files\Microsoft System Center 2012\Virtual Machine Manager\bin\psModules\virtualmachinemanager\virtualmachinemanager
    • Set the execution policy in PowerShell to allow the execution of Import-Module C:\Program Files\Microsoft System Center 2012\Virtual Machine Manager\bin\psModules\virtualmachinemanager\virtualmachinemanager Use the command Set-ExecutionPolicy (we recommend RemoteSigned).

For more information, see Where can I find more information about PowerShell sensors?

Steps to take

  1. Download the SCVMM sensor package that contains the PowerShell script, the device template, and the lookup files: PRTG-SCVMM-HyperV.zip
    Use the updated script located at GitHub.
  2. Unzip and save the script PRTG-SCVMM-HyperV.ps1 to the \Custom Sensors\EXE subfolder of your PRTG program directory on the system with the probe from which you want to monitor your SCVMMs.
  3. Open a PowerShell (32-bit) with admin privileges on this system and execute the following command (and confirm it):
    Set-ExecutionPolicy RemoteSigned
    • Note: Executing the PowerShell script with PowerShell (x86) will not work with the script. The sensor message is UnauthorizedAccess when trying a 64-bit PowerShell.
  4. Unzip and save the following lookup files to the \lookups\custom subfolder of your PRTG program directory on the PRTG server.
    Note: This step is not necessary if you updated from a PRTG version previous to 16.1.23.
    • prtg.standardlookups.hyperv.clusternodestatus.ovl
    • prtg.standardlookups.hyperv.communicationstate.ovl
    • prtg.standardlookups.hyperv.computerstate.ovl
    • prtg.standardlookups.hyperv.hoststatus.ovl
    • prtg.standardlookups.hyperv.virtualserverstate.ovl
    • prtg.standardlookups.hyperv.vmstatus.ovl
  5. Add a device to PRTG that represents your SCVMM.
  6. Provide your Credentials for Windows Systems if the inherited credentials are not sufficient for the SCVMM.
  7. Add a new HTTP Push Data sensor or HTTP Push Data Advanced sensor to the device, name it any way you like (for example, Template Sensor), and pause it. Write down its sensor ID.
  8. Create a new EXE/Script sensor and select the PRTG-SCVMM-HyperV.ps1 script.
  9. Set the timeout to 900 seconds.
  10. Enter the corresponding parameters. These are explained in the table below.
  11. Click Continue.

When you directly enter the data in the script, you can also test it on the fly. Initially, it will look like the attached screenshot #1, consequential runs will look like #2. Note that the sensors may not get any data immediately after the first run. This is because the sensors' startup will take some time and the script may push values prior to that.

Detailed output of the sensor when it is initially executed adding new hosts or VMs:

SCVMM Sensor in the console
Click to enlarge.

Detailed output of the sensor when executed with an existing GUID file:

SCVMM Sensor in the console
Click to enlarge.

Custom SCVMM sensor monitoring a virtual machine:

SCVMM VM Sensor
Click to enlarge.

Parameters

ParameterDescription
prtgHostNameThe URL of your PRTG web interface, for example, http://prtg.acme.com or https://prtg.acme.com
prtgPortThe port used by your PRTG web interface, for example, 80 or 443
prtgUserNameA user with read/write permissions for the device or a PRTG administrator
prtgPassHashThe passhash of the above user
prtgPushPortThe push port you configured in the template
prtgScvmmDeviceIdThe ID of the device that resembles your SCVMM server:
Recommended value is %deviceid
prtgTemplateSensorThe ID of the HTTP Push Data template sensor or the HTTP Push Data Advanced template sensor(not the sensor token, but the PRTG ID)
UserdomainThe domain of the user that will be used for Remote PowerShell access:
Recommended value is %windowsdomain
UsernameThe username that will be used for Remote PowerShell access:
Recommended value is %windowsuser
PasswordThe password of the user that will be used for Remote PowerShell access:
Recommended value is %windowspassword
VerboseWhen this is set, there will be debug messages as script output. This can always be enabled as it does not bother PRTG.

Version history

VersionRelease Notes
1.3[Changed] Switch to a HTTP Push sensor-based system. No device templates are needed. This is better for large environments.
[Notes]
The sensor is a simple EXE/Script sensor now, no longer an EXE/Script Advanced sensor.
Device templates are no longer needed, as the sensor automatically creates new sensors for new hosts and VMs with each run. With every run, we only run Get-VMHost and Get-VM once on the SCVMM host, receiving all objects at once, not once for every VM. A GUID file is maintained for every SCVMM host that will prevent sensor duplicates. Performance-wise, this is a lot easier and faster. Three VMs and one host take 2 seconds to scan. There is even more detailed script output to see what the script actually does, receives and evaluates.
1.21[Changed] The device template now has a timeout of 5 minutes for large environments.
[Changed] The default VMsensor scanning interval is set to 10 minutes (since there are 10-minute averages).
1.2[Improved] Naming conventions of the sensor
[Fixed] Auto-discovery is now working with the stable version.
1.1[Improved] Documentation
[Fixed] Values were not correctly retrieved when multiple VMs were present.
[Fixed] Values were not correctly retrieved because of a lookup bug.
1.0Initial Release

Flow chart

Credits

Special thanks to Richard Garner, computerservicecentre.com, for going through countless tests and bugfixing with me and giving ideas for improvement.

Note

Attention This will not work if your PRTG server uses HTTPS with an unsigned SSL certificate because of PowerShell being picky and only accepting signed certificates.

Alterations

Created on Mar 10, 2016 2:07:11 PM by  Gerald Schoch [Paessler Support]

Last change on Mar 17, 2021 9:21:27 AM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

How do we get this to work on Server 2012 R2 SCVMM?

I've installed a remote probe on my SCVMM box and tell it to use the custom discovery like the guide above says. Finds 0.

When I try to run the PRTG-SCVMM-HyperV.ps1 from the machine with the probe I get (regardless of PowerShell running as Administrator or not):

**[NAME.DOMAIN.COM] Connecting to remote server NAME.DOMAIN.COM failed with the following error message : Access is denied. For more information, see the about_Remote_Troubleshooting Help topic.
    + CategoryInfo          : OpenError: (NAME.DOMAIN.COM:String) [], PSRemotingTransportException
    + FullyQualifiedErrorId : AccessDenied,PSSessionStateBroken**

If I run the PS1 from my PRTG server to the SCVMM server NAME.DOMAIN.COM it works. I get a list of HyperVs back.

It looks like as long as I'm not localhost the PS1 file will work.

How can I make this work in PRTG?

Created on Sep 14, 2016 2:10:33 AM by  jw2k13 (0)

Last change on Sep 14, 2016 6:05:55 AM by  Luciano Lingnau [Paessler]



Votes:

0

Your Vote:

Up

Down

This is probably due to remote powershell not being properly enabled. Please check this for further instructions. Make sure to download the latest version of the sensor from the initial reply as I posted a new version :)

Created on Sep 14, 2016 2:00:27 PM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

Hi Team,

The sensor is succesfully seeing my SCVMM, however i am getting this error when running the script

3/07/2017 12:16:40 AM]      error      Could not create sensor for SYDAWSDC01.
[3/07/2017 12:16:40 AM]   information   Starting sensor creation for AWSMELDC01 (GUID: 70d40a8d-4dd4-476d-9b50-e9c6783f5be3)
[3/07/2017 12:16:40 AM]      error      Could not create sensor for AWSMELDC01.
[3/07/2017 12:16:40 AM]   information   Starting sensor creation for MMOSRVAPP02 (GUID: 6a812734-e453-4c7f-9c0e-ea37b5dd23c7)
[3/07/2017 12:16:40 AM]      error      Could not create sensor for MMOSRVAPP02.
[3/07/2017 12:16:40 AM]   information   Starting sensor creation for SYDSRVHUB01 (GUID: 64c9431b-a628-4afc-be0a-ead1b10fad21)
[3/07/2017 12:16:40 AM]      error      Could not create sensor for SYDSRVHUB01.
[3/07/2017 12:16:40 AM]   information   Starting sensor creation for MRN-CAS2 (GUID: cb3f169a-383a-4a06-ba54-ec283343d1fa)
[3/07/2017 12:16:40 AM]      error      Could not create sensor for MRN-CAS2.
[3/07/2017 12:16:40 AM]   information   Starting sensor creation for GuestWifiTestVM (GUID: 7d65b3ac-7108-491a-91ab-f2f30fd91a91)
[3/07/2017 12:16:40 AM]      error      Could not create sensor for GuestWifiTestVM.
[3/07/2017 12:16:40 AM]   information   Starting sensor creation for Boot (GUID: 5856c590-6cf1-4afc-9750-facb68271205)
[3/07/2017 12:16:40 AM]      error      Could not create sensor for Boot.
[3/07/2017 12:16:40 AM]   information   Starting sensor creation for AUSSRVMON01 (GUID: fbf1e27f-fbd5-4b17-bc62-fbd724622360)
[3/07/2017 12:16:40 AM]      error      Could not create sensor for AUSSRVMON01.
[3/07/2017 12:16:40 AM]   information   Starting sensor creation for MELSRVDC01 (GUID: caa3b009-3451-43f1-8420-fcdc60c0bcf9)
[3/07/2017 12:16:40 AM]      error      Could not create sensor for MELSRVDC01.
[3/07/2017 12:16:40 AM]   information   Starting sensor creation for AWSSRVAPP01 (GUID: 574d52cd-3c89-4f4b-b339-fff0e8fe8118)
[3/07/2017 12:16:40 AM]      error      Could not create sensor for AWSSRVAPP01.
[3/07/2017 12:16:40 AM]   information   0 new Virtual Machines have been added to PRTG.
[3/07/2017 12:18:20 AM]      error      Couldn't push the data to the configured PRTG server using the specified token (57be3832-f68c-478d-888f-162b2f546c03).
[3/07/2017 12:20:00 AM]      error      Couldn't push the data to the configured PRTG server using the specified token (84e73668-f434-4930-8481-5664321f6220).
[3/07/2017 12:20:02 AM]      error      Couldn't push the data to the configured PRTG server using the specified token (da74ed95-0c77-4081-9461-86bef65dbf2e).
[3/07/2017 12:20:03 AM]      error      Couldn't push the data to the configured PRTG server using the specified token (e81b1ddd-3b73-4284-aaa4-c2341d2423d1).
[3/07/2017 12:20:04 AM]      error      Couldn't push the data to the configured PRTG server using the specified token (f47a588e-e547-4728-99bc-d7b22b4bd280).
[3/07/2017 12:20:05 AM]      error      Couldn't push the data to the configured PRTG server using the specified token (bd83524c-e46f-45f2-807c-0fa2147d6f90).
[3/07/2017 12:20:06 AM]      error      Couldn't push the data to the configured PRTG server using the specified token (df53ed60-4561-432f-827c-53273045b3ef).
[3/07/2017 12:20:07 AM]      error      Couldn't push the data to the configured PRTG server using the specified token (c314a559-7d30-47b2-bcdb-9249fa7877a5).
[3/07/2017 12:20:08 AM]      error      Couldn't push the data to the configured PRTG server using the specified token (0ac01dca-ebcd-40a0-a53e-a335f5a7c75e).
[3/07/2017 12:20:18 AM]      error      Couldn't push the data to the configured PRTG server using the specified token (dcff2afb-fbea-4ead-b6bb-04951f111e0d).
[3/07/2017 12:20:19 AM]      error      Couldn't push the data to the configured PRTG server using the specified token (b3aedd08-81a9-4a16-a1d8-0509d717114a).
[3/07/2017 12:20:20 AM]      error      Couldn't push the data to the configured PRTG server using the specified token (43708edf-6b88-4090-80ff-0a263c1e97b5).
[3/07/2017 12:20:21 AM]      error      Couldn't push the data to the configured PRTG server using the specified token (2c286efa-c241-4db3-a1da-0cd0d22891d2).
[3/07/2017 12:20:22 AM]      error      Couldn't push the data to the configured PRTG server using the specified token (73eefe2d-8bbc-4689-9f33-0cf4db718913).
[3/07/2017 12:20:23 AM]      error      Couldn't push the data to the configured PRTG server using the specified token (dabe90f5-4c55-40c6-b052-11e363cdac3c).
[3/07/2017 12:20:24 AM]      error      Couldn't push the data to the configured PRTG server using the specified token (13b00809-d765-4252-a41e-153dfd857b1e).

I am running SCVMM 2016, however looks more like an issue getting the data into PRTG.

Any ideas or tips would be great.

Cheers Matt

Created on Jul 2, 2017 2:21:41 PM by  MacquarieMedia (0)

Last change on Jul 3, 2017 5:01:15 AM by  Sven Roggenhofer [Paessler Technical Support]



Votes:

0

Your Vote:

Up

Down

Dear MacquarieMedia

Did you manually create the HTTP Push Data Advanced sensor before you ran the script?

Created on Jul 3, 2017 2:01:31 PM by  Arne Seifert [Paessler Support]



Votes:

0

Your Vote:

Up

Down

This seems overly complicated. PRTG has always allowed me to quickly monitor simple and complicated things in an "easier to setup" way then other monitoring applications. This is why I recommend PRTG to other users. But this is not simple.

The instructions could use some more detailed, "example based" instructions for setting up the parameters for the script. This custom sensor should be reworked so that is select-able with the parameters in the web gui vs doing it this way. This would mimic the previous sensor, but require the powershell modules. I recognize that VMWare is probably easier to monitor. Sensors for HyperV and System Center Virtual Machine Manager should be something that PRTG makes easier to setup and monitor then the other monitoring companies.

Thanks for a great product and for listening. DB

Created on Jul 5, 2017 6:34:38 PM by  davbujn17 (0)



Votes:

0

Your Vote:

Up

Down

Dear davbujn17

Yes, this custom sensor solution is rather complicated. But custom sensors cannot be made select-able in the web gui. We don't want to re-add this sensor to the web gui as we deprecated it just last years because of its little overall usage.

It surely appears counter-intuitive how we make the software better if we remove existing features. The idea is two-fold: One, we keep PRTG simple. Second, we reduce the source code, making it easier to rework and easier for new developers to get into it. That means, that we try to not implement little-used features in the first place, and last year we even removed existing, but little-used sensors.

While SCVMM monitoring is now admittedly more complex, we used our development resources to make other things better.

Created on Jul 6, 2017 1:03:03 PM by  Arne Seifert [Paessler Support]



Votes:

0

Your Vote:

Up

Down

We've got more than 8000 VM's in Hyper-V and I'm very pro-PRTG, so I've tried to sell PRTG in our organization. Because of this issue they've decided to not buy the unlimited license.

Created on Jul 24, 2018 9:59:37 AM by  Hermanbrood26 (0)



Votes:

0

Your Vote:

Up

Down

While the script was tested with around 300 VMs, this surely is over the top and we cannot test this with such large environments :( It's rather possible that the script will take a loooong time to retrieve the host servers and virtual machines, running into Windows' 20 minute child process timeout rather than working correctly.

For environments that large, you're probably better off with Microsoft SCOM :)


Kind regards,
Stephan Linke, Tech Support Team

Created on Jul 24, 2018 11:36:19 AM by  Stephan Linke [Paessler Support]

Last change on Jul 24, 2018 11:40:25 AM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

Hello Stephan,

We've got an environment with more than 8000 vm's. We're currently monitoring using PRTG the yper-V hosts only. We would like to buy the unlimited sensor suite of PRTG, but only if PRTG can measure VM's in Hyper-V cluster aware, and directly on the Hyper-V node without SCVMM.

Are you basically saying that PRTG is not a good product for our sizing when it comes to live migrating VM's in Hyper-V?

Created on Jan 21, 2019 1:41:50 PM by  Hermanbrood26 (0)



Votes:

0

Your Vote:

Up

Down

In that case, I'd recommend against it, yes. The HTTP Push Sensors used in this approach are putting less strain on either system (target host and PRTG). It's unfortunately a chicken and the egg case. We can't monitor moving VMs moving on HyperV clusters; even if we could, it would be 8,000 WMI queries against the systems. The script approach above is querying Hyper-V directly, querying all VMs and hosts at once. However, it has not been tested with that amount of VMs - the most we had were about 400, and it took quite a bit to get the values (took about 2-3 minutes to get them).


PRTG Scheduler | PRTGapi | Feature Requests | WMI Issues | SNMP Issues

Kind regards,
Stephan Linke, Tech Support Team

Created on Jan 21, 2019 7:10:40 PM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

Hi. I'm trying to set up this custom sensor to monitor two SCVMM machines, one SCVMM 2012r2 and one SCVMM 2016. I don't why, but i cannot seem to get the parameters correct on the sensor settings.

I feel like i have tried all possible combinations to get it to work. Can anyone please give me an example on the correct syntax to use for the parameters when creating the sensor?

Created on Feb 25, 2019 4:00:57 PM by  roever (0)



Votes:

0

Your Vote:

Up

Down

Sorry that this took a while, as I was on vacation :( What does your log look like and what parameters do you use, exactly? Did you create the SCVMM device on a remote probe by any chance?

Created on Mar 11, 2019 7:26:17 AM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

Hi Stephan. I have been on vacation also, so no worries there. :)

What logs would you like? Can i PM them in some way? The parameters i entered are anonymized but here is the exact string entered on the parameters field on the sensor settings.

-prtgHostName=https://fqdn.prtgserver.com -prtgPort=443 [email protected] -prtgPassHash=********** -prtgPushPort=5050 -prtgScvmmDeviceId=%deviceid -prtgTemplateSensor=7284 -Userdomain=%windowsdomain -Username=%windowsuser -Password=%windowspassword -Verbose=$true

Right now the sensor says "Monitoring 0 objects. Last scan took 0 seconds and added 0 objects."

The device is created on a probe yes. I have installed the hyper-v script package on both the probe and the main PRTG server.

Created on Mar 21, 2019 12:12:32 PM by  roever (0)

Last change on Mar 21, 2019 6:57:10 PM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

Oh well - nice! :) If it's one a probe, please use this version instead:
https://gist.github.com/stephanlinke/3cf39a40dea862171e383fc9553899b1

It has an additional parameter -prtgProbeAddress, allowing you to pass the FQDN/IP of the Remote Probe. It should work with that one. Otherwise, execute the script on the PowerShell command line with the same parameters, including -Verbose (=$true is not necessary, as it's a switch) and post it here with !NO PUBLISH. Then I can check it without others seeing it :)


PRTGapi | Feature Requests | WMI Issues | SNMP Issues

Kind regards,
Stephan Linke, Tech Support Team

Created on Mar 21, 2019 7:00:15 PM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

Is Remote PowerShell enabled on the SCVMM Server, as disclosed on HowToGeek? The script complains that it cannot connect to the target host :)


PRTGapi | Feature Requests | WMI Issues | SNMP Issues

Kind regards,
Stephan Linke, Tech Support Team

Created on Mar 22, 2019 2:35:31 PM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

Issue remains that the script cannot connect to the target host :( Try the domain without .local in the userdomain instead.


PRTGapi | Feature Requests | WMI Issues | SNMP Issues

Kind regards,
Stephan Linke, Tech Support Team

Created on Mar 25, 2019 7:24:01 AM by  Stephan Linke [Paessler Support]

Last change on Mar 25, 2019 7:24:11 AM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

Sorry, no luck there. Still unable to connect. I have also tried to use the FQDN for bbvmm.

Created on Mar 25, 2019 12:50:36 PM by  roever (0)



Votes:

0

Your Vote:

Up

Down

Executing Get-Command -Module hyper-v | Out-GridView on the target host will give you a comprehensive list of installed Hyper-V modules. Get-VMHost and Get-VM should be included there. Is that the case?


PRTGapi | Feature Requests | WMI Issues | SNMP Issues

Kind regards,
Stephan Linke, Tech Support Team

Created on Mar 26, 2019 1:31:26 PM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

Hi. Sorry for the late answer. Yes. Get-VM and Get-VMHost is in the list on all hosts. I also checked our SCVMM servers. Both have the Powershell modules for Hyper-V management. Still not getting anything.

Created on Apr 15, 2019 6:23:55 AM by  roever (0)



Votes:

0

Your Vote:

Up

Down

I'll drop you a mail later as this is seemingly something different I'm not seeing yet. I'll be in touch.


PRTGapi | Feature Requests | WMI Issues | SNMP Issues

Kind regards,
Stephan Linke, Tech Support Team

Created on Apr 15, 2019 10:04:18 AM by  Stephan Linke [Paessler Support]



Votes:

1

Your Vote:

Up

Down

I've made a small modification to this script as my SC-VMM also has ESXi hosts in there as we're using the SCVMM tools to migrate away from VMware. I don't want PRTG to be monitoring ESX hosts and vSphere clusters via SCVMM so I've changed lines 423 and 424 from

$hosts = (Get-VMHost); $vms = (Get-VM);

to

$hosts = (Get-VMHost | Where-Object {$_.OperatingSystem -match "Windows"}); $vms = (Get-VM | Where-Object {$_.VirtualizationPlatform -match "HyperV"});

That way, it only returns Hyper-V hosts and VMs.

Created on Apr 24, 2019 10:09:47 AM by  norphus (30) 1



Votes:

0

Your Vote:

Up

Down

Nice one! :)


PRTG Scheduler | PRTGapi | Feature Requests | WMI Issues | SNMP Issues

Kind regards,
Stephan Linke, Tech Support Team

Created on Apr 24, 2019 10:22:52 AM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

Hello Team,

I have created the sensor for the VM monitoring as described in the manual. Unfortunately, the VMs are created twice and in -guidfile.dat no entry is made.

How can I solve this problem?

Best Regards Nils

Created on May 23, 2019 6:41:03 AM by  spyware (0)



Votes:

0

Your Vote:

Up

Down

This likely means that the script can't connect to your SCVMM host and read the hosts/VMs. What's the output of the script when running the script within ISE, configuring the parameters directly in the script?

Created on May 23, 2019 6:50:12 AM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

The script says that no connection can be made. But in PRTG, VM sensors are created. Unfortunately, I do not have all access data and permissions for the SCVMM server, these are only stored in PRTG. Is it possible to display the output of the script via PRTG?

Created on May 23, 2019 7:13:24 AM by  spyware (0)



Votes:

0

Your Vote:

Up

Down

Are you using these Sensors on a Remote Probe by any chance?


PRTGapi | Feature Requests | WMI Issues | SNMP Issues

Kind regards,
Stephan Linke, Tech Support Team

Created on May 23, 2019 8:21:21 AM by  Stephan Linke [Paessler Support]

Last change on May 23, 2019 8:21:26 AM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

No, i use the sensors on the local probe under the SCVMM device

Created on May 23, 2019 8:44:27 AM by  spyware (0)



Votes:

0

Your Vote:

Up

Down

Strange. Could you check if it makes a difference when disabling the IE first run wizard on a system level, according to https://stackoverflow.com/a/43496639 - simply create the registry entry and let the script run again. Do you get the same error?


PRTGapi | Feature Requests | WMI Issues | SNMP Issues

Kind regards,
Stephan Linke, Tech Support Team

Created on May 23, 2019 12:54:36 PM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

Hi Stephan,

The registry entry has brought no change. I have run the script once with the correct access data directly on the core sample. There were three error messages. The VMs were successfully read and created in PRTG as a sensor, but these sensors do not provide any values. In addition, duplicate sensors with the same GuID will continue to be created

Method invocation failed because [System.Diagnostics.Stopwatch] does not contain a method named 'new'.
At C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXE\PRTG-SCVMM-HyperV.ps1:126 char:1
+ $Stopwatch = [system.diagnostics.stopwatch]::new()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound
 


You cannot call a method on a null-valued expression.
At C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXE\PRTG-SCVMM-HyperV.ps1:530 char:1
+ $Stopwatch.Start();
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull



You cannot call a method on a null-valued expression.
At C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXE\PRTG-SCVMM-HyperV.ps1:531 char:23
+ This-GetSCVMMObjects; $Stopwatch.Stop();
+                       ~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

Created on May 28, 2019 11:39:25 AM by  spyware (0)

Last change on May 31, 2019 6:03:28 AM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

Are the latest PowerShell version (5.1) and .NET installed on the PRTG Server? Please also try the updated script version available at github. Thanks!

Created on May 31, 2019 6:04:03 AM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

Today i begun to configure the scvmm monitoring, but it seems that i stuck in problems. If i try to test the script manually, i will get following message:

PS C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXE> .\PRTG-SCVMM-HyperV.ps1 -prtgHostName=https://server.ddcmgm.local -prtgPushPort=443 [email protected] -prtgPassHash=*** -prtgPushPort=5050 -prtgTemplateSensor=5173 -prtgScvmmDeviceID=5170 -Userdomain=%windowsdomain -Username=%windowsuser -Password=%windowspassword -Verbose=$true
[29.12.2020 15:04:01]   information   GUID file path: C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXE\-guidfile.dat
[29.12.2020 15:04:01]   information   Retrieving HyperV hosts and VMs...
[29.12.2020 15:04:01]      error      Couldn't connect to the server or execute the given commands. Please check if WinRM is enabled and allowed.
Cannot index into a null array.
At C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXE\PRTG-SCVMM-HyperV.ps1:483 char:5
+     $VMHosts   = $objects[0];
+     ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

Cannot index into a null array.
At C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXE\PRTG-SCVMM-HyperV.ps1:484 char:5
+     $VMs       = $objects[1];
+     ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

[29.12.2020 15:04:01]     success     0 HyperV hosts have been found.
[29.12.2020 15:04:01]     success     0 Virtual Machines have been found.
[29.12.2020 15:04:01]   information   0 new HyperV Hosts have been added to PRTG.
[29.12.2020 15:04:01]   information   0 new Virtual Machines have been added to PRTG.
[29.12.2020 15:04:01]   information   Elapsed Time: 00:00:00.2575762
0:Monitoring 0 objects. Last scan took 0 seconds and added 0 objects.
PS C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXE> Enter-PSSession -ComputerName ddcmgmscvmm10.ddcmgm.local
[ddcmgmscvmm10.ddcmgm.local]: PS C:\Users\svc.scvmm\Documents>

As you see - we can connect over powershell to the remote system.

What is the problem here? How can we get this sensors up and working?

Created on Dec 29, 2020 2:08:24 PM by  UweKnoepfle (0)

Last change on Dec 30, 2020 8:10:57 AM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

I assume that you actually used credentials instead of the % placeholders and are using single quotes to surround them? Is the account you're using a member of the Hyper-V administrators?

Created on Dec 30, 2020 8:12:23 AM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

I assume that you actually used credentials instead of the % placeholders and are using single quotes to surround them? Is the account you're using a member of the Hyper-V administrators?

Created on Dec 30, 2020 8:12:29 AM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

I am having an issue when the scvmm sensor is on a remote probe. I have entered the $prtgProbeAddress to the script on the remote probe but I receive this error when the script runs on the remote probe, "Couldn't push the data to the configured PRTG server using the specified token".

It seems roever above had the same issue but I do not see any resolution to his/her issue.

Created on Feb 15, 2021 3:04:39 PM by  jciarlette (0) 1



Votes:

0

Your Vote:

Up

Down

Is the URL to the Sensor (to where the script is pushing the data) actually opening with a browser on the probe? The script uses Invoke-WebRequest, which may be stopped by the First Run Wizard. Once disabled, it may already work :)

Created on Feb 17, 2021 6:29:56 AM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

I've made a couple more modifications to this script which help me a little.

The first is with the display names of the sensors. When the script creates its sensors, it just names it after the VM which is great but when you have hundreds of VMs spread across multiple clusters, it makes it a little hard to keep track of what is where. Naming conventions are all very well and good, but aren't always followed. So therefore I've changed line 348 from

if(This-AddHTTPPushSensors -sensorName $object.name -Token $object.id)

to

if(This-AddHTTPPushSensors -sensorName $(if ($object.ObjectType -eq "VM") {"$($(Get-Cluster -Name $object.VMHost).name) - $($object.name)"} else {$object.name}) -Token $object.id)

That gets the name of the cluster that the host node is a member of and uses it as a prefix to the sensor name. The sensors now display the name of the cluster, followed by the name of the VM.

I've also added a metric to be measured to the VM sensor, I've added a line at line 523ish which says:

"Memory Available" = @($VM.MemoryAvailablePercentage,"Percent",0,0,0,0);

I like this script, and I can see myself adapting it for use for other things outside of SCVMM.

Created on Mar 2, 2021 5:34:23 PM by  norphus (30) 1



Votes:

0

Your Vote:

Up

Down

Cool update! Indeed, better naming conventions are crucial for large environments. I'll add your post to the first one if anybody else needs it and doesn't want to dig the whole thread :)

Created on Mar 5, 2021 8:17:58 AM by  Stephan Linke [Paessler Support]



Votes:

1

Your Vote:

Up

Down

Looking further at this script, it has occurred to me that there is something missing which I think might be useful:

The script uses the GUID file to check that a sensor already exists, and skips the creation process if it does. What it doesn't do is check to see if the VM exists in SCVMM; if a VM is deleted from SCVMM, it's still showing as healthy in PRTG which could be a problem if a VM is accidentally or maliciously deleted. Even from a sensor cleanup point of view, I think it would be useful as it would remind the PRTG admin to remove the unneeded sensor.

I think I have an idea of how to implement this but it's clear that your PowerShell-Fu is considerably more powerful than mine so could you consider this a feature request?

Created on Mar 15, 2021 10:17:49 AM by  norphus (30) 1



Votes:

0

Your Vote:

Up

Down

Saying that, this seems to work:

function This-CheckVMExists {
    #Get content of GUID file
    $objects = Get-Content $guidFile | Where-Object {$_.trim() -ne ""}
    $VMs = (Invoke-Command -ComputerName $computername -ScriptBlock { 
        $VirtualMachines = Get-SCVirtualMachine | Select Name, id
        return $VirtualMachines
    
    
    } -Credential (This-GenerateCredential))
    
    Write-Host($VMs.id.guid)

    foreach ($object in $objects) {
        Console-ShowMessage "Information" "Checking for database with GUID $($object)"
        
                      
        if ($VMs.Id.guid -match $object ) {
            #This VM exists, no need for further processing
            Console-ShowMessage "Information" "This VM Does Exist, resolving name as $($($VMs | Where-Object {$_.Id -eq $object}).name)"
            } 
            
        else {
            Console-ShowMessage "Information" "This VM Doesn't Exist, sending error to PRTG"
            #This VM doesn't exist, flag as error
            $metrics = @{
                    "State"                = @("VMStateMissing","Custom","prtg.standardlookups.hyperv.hoststatus",1,"<NotifyChanged>");
                    }

             # first, we'll format the data and sanatize the metrics
             
             $channels = (This-PrtgXmlWrapper -Metrics $metrics);

             # ...then we'll push it to PRTG. Don't forget to join the array!
             This-PushData -token $object -data $channels;
             }
        }
    }

then at the bottom of the script, add

This-CheckVMExists

some place after

This-GetSCVMMObjects;

Created on Mar 15, 2021 2:27:44 PM by  norphus (30) 1

Last change on Mar 15, 2021 3:57:32 PM by  Felix Wiesneth [Paessler Support]



Votes:

0

Your Vote:

Up

Down

Cool, thanks @norphus! Could you post the entire thing so I could link it in the first post as a variant of the script? :)

Created on Mar 16, 2021 6:13:54 AM by  Stephan Linke [Paessler Support]



Votes:

1

Your Vote:

Up

Down

Sure. It's based on v1.3 of your script because I didn't notice that you've got a newer version until just now. Anyway...

#requires -version 4.0
# ___ ___ _____ ___
#| _ \ _ \_   _/ __|
#|  _/   / | || (_ |
#|_| |_|_\ |_| \___|
# SCVMM & HyperV-VM Sensors
# ================================
# This sensor will monitor HyperV hosts and their virtual machines using SCVMM.
# It also supports metascan (https://kb.paessler.com/en/topic/68109), so you don't have
# to do all the configuration work. Note that this will only work in an upcoming stable release
#
# Version History
# ----------------------------
# 1.3        [Changed] Switched to HTTP Push Sensor based system. No device templates needed, better for large environments.
#            [Notes  ] It's an simple EXE/Script sensor now, no longer EXE/Script Advanced.
#                      Device templates are no longer needed, as the sensor automatically creates new sensors for new hosts and VMs with each run
#                      With every run, we only run Get-VMHost and Get-VM once on the SCVMM host, receiving all objects at once, not once for every VM
#                      A GUID file is maintained for every SCVMM host that will prevent sensor duplicates
#                      Performance wise, it should be way easier and faster. Three VMs and one host take 2s to scan.
#                      Better, more verbose script output to see what the script actually does, receives and evaluates.
# 1.2        [Changed] Updated device template, changed naming template of VM sensors
# 1.13       [Fixed] Paramter was wrongly passed to Get-VMHost and Get-VM
# 1.12       [Fixed] Values weren't retrieved correctly when multiple VMs were present.
# 1.1        [Fixed] Values weren't retrieved correctly due to lookup bug
# 1.0        Initial Release
#
# Credits
# ----------------------------
# RICHARD GARNER, computerservicecentre.com
# For going through countless tests and bugfixing with me. And improvement ideas - Thanks! :)
# # # # # # # # # # # # # # # # # # # # # # # # # #

<#
   .SYNOPSIS
   This sensor will monitor HyperV hosts and their virtual machines using SCVMM.
   .DESCRIPTION
   Installation:
   1. Save the script as PRTG-SCVMM-HyperV.ps1 under <PRTG Application folder>\Custom Sensors\EXE\
   2. Open up your SCVMM device in PRTG
   3. Add a new HTTP Push Data (Advanced) sensor to the device, name it any way you like (e.g. "Template Sensor"), and pause it. Note it's sensor ID
   4. Create a new EXE/Script sensor and select the PRTG-SCVMM-HyperV.ps1 script
   5. Set the timeout to 900 seconds
   6. Enter the following parameters:

   -prtgHostName <your prtg url, e.g. http://prtg.acme.com or https://prtg.acme.com>
   -prtgUserName <a user with read/write permissions to the device, or a PRTG administrator>
   -prtgPasshash <the passhash of the above user>
   -prtgTemplateSensor <the ID (not token) of the HTTP Push sensor>
   -prtgScvmmDeviceID %deviceid
   -ComputerName %host
   -Userdomain %windowsdomain
   -Username %windowsuser
   -Password %windowspassword

   When you enter the data in the script directly, you can also test it on the fly. Initially, it will look like the attached screenshot #1, consequential runs will look like #2.
   Note that the sensors may not have data directly after the first run. This is due to the startup of the sensors taking some time and the script may push values prior to that.
   .PARAMETER prtgHostName
   The URL of your PRTG webinterface, e.g. http://prtg.acme.com or https://prtg.acme.com
   .PARAMETER prtgPort
   The port used by your PRTG webinterface, e.g. 80 or 443
   .PARAMETER prtgUserName
   A user with read/write permissions to the device, or a PRTG administrator
   .PARAMETER prtgPassHash
   The passhash of the above user
   .PARAMETER prtgPushPort
   The push port you configured in the template HTTP Push Advanced sensor
   .PARAMETER prtgScvmmDeviceId
   This is the ID of the device that resembles your SCVMM server - use %deviceid
   .PARAMETER prtgTemplateSensor
   This is the ID of the HTTP Push Data (Advanced) template sensor (not the sensor token, but the PRTG ID)
   .PARAMETER Userdomain
   The domain of the user that will be used for remote powershell access - use %windowsdomain
   .PARAMETER Username
   The username of the user that will be used for remote powershell access - use %windowsuser
   .PARAMETER Password
   The password of the user that will be used for remote powershell access - use %windowspassword
   .PARAMETER verbose
   When this is set, the script will output debug messages. This can always be enabled as it doesn't bother PRTG.
   .EXAMPLE
   C:\PS> .\Get-Events.ps1  -ComputerName %host -Username "%windowsdomain\%windowsuser" -Password "%windowspassword" -ProviderName "Microsoft-Windows-Immersive-Shell" -Channel "Microsoft-Windows-TWinUI/Operational" -LimitEntries 1 -MaxAge 1 -EventID 1719 -Level 4
#>


param(
       [string]$prtgHostName      = "",
       [string]$prtgPort          = 80,
       [int]$prtgPushPort         = 5050,
       [string]$prtgUserName      = '',
       [string]$prtgPasshash      = 0,
       [int]$prtgScvmmDeviceId    = 0,
       [int]$prtgTemplateSensor   = 0,
       [string]$computername      = "",
       [string]$userdomain        = "",
       [string]$username          = "",
       [string]$password          = "",
       [switch]$verbose           = $true
)


$global:counter   = 0;
$scriptPath       = "C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXE";
$guidFile         = [string]::Format("{0}\{1}-guidfile.dat",$scriptPath,$computername);

$global:webclient = New-Object System.Net.WebClient;


# this will output debug messages to the console
function Console-ShowMessage([string]$type,$message){
    if($verbose){
        Write-Host ("[{0}] " -f (Get-Date)) -NoNewline;
        switch ($type){
            "success"       { Write-Host "    success    "  -BackgroundColor Green      -ForegroundColor White -NoNewline; }
            "information"   { Write-Host "  information  "  -BackgroundColor DarkCyan   -ForegroundColor White -NoNewline; }
            "warning"       { Write-Host "    warning    "  -BackgroundColor DarkYellow -ForegroundColor White -NoNewline; }
            "error"         { Write-Host "     error     "  -BackgroundColor DarkRed    -ForegroundColor White -NoNewline; }
            default         { Write-Host "     notes     "  -BackgroundColor DarkGray   -ForegroundColor White -NoNewline; }
        }
        Write-Host (" {0}{1}" -f $message,$Global:blank)
    }
}

# if the guid files don't exist, create them
if(!(Test-Path $guidFile))  { New-Item -ItemType File -Path $guidFile | Out-Null; Console-ShowMessage -type "information" -message "created GUID file: $($guidFile)"; }

Console-ShowMessage "information" "GUID file path: $($guidFile)";

$Stopwatch = [system.diagnostics.stopwatch]::new()

#region  xml item
$channel = @"
<result>
       <channel>{0}</channel>
       <value>{1}</value>{2}
       <showChart>{3}</showChart>
       {4}
       {5}
       {6}
   </result>
"@
#endregion

#region Function Library


# this will return a value only if it's an integer
function This-Numeric ($Value) {
    return $Value -match "^[\d\.]+$"
}

# Since we need lookup files to show this properly, we'll have to convert
# the states received to integers
function This-StateConvert([string]$Type, [string]$CurrentStatus){

 # replacement tables
 [hashtable]$States = @{
        "OverallStatesUnknown"              = -1
        "OverallStatesAdding "              = 1
        "OverallStatesNotResponding"        = 2
        "OverallStatesReassociating"        = 3
        "OverallStatesRemoving"             = 4
        "OverallStatesUpdating"             = 5
        "OverallStatesPending"              = 6
        "OverallStatesMaintenanceMode"      = 7
        "OverallStatesNeedsAttention"       = 8
        "OverallStateOk"                    = 9
        "OverallStatesLimited"              = 10
        "CommunicationStateUnknown"         = -1
        "CommunicationStateResponding"      = 0
        "CommunicationStateNotResponding"   = 1
        "CommunicationStateAccessDenied "   = 2
        "CommunicationStateConnecting"      = 3
        "CommunicationStateDisconnecting"   = 4
        "CommunicationStateResetting"       = 5
        "CommunicationStateNoConnection"    = 6
        "ComputerStateUnknown"              = -1
        "ComputerStateAdding"               = 0
        "ComputerStateRemoving"             = 1
        "ComputerStateResponding"           = 2
        "ComputerStateNotResponding"        = 3
        "ComputerStateAccessDenied"         = 4
        "ComputerStateUpdating"             = 5
        "ComputerStateReassociating"        = 6
        "ComputerStatePending"              = 7
        "ComputerStateMaintenanceMode"      = 8
        "ClusterNodeStatusUnknown"          = 0
        "ClusterNodeStatusRunning"          = 1
        "ClusterNodeStatusStopped"          = 2
        "ClusterNodeStatusNoCluster"        = 3
        "VirtualServerStateUnknown"         = 0
        "VirtualServerStateRunning"         = 1
        "VirtualServerStateStopped"         = 2
        "VMStateUnknown"                    = -1
        "VMStateRunning"                            = 0
        "VMStatePowerOff"                   = 1
        "VMStatePoweringOff"                = 2
        "VMStateSaved"                      = 3
        "VMStateSaving"                     = 4
        "VMStateRestoring"                  = 5
        "VMStatePaused"                     = 6
        "VMStateDiscardSavedState"          = 10
        "VMStateStarting"                   = 11
        "VMStateMergingDrives"              = 12
        "VMStateDeleting"                   = 13
        "VMStateDiscardingDrives"           = 80
        "VMStatePausing"                    = 81
        "VMStateUnderCreation"              = 100
        "VMStateCreationFailed"             = 101
        "VMStateStored"                     = 102
        "VMStateUnderTemplateCreation"      = 103
        "VMStateTemplateCreationFailed"     = 104
        "VMStateCustomizationFailed"        = 105
        "VMStateUnderUpdate"                = 106
        "VMStateUpdateFailed"               = 107
        "VMStateUnderMigration"             = 200
        "VMStateMigrationFailed"            = 201
        "VMStateCreatingCheckpoint"         = 210
        "VMStateDeletingCheckpoint"         = 211
        "VMStateRecoveringCheckpoint"       = 212
        "VMStateCheckpointFailed"           = 213
        "VMStateInitializingCheckpointOperation" = 214
        "VMStateFinishingCheckpointOperation"    = 215
        "VMStateMissing"                    = 220
        "VMStateHostNotResponding"          = 221
        "VMStateUnsupported"                = 222
        "VMStateIncompleteVMConfig"         = 223
        "VMStateUnsupportedSharedFiles"     = 224
        "VMStateUnsupportedCluster"         = 225
        "VMStateP2VCreationFailed"          = 240
        "VMStateV2VCreationFailed"          = 250
        
    }

 
 return $states[$Type+$CurrentStatus] 
 
}

# This will turn the metrics received from the SCVMM into PRTG channels,
# with their corresponding channel settings.
function This-PrtgXmlWrapper($Metrics){

    $cleanMetrics = $Metrics;

       foreach ($metric in $cleanMetrics.GetEnumerator() | sort -Property Name)
       {

       $Lookup = "";
       $Volume = "";

       #region Metric Properties Replacement
            # get the unit of the item
            If($metric.Value[1] -ne 0)
            { $Unit   = [string]::Format("<unit>{0}</unit>", $metric.Value[1])}
            else
            { $Unit   = "<unit>Count</unit>" }

            # get the value lookup of the item
            If($metric.Value[2] -ne 0)
            { $Lookup = [string]::Format("<ValueLookup>{0}</ValueLookup>",$metric.Value[2]); }

            # should the metric show up in the graph?
            If($metric.Value[3] -eq 0)
            { $showChart = 0 }
            else
            { $showChart = 1; }

            # can the item fire a change trigger?
            if($metric.Value[4] -ne 0)
            { $notifyChanged = "<NotifyChanged></NotifyChanged>" }
            else
            { $notifyChanged = "" }

            if($metric.value[5])
            { $Volume = "<VolumeSize>$($metric.value[5])</VolumeSize>" }

        #endregion
        # replace the state strings with their corresponding IDs
        if(!(This-Numeric $metric.Value[0]))
        { 
            $metric.Value[0] = (This-StateConvert -Type $metric.Name -CurrentStatus $metric.Value[0]) }
        $channels += [string]::Format($channel,$metric.Name, $metric.Value[0], $Unit,$showChart,$notifyChanged,$Lookup,$Volume)

       }
       return $channels;

}

# If there's an error, only this will be outputted
function This-PrtgError($Message){

    if(!($verbose)){
        Write-Host "<?xml version='1.0' encoding='UTF-8' ?><prtg>"
        Write-Host ([string]::Format("<error>1</error><text>{0}</text>",$Message));
        Write-Host "</prtg>";
    exit 0;
    }
}

# We need to ignore $null values, this will cleanse the metrics accordingly
function This-ResultSanitize($Metrics){

    $CleanMetric = @{};

    foreach ($metric in $Metrics.GetEnumerator() | sort -Property Name)
    { if($metric.Value[0] -ne $null) {$CleanMetric.Add($metric.key,$metric.value)} }

    return $CleanMetric;

}

# @Output: PSCredentialObject
#
# This function will generate a PowerShell Credential object for the
# given username, password and domainname
function This-GenerateCredential(){

    try{
    # Generate credentials object for authentication
    $SecPasswd   = ConvertTo-SecureString $password -AsPlainText -Force
    $Credentials = New-Object System.Management.Automation.PSCredential ([string]::Format("{0}\{1}",$userdomain,$username), $secpasswd)

    return $Credentials;
    }
    catch{

        catch{ This-PrtgError -Message "Couldn't connect to the server or execute the given commands. Please check if WinRM is enabled and allowed." }
    }

}

# @Output: Update HTTP Push (Advanced) sensors
function This-UpdateHTTPPushSensors {
     param([string]$type, [pscustomobject[]]$objects)

     $counter    = 0;

    # first load the GUID list to check the GUIDs against
     $guidList = ( Get-Content $guidFile );


     # add sensors that are not in our list as a HTTP Push Content sensor
     foreach($object in $objects){
        if(!($guidList -match $object.id))
        {
            #if ($object.ObjectType -eq "VM") {Write-Host("$($object.HostGroupPath.split("\")[1]) $($object.name)")}
            #Write-Host($object | select name, objecttype)
            if(This-AddHTTPPushSensors -sensorName $(if ($object.ObjectType -eq "VM") {"$($(Get-Cluster -Name $object.VMHost).name) - $($object.name)"} else {$object.name}) -Token $object.id)
            {
                Console-ShowMessage -type "success" -message "Sensor for $($object.name) created successfully.";
                # append the GUID to the file so we don't add duplicates in future scans
                $object | Select "ID" | ft -HideTableHeaders | Out-File -FilePath $guidFile -Append
                $counter++;
                $global:counter++;
            }
            else
            {
              Console-ShowMessage -type "error" -message "Could not create sensor for $($object.name).";
            }
        }
        else
        { Console-ShowMessage -type "information" -message "$($object.name) with ID $($object.id) is already existing as a sensor."; }
     }
     Console-ShowMessage -type "information" -message "$($counter) new $($type) have been added to PRTG.";
}

# @Output: Create HTTP Push (Advanced) sensors
#
# This function will generate the PRTG Metascan Items for the VMs in XML format
function This-AddHTTPPushSensors {
     param([string]$sensorName, [guid]$token)

     try{
         Console-ShowMessage "information" "Starting sensor creation for $($sensorName) (GUID: $($token))";

         # create the URL for duplicating the original sensor
         $url = [string]::Format("{0}:{1}/api/duplicateobject.htm?id={2}&name={3}&targetid={4}&username={5}&passhash={6}",
                          $prtgHostName, $prtgPort, $prtgTemplateSensor, $sensorName, $prtgScvmmDeviceId, $prtgUserName, $prtgPasshash);

         # call the URL and store the content, we need the actual ID of the new sensor to change the settings and unpause it
         $request = [System.Net.WebRequest]::Create($url);
         $request.AllowAutoRedirect = $false
         $response=$request.GetResponse();


         If ($response.StatusCode -eq "Redirect")
         {

            $response.GetResponseHeader("Location") -match '\d{3,}' | Out-Null;
            $newSensorID = $Matches[0];
            Console-ShowMessage -type "success" -message "Sensor created successfully. New sensor ID: $($newSensorID)";
         }
         Else
         { Console-ShowMessage "error" "Sensor creation failed. PRTG returned: $($response.StatusCode)"; }

         # modify the token to resemble the GUID of the device
         $url = [string]::Format("{0}:{1}/api/setobjectproperty.htm?id={2}&name={3}&value={4}&username={5}&passhash={6}",
                         $prtgHostName, $prtgPort, $newSensorID, "httppushtoken", $token, $prtgUserName, $prtgPasshash);

         $UpdateSensorResult = (Invoke-WebRequest $url)

         if($UpdateSensorResult.StatusCode -eq "200")
         { Console-ShowMessage -type "success" -message "Changed sensor token to GUID of the host/vm."; }

         # start the sensors
         $url = [string]::Format("{0}:{1}/api/pause.htm?id={2}&action=1&username={3}&passhash={4}",
                         $prtgHostName, $prtgPort, $newSensorID, $prtgUserName, $prtgPasshash);

         $StartSensorResult = (Invoke-WebRequest $url)

         if($StartSensorResult.StatusCode -eq "200")
         { Console-ShowMessage -type "success" -message "Sensor has been started succesfully."; }

         return $true
     }
     catch{ return $false; }
}

# @Output: PowerShell Object Array with all hosts
#
# This function will retrieve all VM hosts available
function This-GetHostsAndVms() {
    Console-ShowMessage -type "information" -message "Retrieving HyperV hosts and VMs...";
    try{
    $objects = (Invoke-Command -ComputerName $computername -ScriptBlock {

            # load the correct snapins:
            if ((new-object 'version' (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Microsoft System Center Virtual Machine Manager Server\Setup" ProductVersion | select -expandproperty productversion)) -ge (new-object 'Version' 3,0)) { Import-Module ((Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Microsoft System Center Virtual Machine Manager Server\Setup" InstallPath | select -ExpandProperty InstallPath) + "bin\psModules\virtualmachinemanager") } else { Add-PSSnapin Microsoft.SystemCenter.VirtualMachineManager }
            if ((new-object 'version' (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Microsoft System Center Virtual Machine Manager Server\Setup" ProductVersion | select -expandproperty productversion)) -ge (new-object 'Version' 6,2)) { Get-SCVMMServer localhost | Out-Null } else { Get-VMMServer localhost | Out-Null }

            $hosts = (Get-VMHost | Where-Object {$_.OperatingSystem -match "Windows"});
            $vms   = (Get-VM | Where-Object {$_.VirtualizationPlatform -match "HyperV"});

            # The cmdlets above give back a single object or an array of objects.
            # For the sake of simplicity, let's convert them, so they're always arrays
            if($hostList -isnot [system.array])
            { $hostList = @($hosts) }
            if($vmList -isnot [system.array])
            { $vmList = @($vms) }


            $objects = @($hostList,$vmList)

            return $objects;
        } -Credential (This-GenerateCredential)
    )
    return $objects;
    }
    catch{
    Console-ShowMessage -type "error" -message "Couldn't connect to the server or execute the given commands. Please check if WinRM is enabled and allowed.";
    This-PrtgError -Message "Couldn't connect to the server or execute the given commands. Please check if WinRM is enabled and allowed."
    }

}

# @Param token: the GUID of the VM/host
# @Param data:  the channels of the VM/host
function This-PushData([string]$token, [string]$data){

        $pushData = ([string]::Format("<prtg>{0}</prtg>",$data)).replace("`n"," ").Replace(" ",'%20');
             $url = [string]::Format("{0}:{1}/{2}?content={3}",($prtgHostName -replace "https","http"),$prtgPushPort,$token,$pushData);

        try   {

            Invoke-WebRequest $url -Method Get | Out-Null
            Console-ShowMessage -type "success" -message "Data for host with ID $($token) pushed to corresponding sensor.";
        }
        catch {
            Console-ShowMessage -type "error" -message "Couldn't push the data to the configured PRTG server using the specified token ($($token)).";
            This-PrtgError -Message "Couldn't push the data to the configured PRTG server using the specified token ($($token))."
        }
}

function This-GetSCVMMObjects(){

    # lets retrieve hosts and vms first
    $Objects = (This-GetHostsAndVms)

    # ... and seperate them
    $VMHosts   = $objects[0];
    $VMs       = $objects[1];

    Console-ShowMessage -type "success" -message "$($VMHosts.count) HyperV hosts have been found.";
    Console-ShowMessage -type "success" -message "$($VMs.count) Virtual Machines have been found.";

    # let's add the sensor first, before we do anything
    This-UpdateHTTPPushSensors -objects $VMHosts -type "HyperV Hosts"
    This-UpdateHTTPPushSensors -objects $VMs     -type "Virtual Machines"

    # we have to wait for the sensors to become active.
    if($global:counter -gt 0){
    Console-ShowMessage -type "information" "Waiting for new push sensors to become active"
    Start-Sleep 10;
    }

    # now that the sensors are there, let's push the values to them
    foreach($VMHost in $VMHosts){

          $metrics = @{
                    "OverallState"         = @($VMHost.OverallState,"Custom","prtg.standardlookups.hyperv.hoststatus",1,"<NotifyChanged>");
                    "CommunicationState"   = @($VMHost.CommunicationState,"Custom","prtg.standardlookups.hyperv.communicationstate");
                    "CpuUtilization"       = @($VMHost.CpuUtilization,"CPU",0,1,1,0);
                    "TotalMemory"          = @($VMHost.TotalMemory,"BytesMemory",0,1,0,"Kilobyte");
                    "AvailableMemory"      = @(($VMHost.AvailableMemory * 1024 * 1024),"BytesMemory",0,1,0,"MegaByte");
                    "ClusterNodeStatus"    = @($VMHost.ClusterNodeStatus,"Custom","prtg.standardlookups.hyperv.clusternodestatus");
                    "VirtualServerState"   = @($VMHost.VirtualServerState,"Custom","prtg.standardlookups.hyperv.virtualserverstate");
                    "ComputerState"        = @($VMHost.ComputerState,"Custom","prtg.standardlookups.hyperv.computerstate");
                    "HostCluster"          = @($VMHost.HostCluster,"Custom","prtg.standardlookups.hyperv.clusternodestatus"); }

         # first, we'll format the data and sanatize the metrics
         $channels = (This-PrtgXmlWrapper -Metrics $metrics);

         # ...then we'll push it to PRTG. Don't forget to join the array!
         This-PushData -token $VMHost.id -data $channels;
    }

    # The same thing again, but for the VMs
    foreach($VM in $VMs){

        $metrics = @{
                    "VMState"            = @($VM.Status,"Custom","prtg.standardlookups.hyperv.vmstatus",0,"<NotifyChanged>");
                    "CPU Usage"          = @($VM.PerfCPUUtilization,"Percent",0,0,0,0);
                    "Memory Available"   = @($VM.MemoryAvailablePercentage,"Percent",0,0,0,0);
                    "PerfDiskBytesRead"  = @($VM.PerfDiskBytesRead,"BytesDisk",0,0,0,0);
                    "PerfDiskBytesWrite" = @($VM.PerfDiskBytesWrite,"BytesDisk",0,0,0,0); }



        # first, we'll format the data and sanatize the metrics ...
        $channels = (This-PrtgXmlWrapper -Metrics $metrics);

        # ...then we'll push it to PRTG.
        This-PushData -token $VM.id -data $channels;
    }


}

function This-CheckVMExists {
    #Get content of GUID file
    $objects = Get-Content $guidFile | Where-Object {$_.trim() -ne ""}
    $VMs = (Invoke-Command -ComputerName $computername -ScriptBlock { 
        # load the correct snapins:
        if ((new-object 'version' (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Microsoft System Center Virtual Machine Manager Server\Setup" ProductVersion | select -expandproperty productversion)) -ge (new-object 'Version' 3,0)) { Import-Module ((Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Microsoft System Center Virtual Machine Manager Server\Setup" InstallPath | select -ExpandProperty InstallPath) + "bin\psModules\virtualmachinemanager") } else { Add-PSSnapin Microsoft.SystemCenter.VirtualMachineManager }
        if ((new-object 'version' (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Microsoft System Center Virtual Machine Manager Server\Setup" ProductVersion | select -expandproperty productversion)) -ge (new-object 'Version' 6,2)) { Get-SCVMMServer localhost | Out-Null } else { Get-VMMServer localhost | Out-Null }

        $VirtualMachines = Get-SCVirtualMachine | Select Name, id
        $VirtualHosts = Get-VMHost | select Name, Id
        
        $ObjectsToReturn = $VirtualMachines + $VirtualHosts

        return $ObjectsToReturn
    
    
    } -Credential (This-GenerateCredential))
    
    #Write-Host($VMs.id.guid)

    foreach ($object in $objects) {
        Console-ShowMessage "Information" "Checking for VM with GUID $($object)"
        
                      
        if ($VMs.Id.guid -match $object ) {
            #This VM exists, no need for further processing
            Console-ShowMessage "Information" "This VM Does Exist, resolving name as $($($VMs | Where-Object {$_.Id -eq $object}).name)"
            } 
            
        else {
            Console-ShowMessage "Error" "This VM Doesn't Exist, sending error to PRTG"
            #This VM doesn't exist, flag as error
            $metrics = @{
                    "VMState"                = @(220,"Custom","prtg.standardlookups.hyperv.hoststatus",1,"<NotifyChanged>");
                    }

             # first, we'll format the data and sanatize the metrics
             
             $channels = (This-PrtgXmlWrapper -Metrics $metrics);

             # ...then we'll push it to PRTG. Don't forget to join the array!
             This-PushData -token $object -data $channels;
             }
        }
    }



$Stopwatch.Start();
Console-ShowMessage "Information" "Gathering VM Metrics"
This-GetSCVMMObjects; 
Console-ShowMessage "Information" "Checking for missing VMs"
This-CheckVMExists; $Stopwatch.Stop();
Console-ShowMessage -type "information" -message "Elapsed Time: $($Stopwatch.Elapsed)";

$objects = (((gc $guidFile) | ? {$_.trim() -ne "" } | Measure-Object).Count)





write-host ([string]::Format("{0}:Monitoring {2} objects. Last scan took {1} seconds and added {0} objects.",$global:counter,$Stopwatch.Elapsed.Seconds,$objects));

Created on Mar 16, 2021 9:59:07 AM by  norphus (30) 1



Votes:

0

Your Vote:

Up

Down

Thanks, added to the list! :)

Created on Mar 17, 2021 9:21:48 AM by  Stephan Linke [Paessler Support]



Votes:

0

Your Vote:

Up

Down

So I think I got this to work - however some machines are duplicated? And my XML Custom EXE/Script sensor has a red failure.

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)

Is that normal? Is there any difference for this to work with SCVMM 2019? I am using v1.4 of the script from github...

Created on Jul 21, 2021 5:56:05 AM by  Erik Tank (0)

Last change on Jul 21, 2021 9:02:49 AM by  Felix Wiesneth [Paessler Support]



Votes:

0

Your Vote:

Up

Down

Erik,

Can you post the raw output from the script?

Benjamin Day
[Paessler Support]

Created on Jul 21, 2021 5:03:10 PM by  Benjamin Day [Paessler Support]



Please log in or register to enter your reply.


Disclaimer: The information in the Paessler Knowledge Base comes without warranty of any kind. Use at your own risk. Before applying any instructions please exercise proper system administrator housekeeping. You must make sure that a proper backup of all your data is available.