I have a script I want to share. There is already a German topic (https://helpdesk.paessler.com/en/support/solutions/articles/2493-how-can-i-monitor-flexlm-lizenzdienste), but I fine-tuned the script so you can read all licenses at once.

You will need the lmutil.exe from the FlexLM tools util folder and put it together with this script in the EXEXML PRTG folder. In the parameters you can define the server and which licenses you want to monitor.

Script:

# **********************************************************************************
# * SCRIPT INFORMATION                                                             *
# * ==================                                                             *
# *                                                                                *
# * NAME        : FlexLM_LicenseMonitor.ps1                                        *
# * DESCRIPTION : FlexLM_LicenseMonitor for PRTG (EXEXML Sensor)                   *
# *               Lookup the number of licenses used with lmutil                   *
# *                                                                                *
# * EXT. SOFT.  : - lmutil.exe                                                     *
# *                 --> Search for it in the FlexLM util folder                    *
# *                                                                                *
# **********************************************************************************

# **********************************************************************************
# * CHANGE LOG                                                                     *
# * ==========                                                                     *
# *                                                                                *
# * DATE          USER      DESCRIPTION                                            *
# * ------------------------------------------------------------------------------ *
# *                                                                                *
# *                                                                                *
# **********************************************************************************

# **********************************************************************************
# * USAGE                                                                          *
# * =====                                                                          *
# *                                                                                *
# * Script.ps1 -PortServer 1234@ServerName -Features F1,F2, ...                    *
# *                                                                                *
# * PortServer: Port and Servername to connect to the FlexLM License Manager       *
# * Features: Name of the License (Run the lmutil to see available features)       *
# *                                                                                *
# **********************************************************************************



# Parameters
# ==========

param(
   [Parameter(Mandatory=$True)]
   [string] $PortServer,

   [Parameter(Mandatory=$True)]
   [array] $Features
)



# Set static variables
# ====================

$LMUtilPath	= "C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\lmutil.exe"
$TempXMLFile	= "C:\Windows\Temp\LMUtil_" + $PortServer.Replace("@","") + ".xml"



# Set other variables
# ===================

$FeaturesTotalMax   = 0
$FeaturesTotalValue = 0



# Functions
# =========

function AddXMLResult
{
   param(
      [string] $Channel, 
      [string] $Val,
      [string] $Unit
   )

   $xmlWriter.WriteStartElement("Result")

   $xmlWriter.WriteStartElement("Channel")
   $xmlWriter.WriteString($Channel)
   $xmlWriter.WriteEndElement() # Close Channel

   $xmlWriter.WriteStartElement("Value")
   $xmlWriter.WriteString($Val)
   $xmlWriter.WriteEndElement() # Close Value

   switch($Unit) {
	"Lic" {
           $xmlWriter.WriteStartElement("CustomUnit");
           $xmlWriter.WriteString("Lic");
           $xmlWriter.WriteEndElement() # close CustomUnit
        }
	"Percent" {
           $xmlWriter.WriteStartElement("Unit");
           $xmlWriter.WriteString("Percent");
           $xmlWriter.WriteEndElement() # close Unit
        }
   }

   $xmlWriter.WriteEndElement() # close Result
}



# Start Script
# ============


# Open XML Doc
# ------------

$xmlWriter = New-Object System.Xml.XmlTextWriter($TempXMLFile,$null)
$xmlWriter.Formatting = "Indented"
$xmlWriter.Indentation = "2"
$xmlWriter.WriteStartDocument()
$xmlWriter.WriteStartElement("PRTG")


# Lookup Features
# ---------------

ForEach ($Feature in $Features) { 
   $ReadLicense  = &$LMUtilPath lmstat -a -c $PortServer | Select-String -Pattern ("Users of " + $Feature + ":")

   $FindNumbers  = [RegEx]"\b [0-9]+ \b"
   $ValuesFound  = $FindNumbers.Matches($ReadLicense)

   $FeatureMax   = $ValuesFound[0].Value.Trim()
   $FeatureValue = $ValuesFound[1].Value.Trim()

   $FeaturesTotalMax = $FeaturesTotalMax + $FeatureMax
   $FeaturesTotalValue = $FeaturesTotalValue + $FeatureValue

   $FeaturePerc  = [math]::Round($FeatureValue / $FeatureMax * 100)


   # Provide License Name When Known
   # -------------------------------

   $FeatureName  = $Feature
   switch($Feature) {
	"dwgeditor" { $FeatureName = "DWG Editor"}
	"solidworks" { $FeatureName = "SolidWorks Standard"}
	"swofficepro" { $FeatureName = "SolidWorks Professional"}
	"swofficepremium" { $FeatureName = "SolidWorks Premium"}
	"swepdm_viewer" { $FeatureName = "PDM Viewer"}
	"swepdm_cadeditorandweb" { $FeatureName = "PDM Editor"}
	"swepdm_contributorandweb" { $FeatureName = "PDM Contributor"}
   }


   # Add to XML
   # ----------

   AddXMLResult $FeatureName $FeatureValue "Lic"
   AddXMLResult ($FeatureName + " Perc") $FeaturePerc "Percent"
}


# Calc totals & Add to XML
# ------------------------

$FeaturesTotalPerc = [math]::Round($FeaturesTotalValue / $FeaturesTotalMax * 100)

AddXMLResult "Total Licenses Used" $FeaturesTotalValue "Lic"
AddXMLResult "Total Licenses Used Perc" $FeaturesTotalPerc "Percent"



# Close XML Doc
# -------------

$xmlWriter.WriteEndElement() # Close root element (PRTG)
$xmlWriter.WriteEndDocument()
$xmlWriter.Flush()
$xmlWriter.Close()


# Write-Output XML Doc
# --------------------
Write-Output (Get-Content $TempXMLFile)


Article Comments

Thank you very much for sharing this!


Mar, 2016 - Permalink

I can verify that this works in our environment. Fantastic script! Thank you.


Mar, 2017 - Permalink

Hi can someone help me here? I have added this as a EXE/Script Sensor. The script i running and giving results that make sense.

But PRTG is giving this results. What are I doing wrong?

Response not wellformed: "(<?xml version="1.0"?> <PRTG> <Result> <Channel>ZWCAD PRO</Channel> <Value>3</Value> <CustomUnit>Lic</CustomUnit> </Result> <Result> <Channel>ZWCAD PRO Perc</Channel> <Value>23</Value> <Unit>Percent</Unit> </Result> <Result> <Channel>Total Licenses Used</Channel> <Value>3</Value> <CustomUnit>Lic</CustomUnit> </Result> <Result> <Channel>Total Licenses Used Perc</Channel> <Value>23</Value> <Unit>Percent</Unit> </Result> </PRTG> )" (code: PE132)

The output file looks like this: <?xml version="1.0"?> <PRTG> <Result> <Channel>ZWCAD PRO</Channel> <Value>3</Value> <CustomUnit>Lic</CustomUnit> </Result> <Result> <Channel>ZWCAD PRO Perc</Channel> <Value>23</Value> <Unit>Percent</Unit> </Result> <Result> <Channel>Total Licenses Used</Channel> <Value>3</Value> <CustomUnit>Lic</CustomUnit> </Result> <Result> <Channel>Total Licenses Used Perc</Channel> <Value>23</Value> <Unit>Percent</Unit> </Result> </PRTG>


Oct, 2017 - Permalink

Hello OlaAndre,

it looks like you've used the incorrect sensor type. Since this is a multi-channel sensor, you need to use the EXE/Script Advanced sensor, you will get an error if you attempt to use the regular EXE/Script sensor.

Please be aware that the script file also needs to be placed in the corresponding folder:

EXE/ScriptC:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXE\
EXE/Script AdvancedC:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\

Best Regards,
Luciano Lingnau [Paessler Support]


Oct, 2017 - Permalink

Thanks Luciano for quick answer.


Oct, 2017 - Permalink

Hello,

I extend the script from WesleyVH, so that the issued licenses were also shown.

e.g.: Users of XXX: (Total of 5 licenses issued; Total of 0 licenses in use)

Best Regards thsch

# **********************************************************************************
# * SCRIPT INFORMATION                                                             *
# * ==================                                                             *
# *                                                                                *
# * NAME        : FlexLM_LicenseMonitor.ps1                                        *
# * DESCRIPTION : FlexLM_LicenseMonitor for PRTG (EXEXML Sensor)                   *
# *               Lookup the number of licenses used with lmutil                   *
# *                                                                                *
# * EXT. SOFT.  : - lmutil.exe                                                     *
# *                 --> Search for it in the FlexLM util folder                    *
# *                                                                                *
# **********************************************************************************

# **********************************************************************************
# * CHANGE LOG                                                                     *
# * ==========                                                                     *
# *                                                                                *
# * DATE          USER      DESCRIPTION                                            *
# * ------------------------------------------------------------------------------ *
# * 25.11.2017    tsch      Shows Total Values in the result                       *
# *                                                                                *
# **********************************************************************************

# **********************************************************************************
# * USAGE                                                                          *
# * =====                                                                          *
# *                                                                                *
# * Script.ps1 -PortServer 1234@ServerName -Features F1,F2, ...                    *
# *                                                                                *
# * PortServer: Port and Servername to connect to the FlexLM License Manager       *
# * Features: Name of the License (Run the lmutil to see available features)       *
# *                                                                                *
# **********************************************************************************



# Parameters
# ==========

param(
   [Parameter(Mandatory=$True)]
   [string] $PortServer,

   [Parameter(Mandatory=$True)]
   [array] $Features
)



# Set static variables
# ====================

$LMUtilPath	= "C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\lmutil.exe"
$TempXMLFile	= "C:\Windows\Temp\LMUtil_" + $PortServer.Replace("@","") + ".xml"



# Set other variables
# ===================

$FeaturesTotalMax   = 0
$FeaturesTotalValue = 0



# Functions
# =========

function AddXMLResult
{
   param(
      [string] $Channel, 
      [string] $Val,
      [string] $Unit
   )

   $xmlWriter.WriteStartElement("Result")

   $xmlWriter.WriteStartElement("Channel")
   $xmlWriter.WriteString($Channel)
   $xmlWriter.WriteEndElement() # Close Channel

   $xmlWriter.WriteStartElement("Value")
   $xmlWriter.WriteString($Val)
   $xmlWriter.WriteEndElement() # Close Value

   switch($Unit) {
	"Lic" {
           $xmlWriter.WriteStartElement("CustomUnit");
           $xmlWriter.WriteString("Lic");
           $xmlWriter.WriteEndElement() # close CustomUnit
        }
        "Total" {
           $xmlWriter.WriteStartElement("CustomUnit");
           $xmlWriter.WriteString("Lic");
           $xmlWriter.WriteEndElement() # close CustomUnit
        }
	"Percent" {
           $xmlWriter.WriteStartElement("Unit");
           $xmlWriter.WriteString("Percent");
           $xmlWriter.WriteEndElement() # close Unit
        }
   }

   $xmlWriter.WriteEndElement() # close Result
}



# Start Script
# ============


# Open XML Doc
# ------------

$xmlWriter = New-Object System.Xml.XmlTextWriter($TempXMLFile,$null)
$xmlWriter.Formatting = "Indented"
$xmlWriter.Indentation = "2"
$xmlWriter.WriteStartDocument()
$xmlWriter.WriteStartElement("PRTG")


# Lookup Features
# ---------------

ForEach ($Feature in $Features) { 
   $ReadLicense  = &$LMUtilPath lmstat -a -c $PortServer | Select-String -Pattern ("Users of " + $Feature + ":")

   $FindNumbers  = [RegEx]"\b [0-9]+ \b"
   $ValuesFound  = $FindNumbers.Matches($ReadLicense)

   $FeatureMax   = $ValuesFound[0].Value.Trim()
   $FeatureValue = $ValuesFound[1].Value.Trim()

   $FeaturesTotalMax = $FeaturesTotalMax + $FeatureMax
   $FeaturesTotalValue = $FeaturesTotalValue + $FeatureValue

   $FeaturePerc  = [math]::Round($FeatureValue / $FeatureMax * 100)


   # Provide License Name When Known
   # -------------------------------

   $FeatureName  = $Feature
   switch($Feature) {
	"dwgeditor" { $FeatureName = "DWG Editor"}
	"solidworks" { $FeatureName = "SolidWorks Standard"}
	"swofficepro" { $FeatureName = "SolidWorks Professional"}
	"swofficepremium" { $FeatureName = "SolidWorks Premium"}
	"swepdm_viewer" { $FeatureName = "PDM Viewer"}
	"swepdm_cadeditorandweb" { $FeatureName = "PDM Editor"}
	"swepdm_contributorandweb" { $FeatureName = "PDM Contributor"}
   }


   # Add to XML
   # ----------

   AddXMLResult $FeatureName $FeatureValue "Lic"
   AddXMLResult ($FeatureName + " Total") $FeatureMax "Total"
   AddXMLResult ($FeatureName + " Perc") $FeaturePerc "Percent"
}


# Calc totals & Add to XML
# ------------------------

$FeaturesTotalPerc = [math]::Round($FeaturesTotalValue / $FeaturesTotalMax * 100)

AddXMLResult "Total Licenses Used" $FeaturesTotalValue "Lic"
AddXMLResult "Total Licenses" $FeaturesTotalMax "Total"
AddXMLResult "Total Licenses Used Perc" $FeaturesTotalPerc "Percent"



# Close XML Doc
# -------------

$xmlWriter.WriteEndElement() # Close root element (PRTG)
$xmlWriter.WriteEndDocument()
$xmlWriter.Flush()
$xmlWriter.Close()


# Write-Output XML Doc
# --------------------
Write-Output (Get-Content $TempXMLFile)


Nov, 2017 - Permalink

afther the update of version PRTG Network Monitor 18.2.39.1661 x64

we get the error

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 there a solution for it


Apr, 2018 - Permalink

Hi there,

Please activate the "Write EXE result to disk" option in the sensor's settings and post the log files (Result of Sensor XXX.Data.txt and Result of Sensor XXX.txt) located on the corresponding probe under "C:\ProgramData\Paessler\PRTG Network Monitor\Logs (Sensors)".

Best regards.


Apr, 2018 - Permalink

hi,

i see no error in te

C:\ProgramData\Paessler\PRTG Network Monitor\Logs (Sensors)".

te output file =

<?xml version="1.0"?>
<PRTG>
  <Result>
    <Channel>64300ACD_F</Channel>
    <Value>2</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>64300ACD_F Total</Channel>
    <Value>11</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>64300ACD_F Perc</Channel>
    <Value>18</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>64900CIV3D_F</Channel>
    <Value>11</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>64900CIV3D_F Total</Channel>
    <Value>12</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>64900CIV3D_F Perc</Channel>
    <Value>92</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>85812IDSP_F</Channel>
    <Value>0</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>85812IDSP_F Total</Channel>
    <Value>2</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>85812IDSP_F Perc</Channel>
    <Value>0</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>86295ACD_2015_0F</Channel>
    <Value>0</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86295ACD_2015_0F Total</Channel>
    <Value>11</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86295ACD_2015_0F Perc</Channel>
    <Value>0</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>86445ACD_2016_0F</Channel>
    <Value>1</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86445ACD_2016_0F Total</Channel>
    <Value>11</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86445ACD_2016_0F Perc</Channel>
    <Value>9</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>86468IDSP_2016_0F</Channel>
    <Value>2</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86468IDSP_2016_0F Total</Channel>
    <Value>2</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86468IDSP_2016_0F Perc</Channel>
    <Value>100</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>86514CIV3D_2016_0F</Channel>
    <Value>12</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86514CIV3D_2016_0F Total</Channel>
    <Value>12</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86514CIV3D_2016_0F Perc</Channel>
    <Value>100</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>86718CIV3D_2017_0F</Channel>
    <Value>12</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86718CIV3D_2017_0F Total</Channel>
    <Value>12</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86718CIV3D_2017_0F Perc</Channel>
    <Value>100</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>86830ACD_2018_0F</Channel>
    <Value>1</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86830ACD_2018_0F Total</Channel>
    <Value>11</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86830ACD_2018_0F Perc</Channel>
    <Value>9</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>86893CIV3D_2018_0F</Channel>
    <Value>12</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86893CIV3D_2018_0F Total</Channel>
    <Value>12</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86893CIV3D_2018_0F Perc</Channel>
    <Value>100</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>86909IDSP_2018_0F</Channel>
    <Value>2</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86909IDSP_2018_0F Total</Channel>
    <Value>2</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86909IDSP_2018_0F Perc</Channel>
    <Value>100</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>86063ACD_2014_0F</Channel>
    <Value>0</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86063ACD_2014_0F Total</Channel>
    <Value>11</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86063ACD_2014_0F Perc</Channel>
    <Value>0</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>86123IDSP_2014_0F</Channel>
    <Value>2</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86123IDSP_2014_0F Total</Channel>
    <Value>2</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86123IDSP_2014_0F Perc</Channel>
    <Value>100</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>86173CIV3D_2014_0F</Channel>
    <Value>12</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86173CIV3D_2014_0F Total</Channel>
    <Value>12</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86173CIV3D_2014_0F Perc</Channel>
    <Value>100</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>86252IDSP_2015_0F</Channel>
    <Value>2</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86252IDSP_2015_0F Total</Channel>
    <Value>2</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86252IDSP_2015_0F Perc</Channel>
    <Value>100</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>86354CIV3D_2015_0F</Channel>
    <Value>12</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86354CIV3D_2015_0F Total</Channel>
    <Value>12</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86354CIV3D_2015_0F Perc</Channel>
    <Value>100</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>86604ACD_2017_0F</Channel>
    <Value>0</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86604ACD_2017_0F Total</Channel>
    <Value>11</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86604ACD_2017_0F Perc</Channel>
    <Value>0</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>86702IDSP_2017_0F</Channel>
    <Value>2</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86702IDSP_2017_0F Total</Channel>
    <Value>2</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>86702IDSP_2017_0F Perc</Channel>
    <Value>100</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>Total Licenses Used</Channel>
    <Value>85</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Total Licenses</Channel>
    <Value>150</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Total Licenses Used Perc</Channel>
    <Value>57</Value>
    <Unit>Percent</Unit>
  </Result>
</PRTG>

Apr, 2018 - Permalink

Hi there,

Is this really all within the log file?
I created a simple PowerShell Script which just outputs what you have posted and the results are properly displayed within PRTG without any issue.

Best regards.


Apr, 2018 - Permalink

The log error

Data['blockedsens'].asString := '';
Data['canlinux'].asString := '0';
Data['channelinfos'].asString := '{}';
Data['channelnames'].asString := '';
Data['environment'].asString := '';
Data['exefile'].asString := 'PRTG_FlexLM.PS1';
Data['exeparams'].asString := '-PortServer 27001@NLUTCVLIC03 -Features 64300ACD_F, 64900CIV3D_F, 85812IDSP_F, 86295ACD_2015_0F, 86445ACD_2016_0F, 86468IDSP_2016_0F, 86514CIV3D_2016_0F, 86718CIV3D_2017_0F, 86830ACD_2018_0F, 86893CIV3D_2018_0F, 86909IDSP_2018_0F,86063ACD_2014_0F, 86123IDSP_2014_0F, 86173CIV3D_2014_0F, 86252IDSP_2015_0F, 86354CIV3D_2015_0F, 86604ACD_2017_0F, 86702IDSP_2017_0F';
Data['exeparamscache'].asString := '-PortServer 27001`@NLUTCVLIC03 -Features 64300ACD_F`, 64900CIV3D_F`, 85812IDSP_F`, 86295ACD_2015_0F`, 86445ACD_2016_0F`, 86468IDSP_2016_0F`, 86514CIV3D_2016_0F`, 86718CIV3D_2017_0F`, 86830ACD_2018_0F`, 86893CIV3D_2018_0F`, 86909IDSP_2018_0F`,86063ACD_2014_0F`, 86123IDSP_2014_0F`, 86173CIV3D_2014_0F`, 86252IDSP_2015_0F`, 86354CIV3D_2015_0F`, 86604ACD_2017_0F`, 86702IDSP_2017_0F';
Data['exeparamshash'].asString := '9b2fd105c0df9c1413f0be9fe4edc289c40626a9';
Data['fastcount'].asString := '0';
Data['host'].asString := 'server';
Data['hostv6'].asString := '';
Data['inerror'].asString := '1';
Data['interfacenumber'].asString := '';
Data['inum'].asString := '';
Data['ipversion'].asString := '0';
Data['isexesensor'].asString := '1';
Data['lastmsg'].asString := '#Y2 @#O233 @#O231[Invalid JSON.]';
Data['lastuptime'].asString := '0';
Data['linuxlogindomain'].asString := '';
Data['linuxloginpassword'].asString := '***';
Data['monitorchange'].asString := '';
Data['mutexname'].asString := '';
Data['notonpod'].asString := '0';
Data['reboot'].asString := '43202.4698003241';
Data['reqmsginterval'].asString := '60';
Data['resultfile'].asString := 'Result of Sensor 4787.txt';
Data['sensorid'].asString := '4787';
Data['simulate'].asString := '0';
Data['timeout'].asString := '60';
Data['tlsexplicit_default'].asString := '';
Data['tlsexplicit_ftp'].asString := '';
Data['tlsexplicit_imap'].asString := '';
Data['tlsexplicit_pop3'].asString := '';
Data['tlsexplicit_port'].asString := '';
Data['tlsexplicit_smtp'].asString := '';
Data['uptimecount'].asString := '0';
Data['usednstime'].asString := '0';
Data['usewindowsauthentication'].asString := '0';
Data['windowslogindomain'].asString := 'domain';
Data['windowsloginpassword'].asString := '***';
Data['windowsloginusername'].asString := 'loginname';
Data['writeresult'].asString := '1';

Apr, 2018 - Permalink

Hi there,

It should work when the output in the first response is really all. The result log file, the one you posted first, is there more in this file or just the XML Structure?

Best regards.


Apr, 2018 - Permalink

i just use the PS1 script and the parameters no other settings


Apr, 2018 - Permalink

Hi, we are also using the same script and it was working before the latest update of PRTG. Does any of you have found a workaround for this? We have this error: 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)

Best regards.


Apr, 2018 - Permalink

Hi there,

I think I know where the issue is. We had changed the parameter exchange with PRTG and the scripts in the recent version. This change, due to security concerns, disabled the abbility of filling arrays via parameters. Currently you fill one parameter with multiple values:

-parameter "Value1","Value2","Value3"

However only the following will work from now on:

-parameter1 "Value1" -parameter2 "Value2" -parameter3 "Value3"



Best regards.


Apr, 2018 - Permalink

Hi,

looks good but doesn't work:

We submit

-PortServer "1705@erlh196a" -Features1 "MATLAB" -Features2 "Image_Toolbox" -Features3 "Instr_Control_Toolbox" -Features4 "Optimization_Toolbox" -Features5 "Distrib_Computing_Toolbox" -Features6 "Signal_Toolbox"

to the sensor and get

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)

and in addition a "debug-file" called "Result of Sensor 24156.Data.txt" without any error messages.

Calling:

Flexlm_license.ps1 "1705@erlh196a" MATLAB,"Image_Toolbox","Instr_Control_Toolbox","Optimization_Toolbox","Distrib_Computing_Toolbox","Signal_Toolbox"

in a PowerShell works well.

There must be a problem with handling parameters and/or parsing the result.

Any help is appriciated.

Thanks in advance

Best regards

cyberclaus62


Apr, 2018 - Permalink

Hi there,

Could you post the result of the "Result of Sensor 24156.txt"? There you should see what the script results in and what error may occur.

Best regards.


Apr, 2018 - Permalink

Hi,

here it is:

Data['blockedsens'].asString := '';
Data['canlinux'].asString := '0';
Data['channelinfos'].asString := '{"2":{"Unit":"oukCustom","CustomUnit":"Lic","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"3":{"Unit":"oukPercent","CustomUnit":"#","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"4":{"Unit":"oukCustom","CustomUnit":"Lic","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"5":{"Unit":"oukPercent","CustomUnit":"#","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"6":{"Unit":"oukCustom","CustomUnit":"Lic","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"7":{"Unit":"oukPercent","CustomUnit":"#","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"8":{"Unit":"oukCustom","CustomUnit":"Lic","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"9":{"Unit":"oukPercent","CustomUnit":"#","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"10":{"Unit":"oukCustom","CustomUnit":"Lic","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"11":{"Unit":"oukPercent","CustomUnit":"#","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"12":{"Unit":"oukCustom","CustomUnit":"Lic","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"13":{"Unit":"oukPercent","CustomUnit":"#","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"14":{"Unit":"oukCustom","CustomUnit":"Lic","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"15":{"Unit":"oukPercent","CustomUnit":"#","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"16":{"Unit":"oukCustom","CustomUnit":"Lic","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"17":{"Unit":"oukPercent","CustomUnit":"#","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"18":{"Unit":"oukCustom","CustomUnit":"Lic","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"19":{"Unit":"oukPercent","CustomUnit":"#","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"20":{"Unit":"oukCustom","CustomUnit":"Lic","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"21":{"Unit":"oukPercent","CustomUnit":"#","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"22":{"Unit":"oukCustom","CustomUnit":"Lic","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"23":{"Unit":"oukPercent","CustomUnit":"#","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"24":{"Unit":"oukCustom","CustomUnit":"Lic","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"25":{"Unit":"oukPercent","CustomUnit":"#","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"26":{"Unit":"oukCustom","CustomUnit":"Lic","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""},"27":{"Unit":"oukPercent","CustomUnit":"#","ValueLookupName":"","LimitMode":"0","LimitMinError":"","LimitMinWarning":"","LimitMaxError":"","LimitMaxWarning":""}}';
Data['channelnames'].asString := 'MATLAB'#$D#$A + 
'2'#$D#$A + 
'MATLAB Perc'#$D#$A + 
'3'#$D#$A + 
'Image_Toolbox'#$D#$A + 
'4'#$D#$A + 
'Image_Toolbox Perc'#$D#$A + 
'5'#$D#$A + 
'Instr_Control_Toolbox'#$D#$A + 
'6'#$D#$A + 
'Instr_Control_Toolbox Perc'#$D#$A + 
'7'#$D#$A + 
'Optimization_Toolbox'#$D#$A + 
'8'#$D#$A + 
'Optimization_Toolbox Perc'#$D#$A + 
'9'#$D#$A + 
'Distrib_Computing_Toolbox'#$D#$A + 
'10'#$D#$A + 
'Distrib_Computing_Toolbox Perc'#$D#$A + 
'11'#$D#$A + 
'Signal_Toolbox'#$D#$A + 
'12'#$D#$A + 
'Signal_Toolbox Perc'#$D#$A + 
'13'#$D#$A + 
'Total Licenses Used'#$D#$A + 
'14'#$D#$A + 
'Total Licenses Used Perc'#$D#$A + 
'15'#$D#$A + 
'MATLAB,Image_Toolbox,Instr_Control_Toolbox,Optimization_Toolbox,Distrib_Computing_Toolbox,Signal_Toolbox'#$D#$A + 
'16'#$D#$A + 
'MATLAB,Image_Toolbox,Instr_Control_Toolbox,Optimization_Toolbox,Distrib_Computing_Toolbox,Signal_Toolbox Perc'#$D#$A + 
'17'#$D#$A + 
'`MATLAB,Image_Toolbox,Instr_Control_Toolbox,Optimization_Toolbox,Distrib_Computing_Toolbox,Signal_Toolbox`'#$D#$A + 
'18'#$D#$A + 
'`MATLAB,Image_Toolbox,Instr_Control_Toolbox,Optimization_Toolbox,Distrib_Computing_Toolbox,Signal_Toolbox` Perc'#$D#$A + 
'19'#$D#$A + 
'MATLAB Image_Toolbox Instr_Control_Toolbox Optimization_Toolbox Distrib_Computing_Toolbox Signal_Toolbox'#$D#$A + 
'20'#$D#$A + 
'MATLAB Image_Toolbox Instr_Control_Toolbox Optimization_Toolbox Distrib_Computing_Toolbox Signal_Toolbox Perc'#$D#$A + 
'21'#$D#$A + 
'MATLAB`,`Image_Toolbox`,`Instr_Control_Toolbox,Optimization_Toolbox,Distrib_Computing_Toolbox,Signal_Toolbox'#$D#$A + 
'22'#$D#$A + 
'MATLAB`,`Image_Toolbox`,`Instr_Control_Toolbox,Optimization_Toolbox,Distrib_Computing_Toolbox,Signal_Toolbox Perc'#$D#$A + 
'23'#$D#$A + 
'"MATLAB","Image_Toolbox","Instr_Control_Toolbox","Optimization_Toolbox","Distrib_Computing_Toolbox","Signal_Toolbox"'#$D#$A + 
'24'#$D#$A + 
'"MATLAB","Image_Toolbox","Instr_Control_Toolbox","Optimization_Toolbox","Distrib_Computing_Toolbox","Signal_Toolbox" Perc'#$D#$A + 
'25'#$D#$A + 
'`MATLAB`,`Image_Toolbox`,`Instr_Control_Toolbox`,`Optimization_Toolbox`,`Distrib_Computing_Toolbox`,`Signal_Toolbox'#$D#$A + 
'26'#$D#$A + 
'`MATLAB`,`Image_Toolbox`,`Instr_Control_Toolbox`,`Optimization_Toolbox`,`Distrib_Computing_Toolbox`,`Signal_Toolbox Perc'#$D#$A + 
'27'#$D#$A + 
'';
Data['checkfailed'].asString := '0';
Data['environment'].asString := '';
Data['exefile'].asString := 'Flexlm_license.ps1';
Data['exeparams'].asString := '"1705@erlh196a" "`MATLAB`,`Image_Toolbox`,`Instr_Control_Toolbox`,`Optimization_Toolbox`,`Distrib_Computing_Toolbox`,`Signal_Toolbox"';
Data['exeparamscache'].asString := '\"1705@erlh196a\" \"``MATLAB``,``Image_Toolbox``,``Instr_Control_Toolbox``,``Optimization_Toolbox``,``Distrib_Computing_Toolbox``,``Signal_Toolbox\"';
Data['exeparamshash'].asString := '656d3bff495bac3cd826a3a7ddd9e2553276c1bb';
Data['fastcount'].asString := '0';
Data['host'].asString := 'ERLH196A';
Data['hostv6'].asString := '';
Data['inerror'].asString := '0';
Data['interfacenumber'].asString := '';
Data['inum'].asString := '';
Data['ipversion'].asString := '0';
Data['isexesensor'].asString := '1';
Data['lastmsg'].asString := '#P1';
Data['lastuptime'].asString := '0';
Data['linuxlogindomain'].asString := '';
Data['linuxloginpassword'].asString := '***';
Data['monitorchange'].asString := '';
Data['mutexname'].asString := '';
Data['notonpod'].asString := '0';
Data['reboot'].asString := '43208.0997634606';
Data['reqmsginterval'].asString := '300';
Data['resultfile'].asString := 'Result of Sensor 24156.txt';
Data['sensorid'].asString := '24156';
Data['simulate'].asString := '0';
Data['timeout'].asString := '60';
Data['tlsexplicit_default'].asString := '';
Data['tlsexplicit_ftp'].asString := '';
Data['tlsexplicit_imap'].asString := '';
Data['tlsexplicit_pop3'].asString := '';
Data['tlsexplicit_port'].asString := '';
Data['tlsexplicit_smtp'].asString := '';
Data['uptimecount'].asString := '0';
Data['usednstime'].asString := '0';
Data['usewindowsauthentication'].asString := '1';
Data['windowslogindomain'].asString := 'ad005';
Data['windowsloginpassword'].asString := '***';
Data['windowsloginusername'].asString := 'Z003MHXJ-S01';
Data['writeresult'].asString := '2';

Thanks for having a look at it

Best regards cyberclaus62


Apr, 2018 - Permalink

Hi there,

This is stille the ".DATA" file. We need the result of the normal Log-File, which logs the output of the script. So there should be two files with the same SensorIDs in that directory.

Best regards.


Apr, 2018 - Permalink

Hi,

I'm sorry, I misunderstood. But the other file (Result of Sensor 24156.txt) is empty.

Maybe this helps to localize the problem.

Thanks.

Best regards


Apr, 2018 - Permalink

Hi there,

You seem to transmit the following parameters which is no longer possible:

"1705@erlh196a" "`MATLAB`,`Image_Toolbox`,`Instr_Control_Toolbox`,`Optimization_Toolbox`,`Distrib_Computing_Toolbox`,`Signal_Toolbox"

So to use these parameters in the script, the parameters have to be split within the script and put afterwards into the array used by the script. So filling an array via the parameters has to be done manually now within the script by splitting the values after each ",".

best regards.


Apr, 2018 - Permalink

Hi,

thank you for your answer.

We tried even this by submitting:

-PortServer "1705@erlh196a" -Features1 "MATLAB" -Features2 "Image_Toolbox" -Features3 "Instr_Control_Toolbox" -Features4 "Optimization_Toolbox" -Features5 "Distrib_Computing_Toolbox" -Features6 "Signal_Toolbox"

But we have exact the same results - in both files.

Now you wrote that the script has to modified. Has anyone here in this knowledebase thread the same problem and already changed it. We would then like to use this standardized version and not develope anything on our own that differes from other developments.



Best regards


Apr, 2018 - Permalink

Hi there,

This can't work as the "Features2","Featured3" variable is not available in the script. Unfortunately, without the exact error message to check what the script exactly complains about, it is hard to find out what the issue actually is.

Best regards.


Apr, 2018 - Permalink

the output in result of sensor log file is

C:\Program Files (x86)\PRTG Network Monitor\custom sensors\EXEXML\PRTG_FlexLM.P S1 : A positional parameter cannot be found that accepts argument '64900CIV3D_F '. At line:1 char:137 + ... ll.Utility};&'C:\Program Files (x86)\PRTG Network Monitor\custom sens ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (:) [PRTG_FlexLM.PS1], Paramete rBindingException + FullyQualifiedErrorId : PositionalParameterNotFound,PRTG_FlexLM.PS1


Apr, 2018 - Permalink

Hi,

thank you for your response. We fixed this for now.

The message from Apr 17, 2018 6:58:17 PM further up in this thread didn't name that the script itsself must be changed. We thought that PRTG doesn't accept an array but builds one before sending the single variables to the powershell script. Anyway. It is fixed and works.

But as soon a new - more or less official - version of the script pops up here and then we'll take that. Only to be sure to have the same on which will be discussed the next time.

Thanks again.

Best regards cyberclaus62


Apr, 2018 - Permalink

I have modifyed the script and now it is working. Created a new sensor whitout any parameters

the flowing lines are added in the script

$portserver = "%portserveraddress%"

$features1 = Import-Csv -Delimiter ";" -Path "C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\1.csv"
$features = $features1.licfile

Apr, 2018 - Permalink

There is an easier way to specify multiple features: Pass them as comma-separated string, then split the string.

Thanks to WesleyVH for the first version! :-)

Adapted script:

# Quelle: https://helpdesk.paessler.com/en/support/solutions/articles/68662-flexlm-licensemonitor
# **********************************************************************************
# * SCRIPT INFORMATION                                                             *
# * ==================                                                             *
# *                                                                                *
# * NAME        : FlexLM_LicenseMonitor.ps1                                        *
# * DESCRIPTION : FlexLM_LicenseMonitor for PRTG (EXEXML Sensor)                   *
# *               Lookup the number of licenses used with lmutil                   *
# *                                                                                *
# * EXT. SOFT.  : - lmutil.exe                                                     *
# *                 --> Search for it in the FlexLM util folder                    *
# *                                                                                *
# **********************************************************************************

# **********************************************************************************
# * CHANGE LOG                                                                     *
# * ==========                                                                     *
# *                                                                                *
# * DATE          USER      DESCRIPTION                                            *
# * ------------------------------------------------------------------------------ *
# * 25.11.2017    tsch      Shows Total Values in the result                       *
# * 29.06.2018    uka       Pass Features as String, Split by comma                *
# *                                                                                *
# **********************************************************************************

# **********************************************************************************
# * USAGE                                                                          *
# * =====                                                                          *
# *                                                                                *
# * Script.ps1 -PortServer 1234@ServerName -Features "F1,F2, ..."                  *
# *                                                                                *
# * PortServer: Port and Servername to connect to the FlexLM License Manager       *
# * Features: Name of the License (Run the lmutil to see available features)       *
# *           separate multiple features by comma                                  *
# **********************************************************************************



# Parameters
# ==========

param(
   [Parameter(Mandatory=$True)]
   [string] $PortServer,

   [Parameter(Mandatory=$True)]
   [string] $FeaturesString
)



# Set static variables
# ====================

$LMUtilPath	= "C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\lmutil.exe"
$TempXMLFile	= "C:\Windows\Temp\LMUtil_" + $PortServer.Replace("@","") + ".xml"
$Features = $FeaturesString.Split(",")


# Set other variables
# ===================

$FeaturesTotalMax   = 0
$FeaturesTotalValue = 0



# Functions
# =========

function AddXMLResult
{
   param(
      [string] $Channel, 
      [string] $Val,
      [string] $Unit
   )

   $xmlWriter.WriteStartElement("Result")

   $xmlWriter.WriteStartElement("Channel")
   $xmlWriter.WriteString($Channel)
   $xmlWriter.WriteEndElement() # Close Channel

   $xmlWriter.WriteStartElement("Value")
   $xmlWriter.WriteString($Val)
   $xmlWriter.WriteEndElement() # Close Value

   switch($Unit) {
	"Lic" {
           $xmlWriter.WriteStartElement("CustomUnit");
           $xmlWriter.WriteString("Lic");
           $xmlWriter.WriteEndElement() # close CustomUnit
        }
        "Total" {
           $xmlWriter.WriteStartElement("CustomUnit");
           $xmlWriter.WriteString("Lic");
           $xmlWriter.WriteEndElement() # close CustomUnit
        }
	"Percent" {
           $xmlWriter.WriteStartElement("Unit");
           $xmlWriter.WriteString("Percent");
           $xmlWriter.WriteEndElement() # close Unit
        }
   }

   $xmlWriter.WriteEndElement() # close Result
}



# Start Script
# ============


# Open XML Doc
# ------------

$xmlWriter = New-Object System.Xml.XmlTextWriter($TempXMLFile,$null)
$xmlWriter.Formatting = "Indented"
$xmlWriter.Indentation = "2"
$xmlWriter.WriteStartDocument()
$xmlWriter.WriteStartElement("PRTG")


# Lookup Features
# ---------------

ForEach ($Feature in $Features) { 
   $ReadLicense  = &$LMUtilPath lmstat -a -c $PortServer | Select-String -Pattern ("Users of " + $Feature + ":")

   $FindNumbers  = [RegEx]"\b [0-9]+ \b"
   $ValuesFound  = $FindNumbers.Matches($ReadLicense)

   $FeatureMax   = $ValuesFound[0].Value.Trim()
   $FeatureValue = $ValuesFound[1].Value.Trim()

   $FeaturesTotalMax = $FeaturesTotalMax + $FeatureMax
   $FeaturesTotalValue = $FeaturesTotalValue + $FeatureValue

   $FeaturePerc  = [math]::Round($FeatureValue / $FeatureMax * 100)


   # Provide License Name When Known
   # -------------------------------

   $FeatureName  = $Feature
   switch($Feature) {
	"dwgeditor" { $FeatureName = "DWG Editor"}
	"solidworks" { $FeatureName = "SolidWorks Standard"}
	"swofficepro" { $FeatureName = "SolidWorks Professional"}
	"swofficepremium" { $FeatureName = "SolidWorks Premium"}
	"swepdm_viewer" { $FeatureName = "PDM Viewer"}
	"swepdm_cadeditorandweb" { $FeatureName = "PDM Editor"}
	"swepdm_contributorandweb" { $FeatureName = "PDM Contributor"}
   }


   # Add to XML
   # ----------

   AddXMLResult $FeatureName $FeatureValue "Lic"
   AddXMLResult ($FeatureName + " Total") $FeatureMax "Total"
   AddXMLResult ($FeatureName + " Perc") $FeaturePerc "Percent"
}


# Calc totals & Add to XML
# ------------------------

$FeaturesTotalPerc = [math]::Round($FeaturesTotalValue / $FeaturesTotalMax * 100)

AddXMLResult "Total Licenses Used" $FeaturesTotalValue "Lic"
AddXMLResult "Total Licenses" $FeaturesTotalMax "Total"
AddXMLResult "Total Licenses Used Perc" $FeaturesTotalPerc "Percent"



# Close XML Doc
# -------------

$xmlWriter.WriteEndElement() # Close root element (PRTG)
$xmlWriter.WriteEndDocument()
$xmlWriter.Flush()
$xmlWriter.Close()


# Write-Output XML Doc
# --------------------
Write-Output (Get-Content $TempXMLFile)

Jun, 2018 - Permalink

If i Run Powershell Script with just LIC_FlexLM.ps1 then i get this: Supply values for the following parameters: PortServer: "i type my @server" (no port, it does not work with port and i must use @) and then Features[0]: 86445ACD_2016_0F Features[1]:

Result:

<?xml version="1.0"?>
<PRTG>
  <Result>
    <Channel>Autodesk AutoCAD 2016</Channel>
    <Value>33</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Autodesk AutoCAD 2016 Total</Channel>
    <Value>41</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Autodesk AutoCAD 2016 Perc</Channel>
    <Value>80</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>Total Licenses Used</Channel>
    <Value>33</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Total Licenses</Channel>
    <Value>41</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Total Licenses Used Perc</Channel>
    <Value>80</Value>
    <Unit>Percent</Unit>
  </Result>
</PRTG>

*********

And then again if i start it with

.\LIC_FlexLM.ps1 -Features 86497INVPROSA_2016_0F

i get

cmdlet LIC_FlexLM.ps1 at command pipeline position 1
Supply values for the following parameters:
PortServer: "i Type my server @name" (no port, it does not work with port and i must use @)

Result:
<?xml version="1.0"?>
<PRTG>
  <Result>
    <Channel>Autodesk Inventor Professional 2016</Channel>
    <Value>6</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Autodesk Inventor Professional 2016 Total</Channel>
    <Value>31</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Autodesk Inventor Professional 2016 Perc</Channel>
    <Value>19</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>Total Licenses Used</Channel>
    <Value>6</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Total Licenses</Channel>
    <Value>31</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Total Licenses Used Perc</Channel>
    <Value>19</Value>
    <Unit>Percent</Unit>
  </Result>
</PRTG>

But if i Start with:

.\LIC_FlexLM.ps1 -PortServer "my server (no port, just servername)" -Features 86497INVPROSA_2016_0F

i get:

Exception calling "Matches" with "1" argument(s): "Value cannot be null.
Parameter name: input"
At C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\LIC_FlexLM.ps1:131 char:4
+    $ValuesFound  = $FindNumbers.Matches($ReadLicense)
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentNullException
 
Cannot index into a null array.
At C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\LIC_FlexLM.ps1:133 char:4
+    $FeatureMax   = $ValuesFound[0].Value.Trim()
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray
 
Cannot index into a null array.
At C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\LIC_FlexLM.ps1:134 char:4
+    $FeatureValue = $ValuesFound[1].Value.Trim()
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray
 
Attempted to divide by zero.
At C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\LIC_FlexLM.ps1:139 char:4
+    $FeaturePerc  = [math]::Round($FeatureValue / $FeatureMax * 100)
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException
 
Attempted to divide by zero.
At C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\LIC_FlexLM.ps1:173 char:1
+ $FeaturesTotalPerc = [math]::Round($FeaturesTotalValue / $FeaturesTot ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException
 
<?xml version="1.0"?>
<PRTG>
  <Result>
    <Channel>Autodesk Inventor Professional 2016</Channel>
    <Value />
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Autodesk Inventor Professional 2016 Total</Channel>
    <Value />
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Autodesk Inventor Professional 2016 Perc</Channel>
    <Value />
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>Total Licenses Used</Channel>
    <Value>0</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Total Licenses</Channel>
    <Value>0</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Total Licenses Used Perc</Channel>
    <Value />
    <Unit>Percent</Unit>
  </Result>
</PRTG>

Why does it not work if i use my Server Name in Command line and it works when i type it manually? Bare in mind i type my Server name just name no port@name, if i use port@name it does not work


Jan, 2019 - Permalink

This is brilliant. I'm sure I looked for something like this over a year ago, but clearly didn't find this topic!

The script works perfectly for us and I plan to build a dashboard we can show in our studio so end users can see how many floating licenses are in use. However, what we would find really useful is to have the list of usernames that currently have a license. I see that usernames are shown when running

 lmutil lmstat -a -c <license>

but not sure where to begin editing the script.

Can anyone help?


Feb, 2021 - Permalink

Older thread, but replying anyway to keep it in the same place. First time trying to setup a custom sensor for this, so definitely a chance I'm not setting it up correctly. I did use the EXE/Script Advanced option, and the ps1 file is in the \Custom Sensors\EXEXML directory.

I am using the version that uka had modified, and it runs fine from powershell on the server itself passing port@servername and then the comma separated string of our features: cae_cwadvpro,camstd,draftsightpremium,solidworks,swofficepro,swofficepremium,swepdm_processor,visustd

PS C:\Source> C:\Source\FlexLM_LicenseMonitor.ps1
cmdlet FlexLM_LicenseMonitor.ps1 at command pipeline position 1
Supply values for the following parameters:
PortServer: port@servername
FeaturesString: cae_cwadvpro,camstd,draftsightpremium,solidworks,swofficepro,swofficepremium,swepdm_processor,visustd
<?xml version="1.0"?>
<PRTG>
  <Result>
    <Channel>Solidworks Simulation Premium</Channel>
    <Value>0</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Solidworks Simulation Premium Total</Channel>
    <Value>1</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Solidworks Simulation Premium Perc</Channel>
    <Value>0</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>Solidworks CAM Standard</Channel>
    <Value>5</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Solidworks CAM Standard Total</Channel>
    <Value>22</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Solidworks CAM Standard Perc</Channel>
    <Value>23</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>Draftsight Enterprise</Channel>
    <Value>0</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Draftsight Enterprise Total</Channel>
    <Value>45</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Draftsight Enterprise Perc</Channel>
    <Value>0</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>SolidWorks Standard</Channel>
    <Value>10</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>SolidWorks Standard Total</Channel>
    <Value>22</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>SolidWorks Standard Perc</Channel>
    <Value>45</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>SolidWorks Professional</Channel>
    <Value>3</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>SolidWorks Professional Total</Channel>
    <Value>19</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>SolidWorks Professional Perc</Channel>
    <Value>16</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>SolidWorks Premium</Channel>
    <Value>0</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>SolidWorks Premium Total</Channel>
    <Value>3</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>SolidWorks Premium Perc</Channel>
    <Value>0</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>PDM Professional</Channel>
    <Value>10</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>PDM Professional Total</Channel>
    <Value>25</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>PDM Professional Perc</Channel>
    <Value>40</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>Solidworks Visualize Standard</Channel>
    <Value>0</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Solidworks Visualize Standard Total</Channel>
    <Value>22</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Solidworks Visualize Standard Perc</Channel>
    <Value>0</Value>
    <Unit>Percent</Unit>
  </Result>
  <Result>
    <Channel>Total Licenses Used</Channel>
    <Value>28</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Total Licenses</Channel>
    <Value>159</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Total Licenses Used Perc</Channel>
    <Value>18</Value>
    <Unit>Percent</Unit>
  </Result>
</PRTG>

However if I try to run it in PRTG I get the PE233 XML JSON error. I don't see any logs related to the sensor that I can find. Any ideas that I can use to troubleshoot?


Mar, 2022 - Permalink

Hello there,

In tab Settings of your sensor you can enable the option Store Result to get logs about the sensor. This will show what your script returns to PRTG. Please note that the result need to be following and nothing from above:

<?xml version="1.0"?>
<PRTG>
  <Result>
    <Channel>Solidworks Simulation Premium</Channel>
    <Value>0</Value>
    <CustomUnit>Lic</CustomUnit>
  </Result>
  <Result>
    <Channel>Solidworks Simulation Premium Total</Channel>
    <Value>1<
.
.
.
.

Kind regards

Felix Wiesneth - Team Tech Support


Mar, 2022 - Permalink

I wasn't satified with the above script, because all it does is tell you wether or not you have a valid licence and while that might be useful for big companies, I find that in smaller companies i would like to know when the licences are going to expire in advance.

so instead of just complaining on a forum, i cooked up the following (use as advanced exe sensor) that auto-populates with the features served by flexLM and their expiration date from lmutil lmstat -i.

Some notes:

  • lmutil lmstat -i shows information written in plain text in the licence file. as far as i can tell, the expiration date returned by this is under no obligation to be the actual expiration date of the licence. Vendors typically do generate their licence files with the correct dates though.
  • Edit lines 99 and 100 if you want to change the alert and warning settings.
  • Cadence has some wierd stuff in their licence files, and i ignore it by removing all features that expired 1-jan-0. this may or may not interfere with what you want. if you have infinite duration licences (why are you monitoring them?), they might not show up. edit lines 80-86 to fix.
#Flexlm/flexera (lmutil) licence expiry sensor for PRTG Network Monitor
#usage: use as advanced exe sensor by placing this file in C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML
#Parameters: -PortServer : port and server for the licence manager (required)
#Example Parameter: -PortServer 5280@licence-server-1.example.com

#Author: o.senn@pbsco.fr / https://poggers.website

param(
   [Parameter(Mandatory=$True)]
   [string] $PortServer
)

# Set lmutil path

$LMUtilPath	= "C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML\lmutil.exe"
#helper func
#https://stackoverflow.com/questions/45357739/how-to-parse-pipe-cmd-line-output-using-powershell-to-an-object
Function Select-Column {
    [cmdletbinding(PositionalBinding=$False)]
    param(
      [Parameter(ValueFromPipeline, Mandatory)]
      $InputObject,
  
      [Parameter(Mandatory, Position=0)]
      [int[]] $Index,
  
      [Parameter(Position=1)]
      [int] $RequiredCount,
  
      [Parameter(Position=2)]
      [string] $OutFieldSeparator = "`t"
  
    )
  
    process {
      if (($fields = -split $InputObject) -and ($RequiredCount -eq 0 -or $RequiredCount -eq $fields.Count)) {
        $fields[$Index] -join $OutFieldSeparator
      }
    }
  
  }






$json = [PSCustomObject]@{
    prtg=[PSCustomObject]@{
        result=@()
        text=""
    }
}

#get lmstat output, trim garbage header

$output = & $LMUtilPath lmstat -c $PortServer -i  |Select-Object -skip 9

#first column is feature name, fourth is expiry date
#columns: 0: feature name, 1: software version, 2: # of licences (issued or not) 3: expiry date, 4: Vendor daemon
$features = $output | Select-Column -Index 0
$exps = $output | Select-Column -Index 3


#vars
$index = 0

$minexp = 9999

#dynamically add a channel for each feature returned by lmstat

foreach ($feature in $features) {

    #Cadence special case:
    #cadence holds info about the licence as features that expired 1 jan 0, so it would show as always expired. 
    #for ex: 
    #Feature                         Version     #licenses    Expires      Vendor
    #LicFileVersion                  2012.0       1           1-jan-0      cdslmd

    if (-not ($exps[$index] -eq "1-jan-0")) {
        $timeleft = New-TimeSpan -Start $(Get-Date) -End $exps[$index]| Select-Object -ExpandProperty Days
        $index ++
    }else {
        $index ++
        continue
    }

    #get soonest expiry for sensor message
    $minexp = [math]::Min($timeleft,$minexp)

    #add channel entry

    $json.prtg.result += @([PSCustomObject]@{
        channel="$feature"
        value= "$timeleft"
        unit="custom"
        customunit="days before expiring"
        limitmode="1"
        limitminwarning="30"
        limitminerror="7"
    })
    
}
$json.prtg.text = "Expiring in $minexp days"

#convert data to json for prtg and just print it to stdout
#ensure UTF8 encoding because powershell is dumb sometimes

$enc =  [System.Text.Encoding]::UTF8.GetBytes($($json |Select-Object -Property * | ConvertTo-Json -Depth 100))
[system.Text.Encoding]::UTF8.GetString( $enc )



Apr, 2022 - Permalink

Hi, Is there a way, the script detects all features of a license automatically? I likely would use this script, but we have different customers, with differenent features. A license most contains over 30 different features and up and it will be a mess to configure this for each customer or license change.

Regards


Oct, 2022 - Permalink