PS-NCentral.psm1
## PowerShell Module for N-Central(c) by Solarwinds ## ## Version : 1.2 ## Author : Adriaan Sluis (as@tosch.nl) ## ## !Still some Work In Progress! ## ## Provides a PowerShell Interface for N-Central(c) ## Uses the SOAP-API of N-Central(c) by Solarwinds ## Completely written in PowerShell for easy reference/analysis. ## ##Copyright 2021 Tosch Automatisering ## ##Licensed under the Apache License, Version 2.0 (the "License"); ##you may not use this file except in compliance with the License. ##You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ##Unless required by applicable law or agreed to in writing, software ##distributed under the License is distributed on an "AS IS" BASIS, ##WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ##See the License for the specific language governing permissions and ##limitations under the License. ## ## Change log ## ## v1.2 Feb 24, 2021 ## -Made PowerShell 7 compatible by removing usage of WebServiceProxy. ## -Sorting CustomProperty-columns by default (NoSort/UnSorted Option) ## -JWT-option in New-NCentralConnection ## ## #Region Classes and Generic Functions using namespace System.Net Class NCentral_Connection { ## Using the Interface ServerEI2_PortType ## See documentation @: ## http://mothership.n-able.com/dms/javadoc_ei2/com/nable/nobj/ei2/ServerEI2_PortType.html #Region Properties ## TODO - Enum-lists for StatusIDs, ErrorIDs, ... ## TODO - Cleanup WebProxy code (whole module) ## Initialize the API-specific values (as static). ## No separate NameSpace needed because of Class-enclosure. Instance NameSpace available as Property. #static hidden [String]$NWSNameSpace = "NCentral" + ([guid]::NewGuid()).ToString().Substring(25) static hidden [String]$SoapURL = "/dms2/services2/ServerEI2?wsdl" ## Create Properties [String]$ConnectionURL ## Server FQDN [String]$BindingURL ## Full SOAP-path [String]$AllProtocols = 'tls12,tls13' ## Https encryption [Boolean]$IsConnected = $false ## Connection Status hidden [PSCredential]$Creds = $null ## Encrypted Credentials hidden [Object]$Connection ## Store Server Session (WebServiceProxy) hidden [Object]$NameSpace ## For accessing API-Class Objects (WebServiceProxy) [int]$RequestTimeOut = 100 ## Default timeout in Seconds hidden [Object]$ConnectedVersion ## For storing full VersionInfoGet-data [String]$NCVersion ## The UI-version of the connected server [int]$DefaultCustomerID ## Used when no CustomerID is supplied in most device-commands [Object]$Error ## Last known Error ## Create a general Key/Value Pair. Will be casted at use. Skipped in most methods for non-reuseablity. ## Integrated (available in session only): $KeyPair = New-Object -TypeName ($NameSpace + '.tKeyPair') #hidden $KeyPair = [PSObject]@{Key=''; Value='';} ## Create Key/Value Pairs container(Array). hidden [Array]$KeyPairs = @() ## Defaults and ValidationLists ## Documented under CustomerModify. Supports decision between Customer- and Organization-properties. hidden [Array]$CustomerValidation = @('zip/postalcode','street1','street2','city','state/province','telephone','country','externalid','externalid2','firstname','lastname','title','department','contact_telephone','ext','email','licensetype') ## Hold data-objects returning from API-Call or for reference. hidden [Array]$rc #Returned Raw Collection of NCentral-Data. hidden [Object]$CustomerData #Caching of CustomerData for quick reference ## Work In Progress #$tCreds ## Testing / Debugging only hidden $Testvar # $Testvar = $this.GetType().name #EndRegion #Region Constructors #Base Constructors ## Using ConstructorHelper for chaining. NCentral_Connection(){ Try{ ## [ValidatePattern('^server\d{1,4}$')] $ServerFQDN = Read-Host "Enter the fqdn of the N-Central Server" } Catch{ Write-Host "Connection Aborted" Break } $PSCreds = Get-Credential -Message "Enter NCentral API-User credentials" $this.ConstructorHelper($ServerFQDN,$PSCreds) } NCentral_Connection([String]$ServerFQDN){ $PSCreds = Get-Credential -Message "Enter NCentral API-User credentials" $this.ConstructorHelper($ServerFQDN,$PSCreds) } NCentral_Connection([String]$ServerFQDN,[String]$JWT){ $SecJWT = (ConvertTo-SecureString $JWT -AsPlainText -Force) $PSCreds = New-Object PSCredential ("_JWT", $SecJWT) $this.ConstructorHelper($ServerFQDN,$PSCreds) } NCentral_Connection([String]$ServerFQDN,[PSCredential]$PSCreds){ $this.ConstructorHelper($ServerFQDN,$PSCreds) } hidden ConstructorHelper([String]$ServerFQDN,[PSCredential]$Credentials){ ## Constructor Chaining not Standard in PowerShell. Needs a Helper-Method. ## ## ToDo: ValidatePattern for $ServerFQDN If (!$ServerFQDN){ Write-Host "Invalid ServerFQDN given." Break } If (!$Credentials){ Write-Host "No Credentials given." Break } ## Construct Session-parameters. ## Place in Class-Property for later reference. $this.ConnectionURL = $ServerFQDN $this.Creds = $Credentials #Write-Debug "Connecting to $this.ConnectionURL." $this.bindingURL = "https://" + $this.ConnectionURL + [NCentral_Connection]::SoapURL ## Initiate the session to the NCentral-server. $this.Connect() } #EndRegion #Region Methods # ## Features # ## Returns all data as Object-collections to allow pipelines. # ## Mimic the names of the API-method where possible. # ## Supports Synchronous Requests only (for now). # ## NO 'Dangerous' API's are implemented (Delete/Remove). # ## # ## To Do # ## TODO - Check for $this.IsConnected before execution. # ## TODO - General Error-handling + customized throws. # ## TODO - Additional Add/Set-methods # ## TODO - Progress indicator (Write-Progress) # ## TODO - DeviceAssetInfoExportWithSettings options (Exclude/Include) # ## TODO - Error on AccessGroupGet # ## TODO - Async processing # ## #Region ClassSupport [void]Connect(){ ## Clear existing connection (if any) $this.Connection = $null $this.IsConnected = $false Try{ ## Secure communications [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} #$AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12,Tls13' # $AllProtocols = [System.Net.SecurityProtocolType]'Tls12,Tls13' # [System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]$this.AllProtocols ## Connect to Soap-service. Use ErrorAction to enable Catching. ## Explicit Namespace not needed at creation when used inside a Class. ## Credentials needed for NCentral class-access/queries. Not checked for setting connection. #$this.Connection = New-Webserviceproxy $this.bindingURL -credential $this.creds -Namespace [NCentral_Connection]::NWSNameSpace -ErrorAction Stop #$this.Connection = New-Webserviceproxy $this.bindingURL -credential $this.creds -ErrorAction Stop #$this.Connection = New-Webserviceproxy $this.bindingURL -ErrorAction Stop } Catch [System.Net.WebException]{ # Write-Host ([string]::Format("Error : {0}", $_.Exception.Message)) $this.Error = $_ $this.ErrorHandler() } ## Connection Properties/Methods #Write-host $this.connection | Get-Member -Force ## Connecting agent info. Only available after succesful connection with Credentials. # Write-Host $this.connection.useragent ## API-Class Properties/Methods base #$this.NameSpace = $this.connection.GetType().namespace #Write-host $this.NameSpace| Get-Member -Force ## Determine NCentral Version ## Errors when using New-Webserviceproxy. DataType Error, Not CLS-compliant. ## Use plain ei2-Envelope and Invoke-RestMethod ## Use versionInfoGet, Includes checking SOAP-connection ## No credentials needed (yet). $VersionEnvelope = @" <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ei2="http://ei2.nobj.nable.com/"> <soap:Header/> <soap:Body> <ei2:versionInfoGet/> </soap:Body> </soap:Envelope> "@ Try{ $this.ConnectedVersion = (Invoke-RestMethod -Uri $this.BindingURL -body $VersionEnvelope -Method POST -TimeoutSec $this.RequestTimeOut). envelope.body.versionInfoGetResponse.return | Select-Object key,value } # Catch [System.Net.WebException]{ # $this.Error = $_ # $this.ErrorHandler() # } Catch { $this.Error = $_ $this.ErrorHandler() } ## Extract NCental UI version from returned data $this.NCVersion = ($this.Connectedversion | Where-Object {$_.key -eq "Installation: Deployment Product Version"} ).value ## TODO Make valid check on connection-error (incl. Try/Catch) ## Now checking on data-retrieval. # if ($this.Connection){ # if ($this.Connection.useragent){ if ($this.NCVersion){ $this.IsConnected = $true } } hidden [Object]NCWebRequest([String]$APIMethod,[String]$APIData){ Return $this.NCWebRequest($APIMethod,$APIData,'') } hidden [Object]NCWebRequest([String]$APIMethod,[String]$APIData,$Version){ ## Basic NCentral SOAP-request, invoking Credentials. ## Optionally invoke version (specific requests) #version - Determines whether MSP N-Central or PSA credentials are to be used. In the case of PSA credentials the number indicates the type of PSA integration setup. # "0.0" indicates that MSP N-central credentials are to be used. # "1.0" indicates that a ConnectWise PSA integration is to be used. # "2.0" indicates that an Autotask PSA integration is to be used. # "3.0" indicates than a Tigerpaw PSA integration is to be used. $VersionKey = '' If($Version){ $VersionKey = (" <ei2:version>{0}</ei2:version>" -f $Version) } ## Build SoapRequest (must be left-lined for @") $MySoapRequest =( @" <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ei2="http://ei2.nobj.nable.com/"> <soap:Header/> <soap:Body> <ei2:{0}>{4} <ei2:username>{1}</ei2:username> <ei2:password>{2}</ei2:password>{3} </ei2:{0}> </soap:Body> </soap:Envelope> "@ -f $APIMethod, $this.PlainUser(), $this.PlainPass(), $APIData, $VersionKey) #Write-Host $MySoapRequest ## Debug purpose $FullReponse = $null Try{ $FullReponse = Invoke-RestMethod -Uri $this.bindingURL -body $MySoapRequest -Method POST } # Catch [System.Net.WebException]{ # Write-Host ([string]::Format("Error : {0}", $_.Exception.Message)) # $this.Error = $_ # $this.ErrorHandler() # } Catch { Write-Host ([string]::Format("Error : {0}", $_.Exception.Message)) $this.Error = $_ $this.ErrorHandler() } #$ReturnProperty = $$APIMethod + "Response" $ReturnClass = $FullReponse.envelope.body | Get-Member -MemberType Property $ReturnProperty = $ReturnClass[0].Name Return $FullReponse.envelope.body.$ReturnProperty.return } hidden [Object]GetNCData([String]$APIMethod,[String]$Username,[String]$PassOrJWT,$KeyPairs){ ## Overload for Backward compatibility Return $this.GetNCData($APIMethod,$KeyPairs,'') } hidden [Object]GetNCData([String]$APIMethod,[Array]$KeyPairs){ Return $this.GetNCData($APIMethod,$KeyPairs,'') } hidden [Object]GetNCData([String]$APIMethod,[Array]$KeyPairs,[String]$Version){ ## Process Keys to Request-settings $MyKeys="" ForEach($KeyPair in $KeyPairs){ $MyKeys = $MyKeys + (" <ei2:settings> <ei2:key>{0}</ei2:key> <ei2:value>{1}</ei2:value> </ei2:settings>" -f ($KeyPair.Key),($KeyPair.Value)) } ## Invoke request Return $this.NCWebRequest($APIMethod, $MyKeys,$Version) } hidden [Object]GetNCDataOP([String]$APIMethod,$CustomerIDs,[Boolean]$ReverseOrder){ ## Get OrganizationProperties for (optional) specified customerIDs ## Process Array $MyKeys="" ForEach($CustomerID in $CustomerIDs){ $MyKeys = $MyKeys + (" <ei2:customerIds>{0}</ei2:customerIds>" -f $CustomerID) } ## Add mandatory options $MyKeys = $MyKeys + (" <ei2:reverseOrder>{0}</ei2:reverseOrder>" -f ($ReverseOrder.ToString()).ToLower()) ## Invoke request Return $this.NCWebRequest($APIMethod, $MyKeys) } hidden [Object]GetNCDataDP([String]$APIMethod,$DeviceIDs,$DeviceNames,$FilterIDs,$FilterNames,[Boolean]$ReverseOrder){ ## Get DeviceProperties for (optional) filtered devices ## Process Arrays $MyKeys="" ForEach($DeviceID in $DeviceIDs){ $MyKeys = $MyKeys + (" <ei2:deviceIDs>{0}</ei2:deviceIDs>" -f $DeviceID) } ForEach($DeviceName in $DeviceNames){ $MyKeys = $MyKeys + (" <ei2:deviceNames>{0}</ei2:deviceNames>" -f $DeviceName) } ForEach($FilterID in $FilterIDs){ $MyKeys = $MyKeys + (" <ei2:filterIDs>{0}</ei2:filterIDs>" -f $FilterID) } ForEach($FilterName in $FilterNames){ $MyKeys = $MyKeys + (" <ei2:filterNames>{0}</ei2:filterNames>" -f $FilterName) } $MyKeys = $MyKeys + (" <ei2:reverseOrder>{0}</ei2:reverseOrder>" -f ($ReverseOrder.ToString()).ToLower()) ## Invoke request Return $this.NCWebRequest($APIMethod, $MyKeys) } hidden [Object]SetNCDataOP([String]$APIMethod,$OrganizationID,$OrganizationPropertyID,[String]$OrganizationPropertyValue){ ## Set a single OrganizationProperty ## Process Arrays $MyKeys=(" <ei2:organizationProperties> <ei2:customerId>{0}</ei2:customerId> <ei2:properties> <ei2:propertyId>{1}</ei2:propertyId> <ei2:value>{2}</ei2:value> </ei2:properties> </ei2:organizationProperties>" -f $OrganizationID,$OrganizationPropertyID,$OrganizationPropertyValue) ## Invoke request Return $this.NCWebRequest($APIMethod, $MyKeys) } hidden [Object]SetNCDataDP([String]$APIMethod,$DeviceID,$DevicePropertyID,[String]$DevicePropertyValue){ ## Set a single DeviceProperty ## Process Arrays $MyKeys=(" <ei2:deviceProperties> <ei2:deviceID>{0}</ei2:deviceID> <ei2:properties> <ei2:devicePropertyID>{1}</ei2:devicePropertyID> <ei2:value>{2}</ei2:value> </ei2:properties> </ei2:deviceProperties>" -f $DeviceID, $DevicePropertyID, $DevicePropertyValue) ## Invoke request Return $this.NCWebRequest($APIMethod, $MyKeys) } hidden [String]PlainUser(){ $CredUser = $this.Creds.GetNetworkCredential().UserName If ($CredUser -eq '_JWT'){ Return $null } Else{ Return $CredUser } } hidden [String]PlainPass(){ Return $this.Creds.GetNetworkCredential().Password } [void]ErrorHandler(){ $this.ErrorHandler($this.Error) } [void]ErrorHandler($ErrorObject){ #Write-Host$ErrorObject.Exception|Format-List -Force #Write-Host ($ErrorObject.Exception.GetType().FullName) # $global:ErrObj = $ErrorObject # Write-Host ($ErrorObject.Exception.Message) Write-Host ($ErrorObject.ErrorDetails.Message) # Known Errors List: # Connection-error (https): There was an error downloading .. # 1012 - Thrown when mandatory settings are not present in "settings". # 2001 - Required parameter is null - Thrown when null values are entered as inputs. # 2001 - Unsupported version - Thrown when a version not specified above is entered as input. # 2001 - Thrown when a bad username-password combination is input, or no PSA integration has been set up. # 2100 - Thrown when invalid MSP N-central credentials are input. # 2100 - Thrown when MSP-N-central credentials with MFA are used. # 3010 - Maximum number of users reached. # 3012 - Specified email address is already assigned to another user. # 3014 - Creation of a user for the root customer (CustomerID 1) is not permitted. # 3014 - When adding a user, must not be an LDAP user. # 3022 - Customer/Site already exists. # 3026 - Customer name length has exceeded 120 characters. # 4000 - SessionID not found or has expired. # 5000 - An unexpected exception occurred. # 5000 - Query failed. # 5000 - javax.validation.ValidationException: Unable to validate UI session # 9910 - Service Organization already exists. Break } [PSObject]ProcessData1([Array]$InArray){ ## Most Common PairClass is Info or Item. ## Fill if not specified. # Hard (Pre-)Fill $PairClass = "info" ## Base on found Array-Properties if possible If($InArray.Count -gt 0){ $PairClasses = $InArray[0] | Get-member -MemberType Property $PairClass = $PairClasses[0].Name } Return $this.ProcessData1($InArray,$PairClass) } [PSObject]ProcessData1([Array]$InArray,[String]$PairClass){ ## Received Dataset KeyPairs 2 List/Columns $OutObjects = @() if ($InArray){ foreach ($InObject in $InArray) { # $ThisObject = New-Object PSObject ## In this routine the object is created at start. Properties are added with values. $Props = @{} ## In this routine the object is created at the end. Properties from a list. ## Add a Reference-Column at Object-Level If ($PairClass -eq "Properties"){ ## CustomerLink if Available if(Get-Member -inputobject $InObject -name "CustomerID"){ # $ThisObject | Add-Member -MemberType NoteProperty -Name 'CustomerID' -Value $InObject.CustomerID -Force $Props.add('CustomerID',$InObject.CustomerID) } ## DeviceLink if Available if(Get-Member -inputobject $InObject -name "DeviceID"){ # $ThisObject | Add-Member -MemberType NoteProperty -Name 'DeviceID' -Value $InObject.DeviceID -Force $Props.add('DeviceID',$InObject.DeviceID) } } ## Convert all (remaining) keypairs to Properties foreach ($item in $InObject.$PairClass) { ## Cleanup the Key and/or Value before usage. If ($PairClass -eq "Properties"){ $Header = $item.label } Else{ If($item.key.split(".")[0] -eq 'asset'){ ##Should use ProcessData2 (ToDo) $Header = $item.key } Else{ $Header = $item.key.split(".")[1] } } ## Ensure a Flat Value If ($item.value -is [Array]){ $DataValue = $item.Value[0] } Else{ $DataValue = $item.Value } ## Now add the Key/Value pairs. # $ThisObject | Add-Member -MemberType NoteProperty -Name $Header -Value $DataValue -Force # if a key is found that already exists in the hashtable if ($Props.ContainsKey($Header)) { # either overwrite the value 'Last-One-Wins' # or do nothing 'First-One-Wins' #if ($this.allowOverwrite) { $Props[$Header] = $DataValue } } else { $Props[$Header] = $DataValue } # $Props.add($Header,$DataValue) } $ThisObject = New-Object -TypeName PSObject -Property $Props #Alternative option ## Add the Object to the list $OutObjects += $ThisObject } } ## Return the list of Objects Return $OutObjects # $OutObjects # Write-Output $OutObjects } [PSObject]ProcessData2([Array]$InArray){ ## Most Common PairClass is Info or Item. ## Fill if not specified. # Hard (Pre-)Fill $PairClass = "info" ## Base on found Array-Properties if possible If($InArray.Count -gt 0){ $PairClasses = $InArray[0] | Get-member -MemberType Property $PairClass = $PairClasses[0].Name } Return $this.ProcessData2($InArray,$PairClass) } [PSObject]ProcessData2([Array]$InArray,[String]$PairClass){ ## Received Dataset KeyPairs 2 Object ## Key-structure: asset.service.caption.28 ## ## Only One Asset at the time can be processed. $OutObjects = @() $SortedInfo = @() $Props = @{} $OldArrayID = "" [Array]$ArrayProperty = $null $OldArrayItemID = "" [HashTable]$ArrayItemProperty = @{} if ($InArray){ ## Get the DeviceId to repeat in every Object-Property $CurrentDeviceID = ($InArray.$PairClass | Where-Object {$_.key -eq 'asset.device.deviceid'} | Select-Object value).value Write-Debug "DeviceObject CurrentDeviceID: $CurrentDeviceID" ## Sort for processing. Column 2,4 $SortedInfo = $InArray.$PairClass | Sort-Object @{Expression={$_.key.split(".")[1] + $_.key.split(".")[3]}; Descending=$false} $Props = @{} ## In this routine the object is created at the end. Properties from this list. ## Process the Keypairs ForEach ($InObject in $SortedInfo) { ## Convert the keypairs to Properties ForEach ($item in $InObject) { ## Add property direct if column4 does not exist ## --> Changed to only asset.device items. Header changed accordingly. ## Build and Add Array if int # If(($item.key.split(".")[3]) -lt 0){ If(($item.key.split(".")[1]) -eq 'device'){ ## Add property as a Non-Array. Write-Debug $item.key # $Header = ($item.key.split(".")[1])+"."+($item.key.split(".")[2]) $Header = $item.key.split(".")[2] $DataValue = $item.Value Write-Debug $Header":"$DataValue $Props[$Header] = $DataValue } Else{ ## Add property as an Array. ## Make an object-Array Before Adding ## Key-structure: asset.service.caption.28 ## Outer-loop differenting on column 2 MainObject Array-Property ## Inner-loop differenting on column 4 ## ObjectItem is column 2.4 (easysplit) Array-ItemID ## ObjectHeaders are Column 3 Array-Item-PropertyHeader ## Create the Property ItemID from the Key-Name $ArrayItemId = ($item.key.split(".")[1])+"."+($item.key.split(".")[3]) ## Is this a new Array-Item? If($ArrayItemId -ne $OldArrayItemID){ ## Add the current object to the array-property and start over If($OldArrayItemID -ne ""){ Write-Debug "ArrayItemId = $ArrayItemId" $ArrayItem = New-Object -TypeName PSObject -Property $ArrayItemProperty $ArrayProperty += $ArrayItem } $ArrayItemProperty = @{} $OldArrayItemID = $ArrayItemId ## Add an unique ID-Column and the DeviceID to the item. $ArrayItemProperty["ItemId"]=$ArrayItemId # $ArrayItemProperty.add("ItemId", $ArrayItemId) $ArrayItemProperty["DeviceId"]=$CurrentDeviceID } ## Create the Main Property Name from the Key-Name $ArrayId = ($item.key.split(".")[1]) ## Is this a new Array? If($ArrayId -ne $OldArrayID){ ## Add the current array to the main object and start a new one If($OldArrayID -ne ""){ Write-Debug "ArrayId = $ArrayId" $Props[$OldArrayId] = $ArrayProperty } $ArrayProperty = $null $OldArrayID = $ArrayId } ## Add the current item to the array-item $Header2 = ($item.key.split(".")[2]) $DataValue2 = $item.Value Write-Debug "Header2 = $Header2" Write-Debug "DataValue2 = $DataValue2" $ArrayItemProperty[$Header2]=$DataValue2 } ## End of item-loop } ## End of Keypairs-loop } ## Debug # $this.TestVar = $Props $ThisObject = New-Object -TypeName PSObject -Property $Props #Alternative option ## Add the Object to the list $OutObjects += $ThisObject ## End of Input-check } ## Return the list of Objects Return $OutObjects } #EndRegion #Region CustomerData [Object]ActiveIssuesList([Int]$ParentID){ # No SearchBy-string adds an empty String. return $this.ActiveIssuesList($ParentID,"") } [Object]ActiveIssuesList([Int]$ParentID,[String]$IssueSearchBy){ ## Refresh / Clean KeyPair-container. $this.KeyPairs = @() ## Add parameters as KeyPairs. $KeyPair1 = [PSObject]@{Key='customerID'; Value=$ParentID;} $this.KeyPairs += $KeyPair1 ## Optional keypair(s) for activeIssuesList. ToDo: Create ENums for choices. ## SearchBy ## A string-value to search the: so, site, device, deviceClass, service, transitionTime, ## notification, features, deviceID, and ip address. If ($IssueSearchBy){ $KeyPair2 = [PSObject]@{Key='searchBy'; Value=$IssueSearchBy;} $this.KeyPairs += $KeyPair2 } ## OrderBy ## Valid inputs are: customername, devicename, servicename, status, transitiontime,numberofacknoledgednotification, ## serviceorganization, deviceclass, licensemode, and endpointsecurity. ## Default is customername. # $IssueOrderBy = "transitiontime" # $KeyPair3 = [PSObject]@{Key='orderBy'; Value=$IssueOrderBy;} # $this.KeyPairs += $KeyPair3 ## ReverseOrder ## Must be true or false. Default is false. # $IssueOrderReverse = "true" # $KeyPair4 = [PSObject]@{Key='reverseorder'; Value=$IssueOrderReverse;} # $this.KeyPairs += $KeyPair4 ## Status ## Only 1 (last) statusfilter will be applied (if used). ## NOC_View_Notification_Acknowledgement_Filter. ## Valid inputs are: "Acknowledged" or "Unacknowledged" # $IssueAcknowledged = "Unacknowledged" # $KeyPair5 = [PSObject]@{Key='NOC_View_Notification_Acknowledgement_Filter'; Value=$IssueAcknowledged;} # $this.KeyPairs += $KeyPair5 ## NOC_View_Status_Filter ## Valid inputs are: no data, stale, normal, warning, failed, misconfigured, disconnected ## 'normal' does not return any data. # $IssueStatus = "warning" # $KeyPair6 = [PSObject]@{Key='NOC_View_Status_Filter'; Value=$IssueStatus;} # $this.KeyPairs += $KeyPair6 $this.rc = $null ## KeyPairs is mandatory in this query. returns limited list Try{ # $this.rc = $this.Connection.activeIssuesList($this.PlainUser(), $this.PlainPass(), $this.KeyPairs) $this.rc = $this.GetNCData('activeIssuesList', $this.KeyPairs) } Catch { $this.Error = $_ $this.ErrorHandler() } ## Needs 'issue' iso 'items' for ReturnObjects # Return $this.ProcessData1($this.rc, "issue") Return $this.ProcessData1($this.rc) } [Object]JobStatusList([Int]$ParentID){ ## Uses CustomerID. Reports ONLY Scripting-tasks now (not AMP or discovery). ## Refresh / Clean KeyPair-container. $this.KeyPairs = @() ## Add parameters as KeyPairs. $KeyPair1 = [PSObject]@{Key='customerID'; Value=$ParentID;} $this.KeyPairs += $KeyPair1 $this.rc = $null Try{ # $this.rc = $this.Connection.jobStatusList($this.PlainUser(), $this.PlainPass(), $this.KeyPairs) $this.rc = $this.GetNCData('jobStatusList', $this.KeyPairs) } Catch { $this.Error = $_ $this.ErrorHandler() } Return $this.ProcessData1($this.rc) } [Object]CustomerList(){ Return $this.CustomerList($false) } [Object]CustomerList([Boolean]$SOList){ ## Refresh / Clean KeyPair-container. $this.KeyPairs = @() If($SOList){ $KeyPair1 = [PSObject]@{Key='listSOs'; Value='true';} $this.KeyPairs += $KeyPair1 } $this.rc = $null ## KeyPairs Array must exist, but is not used in this query. Try{ # $this.rc = $this.Connection.customerList($this.PlainUser(), $this.PlainPass(), $this.KeyPairs) $this.rc = $this.GetNCData('customerList', $this.KeyPairs) } Catch { $this.Error = $_ $this.ErrorHandler() } # Return $this.ProcessData1($this.rc, "items") Return $this.ProcessData1($this.rc) } [Object]CustomerListChildren([Int]$ParentID){ ## Refresh / Clean KeyPair-container. $this.KeyPairs = @() ## Add parameters as KeyPairs. $KeyPair1 = [PSObject]@{Key='customerID'; Value=$ParentID;} $this.KeyPairs += $KeyPair1 $this.rc = $null ## KeyPairs is mandatory in this query. returns limited list Try{ # $this.rc = $this.Connection.customerListChildren($this.PlainUser(), $this.PlainPass(), $this.KeyPairs) $this.rc = $this.GetNCData('customerListChildren', $this.KeyPairs) } Catch { $this.Error = $_ $this.ErrorHandler() } # Return $this.ProcessData1($this.rc, "items") Return $this.ProcessData1($this.rc) } [Int]CustomerAdd([String]$CustomerName,[Int]$ParentID){ Return $this.CustomerAdd($CustomerName,$ParentID,@{}) } [Int]CustomerAdd([String]$CustomerName,[Int]$ParentID,$CustomerDetails){ ## Refresh / Clean KeyPair-container. $this.KeyPairs = @() $KeyPair1 = [PSObject]@{Key='customername'; Value=$CustomerName;} $this.KeyPairs += $KeyPair1 $KeyPair2 = [PSObject]@{Key='parentid'; Value=$ParentID;} $this.KeyPairs += $KeyPair2 ## Only basic properties are allowed others are skipped. Must be an ordered-/hash-list. If($CustomerDetails){ If ($CustomerDetails -is [System.Collections.IDictionary]){ ForEach($key in $CustomerDetails.keys){ If ($this.CustomerValidation -contains $key){ ## This is a standard CustomerProperty. #Write-host ("Adding {1} to {0}." -f $key, $CustomerDetails[$key]) $KeyPair = [PSObject]@{Key=$key; Value=$CustomerDetails[$key];} $this.KeyPairs += $KeyPair } } }Else{ Write-Host "The customer-details must be given in a Hash or Ordered list." } } $this.rc = $null Try{ ## Default GetNCData can be used for API-request $this.rc = $this.GetNCData('customerAdd', $this.KeyPairs) } Catch { $this.Error = $_ $this.ErrorHandler() } ## No dataprocessing needed. Return New customerID Return $this.rc[0] } [void]CustomerModify([Int]$CustomerID,[String]$PropertyName,[String]$PropertyValue){ ## Basic Customer-properties in KeyPairs ## Validate $PropertyName If(!($this.CustomerValidation -contains $PropertyName)){ Write-Host "Invalid customer field: $PropertyName." Break } #Mandatory (Key) customerid - (Value) the (customer) id of the ID of the existing service organization/customer/site being modified. #Mandatory (Key) customername - (Value) Desired name for the new customer or site. Maximum of 120 characters. #Mandatory (Key) parentid - (Value) the (customer) id of the parent service organization or parent customer for the new customer/site. ## Data-caching for faster future-access. Additional data-lookup and key-check for mandatory data. If(!$this.CustomerData){ $this.CustomerData = $this.customerlist() | Select-Object customerid,customername,parentid } ## Lookup Data from cache for mandatory fields related to the $CustomerID. $CustomerName = ($this.CustomerData).where({ $_.customerID -eq $CustomerID }).CustomerName $ParentID = ($this.CustomerData).where({ $_.customerID -eq $CustomerID }).ParentID ## For an Invalid CustomerID, No additional lookup-data is found. If(!$ParentID){ Write-Host "Unknown CustomerID: $CustomerID." Break } ## Refresh / Clean KeyPair-container. $this.KeyPairs = @() ## Add Mandatory parameters as KeyPairs. $KeyPair1 = [PSObject]@{Key='customerid'; Value=$CustomerID;} $this.KeyPairs += $KeyPair1 $KeyPair2 = [PSObject]@{Key="customername"; Value=$CustomerName;} $this.KeyPairs += $KeyPair2 $KeyPair3 = [PSObject]@{Key="parentid"; Value=$ParentID;} $this.KeyPairs += $KeyPair3 ## PropertyName already validated at CmdLet. $KeyPair4 = [PSObject]@{Key=$PropertyName; Value=$PropertyValue;} $this.KeyPairs += $KeyPair4 ## Using as [void]: No returndata needed/used. Try{ # $this.Connection.CustomerModify($this.PlainUser(), $this.PlainPass(), $this.KeyPairs) ## Standard GetNCData can be used here. $this.GetNCData('customerModify', $this.KeyPairs) } Catch { $this.Error = $_ $this.ErrorHandler() } } [Object]OrganizationPropertyList(){ # No FilterArray-parameter adds an empty ParentIDs-Array. Returns all customers return $this.OrganizationPropertyList(@()) } [Object]OrganizationPropertyList([Array]$ParentIDs){ # Returns all Custom Customer-Properties and values. $this.rc = $null Try{ # $this.rc = $this.Connection.organizationPropertyList($this.PlainUser(), $this.PlainPass(), $ParentIDs, $false) $this.rc = $this.GetNCDataOP('organizationPropertyList', $ParentIDs, $false) } Catch { $this.Error = $_ $this.ErrorHandler() } Return $this.ProcessData1($this.rc, "properties") } [Int]OrganizationPropertyID([Int]$OrganizationID,[String]$PropertyName){ ## Search the DevicePropertyID by Name/label (Case InSensitive). ## Returns 0 (zero) if not found. $OrganizationPropertyID = 0 $this.rc = $null $OrganizationProperties = $null Try{ ## Retrieve a list of the properties for the given OrganizationID # $OrganizationProperties = $this.Connection.OrganizationPropertyList($this.PlainUser(), $this.PlainPass(), $OrganizationID, $false) $OrganizationProperties = $this.GetNCDataOP('organizationPropertyList', $OrganizationID, $false) # $OrganizationProperties = $this.OrganizationPropertyList($OrganizationID) } Catch { $this.Error = $_ $this.ErrorHandler() } ForEach ($OrganizationProperty in $OrganizationProperties.properties){ ## Case InSensitive compare. If($OrganizationProperty.label -eq $PropertyName){ $OrganizationPropertyID = $OrganizationProperty.PropertyID } } Return $OrganizationPropertyID } [void]OrganizationPropertyModify([Int]$OrganizationID,[String]$OrganizationPropertyName,[String]$OrganizationPropertyValue){ [Int]$OrganizationPropertyID = $this.OrganizationPropertyID($OrganizationID,$OrganizationPropertyName) If ($OrganizationPropertyID -gt 0){ [void]$this.OrganizationPropertyModify($OrganizationID,$OrganizationPropertyID,$OrganizationPropertyValue) } Else{ ## Throw Error Write-Host "OrganizationProperty '$OrganizationPropertyName' not found on this Customer." Break } } [void]OrganizationPropertyModify([Int]$OrganizationID,[Int]$OrganizationPropertyID,[String]$OrganizationPropertyValue){ $OrganizationProperty = [PSObject]@{PropertyID=$OrganizationPropertyID; value=$OrganizationPropertyValue; PropertyIDSpecified='True';} # $Organization = [PSObject]@{OrganizationID=$OrganizationID; properties=$OrganizationProperty; OrganizationIDSpecified='True';} $OrganizationPropertyArray = [PSObject]@{CustomerID=$OrganizationID; properties=$OrganizationProperty; CustomerIDSpecified='True';} ## Organization-layout: # $Organization = [PSObject]@{CustomerID=''; properties=''; CustomerIDSpecified='True';} # $Organization = New-Object -TypeName ($this.NameSpace + '.organizationProperties') ## properties hold an array of DeviceProperties ## Individual OrganizationProperty layout: # $OrganizationProperty = [PSObject]@{PropertyID=''; value=''; PropertyIDSpecified='True';} # $OrganizationProperty = New-Object -TypeName ($this.NameSpace + '.organizationProperty') # If ($OrganizationPropertyArray){ Try{ # $this.Connection.OrganizationPropertyModify($this.PlainUser(), $this.PlainPass(), $OrganizationPropertyArray) $this.SetNCDataOP('organizationPropertyModify',$OrganizationID,$OrganizationPropertyID,$OrganizationPropertyValue) } Catch { $this.Error = $_ $this.ErrorHandler() } # } # Else{ # Write-Host "INFO:OrganizationPropertyModify - Nothing to save" # } } #EndRegion #Region DeviceData [Object]DeviceList([Int]$ParentID){ ## Use default Settings for DeviceList Return $this.Devicelist($ParentID,'true','false') } [Object]DeviceList([Int]$ParentID,[String]$Devices,[String]$Probes){ ## Returns only Managed/Imported Items. ## Refresh / Clean KeyPair-container. $this.KeyPairs = @() ## Add parameters as KeyPairs. Need to be unique Objects. $KeyPair1 = [PSObject]@{Key='customerID'; Value=$ParentID;} $this.KeyPairs += $KeyPair1 $KeyPair2 = [PSObject]@{Key='devices'; Value=$Devices;} $this.KeyPairs += $KeyPair2 $KeyPair3 = [PSObject]@{Key='probes'; Value=$Probes;} $this.KeyPairs += $KeyPair3 $this.rc = $null Try{ # $this.rc = $this.Connection.deviceList($this.PlainUser(), $this.PlainPass(), $this.KeyPairs) $this.rc = $this.GetNCData('deviceList', $this.KeyPairs) } Catch{ $this.Error = $_ $this.ErrorHandler() } # Return $this.ProcessData1($this.rc, "info") Return $this.ProcessData1($this.rc) } [Object]DeviceGet([int]$DeviceID){ ## Refresh / Clean KeyPair-container. $this.KeyPairs = @() ## Add parameter as KeyPair. #Write-Host "Adding key for $DeviceID" $KeyPair1 = [PSObject]@{Key='deviceID'; Value=$DeviceID;} $this.KeyPairs += $KeyPair1 $this.rc = $null Try{ # $this.rc = $this.Connection.deviceGet($this.PlainUser(), $this.PlainPass(), $this.KeyPairs) $this.rc = $this.GetNCData('deviceGet', $this.KeyPairs) } Catch { $this.Error = $_ $this.ErrorHandler() } Return $this.ProcessData1($this.rc) } [Object]DeviceGetAppliance([int]$ApplianceID){ ## Refresh / Clean KeyPair-container. $this.KeyPairs = @() ## Add parameter as KeyPair. #Write-Host "Adding key for $ApplianceID" $KeyPair1 = [PSObject]@{Key='applianceID'; Value=$ApplianceID;} $this.KeyPairs += $KeyPair1 $this.rc = $null Try{ # $this.rc = $this.Connection.deviceGet($this.PlainUser(), $this.PlainPass(), $this.KeyPairs) $this.rc = $this.GetNCData('deviceGet', $this.KeyPairs) } Catch { $this.Error = $_ $this.ErrorHandler() } Return $this.ProcessData1($this.rc) } [Object]DeviceGetStatus([Int]$DeviceID){ ## Refresh / Clean KeyPair-container. $this.KeyPairs = @() ## Add parameters as KeyPairs. $KeyPair1 = [PSObject]@{Key='deviceID'; Value=$DeviceID;} $this.KeyPairs += $KeyPair1 $this.rc = $null Try{ # $this.rc = $this.Connection.deviceGetStatus($this.PlainUser(), $this.PlainPass(), $this.KeyPairs) $this.rc = $this.GetNCData('deviceGetStatus', $this.KeyPairs) } Catch { $this.Error = $_ $this.ErrorHandler() } # Return $this.ProcessData1($this.rc, "info") Return $this.ProcessData1($this.rc) } [Object]DevicePropertyList([Array]$DeviceIDs,[Array]$DeviceNames,[Array]$FilterIDs,[Array]$FilterNames){ ## Reports the Custom Device-Properties and values. Uses filter-arrays. ## Names are Case-sensitive. ## Returns both Managed and UnManaged Devices. $this.rc = $null Try{ # $this.rc = $this.Connection.devicePropertyList($this.PlainUser(), $this.PlainPass(), $DeviceIDs,$DeviceNames,$FilterIDs,$FilterNames,$false) $this.rc = $this.GetNCDataDP('devicePropertyList',$DeviceIDs,$DeviceNames,$FilterIDs,$FilterNames,$false) } Catch { $this.Error = $_ $this.ErrorHandler() } Return $this.ProcessData1($this.rc, "properties") } [Int]DevicePropertyID([Int]$DeviceID,[String]$PropertyName){ ## Search the DevicePropertyID with Name-Filter (Case InSensitive). ## Returns 0 (zero) if not found. $DevicePropertyID = 0 $DeviceProperties = $null Try{ # $DeviceProperties = $this.Connection.devicePropertyList($this.PlainUser(), $this.PlainPass(), $DeviceID,$null,$null,$null,$false) $DeviceProperties = $this.GetNCDataDP('devicePropertyList',$DeviceID,$null,$null,$null,$false) } Catch { $this.Error = $_ $this.ErrorHandler() } ForEach ($DeviceProperty in $DeviceProperties.properties){ ## Case InSensitive compare. If($DeviceProperty.label -eq $PropertyName){ $DevicePropertyID = $DeviceProperty.devicePropertyID } } Return $DevicePropertyID } [void]DevicePropertyModify([Int]$DeviceID,[String]$DevicePropertyName,[String]$DevicePropertyValue){ [Int]$DevicePropertyID = $this.DevicePropertyID($DeviceID,$DevicePropertyName) If ($DevicePropertyID -gt 0){ [void]$this.DevicePropertyModify($DeviceID,$DevicePropertyID,$DevicePropertyValue) } Else{ ## Throw Error Write-Host "DeviceProperty '$DevicePropertyName' not found on this Device." Break # $this.Error = "DeviceProperty '$DevicePropertyName' not found on this Device." # $this.ErrorHandler() } } [void]DevicePropertyModify([Int]$DeviceID,[Int]$DevicePropertyID,[String]$DevicePropertyValue){ ## Create a custom DevicePropertyArray. Details below. # $DeviceProperty = [PSObject]@{devicePropertyID=$DevicePropertyID; value=$DevicePropertyValue; devicePropertyIDSpecified='True';} # $DevicesPropertyArray = [PSObject]@{deviceID=$DeviceID; properties=$DeviceProperty; deviceIDSpecified='True';} ## Device-layout for WebProxy: # $Device = [PSObject]@{deviceID=''; properties=''; deviceIDSpecified='True';} # $Device = New-Object -TypeName ($this.NameSpace + '.deviceProperties') ## properties hold an array of DeviceProperties ## Individual DeviceProperty layout for WebProxy: # $DeviceProperty = [PSObject]@{devicePropertyID=''; value=''; devicePropertyIDSpecified='True';} # $DeviceProperty = New-Object -TypeName ($this.NameSpace + '.deviceProperty') # If ($devicesPropertyArray){ # Try{ # $this.Connection.devicePropertyModify($this.PlainUser(), $this.PlainPass(), $devicesPropertyArray) $this.SetNCDataDP('devicePropertyModify',$DeviceID,$DevicePropertyID,$DevicePropertyValue) # } # Catch { # $this.Error = $_ # $this.ErrorHandler() # } # } # Else{ # Write-Host "INFO:DevicePropertyModify - Nothing to save" # } } [Object]DeviceAssetInfoExportDevice(){ ## Reports all details for Monitored Assets. ## !!! Potentially puts a high load on the NCentral-server!!! ## Removed/disabled in the Module. ## Only supporting 'DeviceAssetInfoExportDeviceWithSetting' for a single deviceID. # ## Class: DeviceData # ## deviceAssetInfoExport Deprecated # ## deviceAssetInfoExportDevice Same as 'WithSettings' without specifying filters. # ## deviceAssetInfoExportDeviceWithSettings # ## # ## Reports all Monitored Assets and Details. No filtering by CustomerID or DeviceID. Reports All Assets. # ## Use without Header-formatting (has sub-headers). Device.customerid=siteid. # ## Generating this list takes quite a long time. Might even time-out. # #$rc = $nws.deviceAssetInfoExport2("0.0", $username, $password) #Error - nonexisting # #$ri = $nws.deviceAssetInfoExport("0.0", $username, $password) #Error - unsupported version # #$ri = $nws.deviceAssetInfoExportDevice("0.0", $username, $password) # #$PairClass="info" $this.rc = $null Try{ # $this.rc = $this.Connection.deviceAssetInfoExportDevice("0.0", $this.PlainUser(), $this.PlainPass()) # $this.rc = $this.GetNCData('deviceAssetInfoExportDevice','',"0.0") } Catch { $this.Error = $_ $this.ErrorHandler() } Return $this.rc # Return $this.ProcessData1($this.rc, "info") } [Object]DeviceAssetInfoExportDeviceWithSettings($DeviceIDs){ ## Reports Monitored Assets. ## Calls Full Command with Parameters Return $this.DeviceAssetInfoExportDeviceWithSettings($DeviceIds,$null,$null,$null) } [Object]DeviceAssetInfoExportDeviceWithSettings($DeviceIDs,[Array]$DeviceNames,[Array]$FilterIDs,[Array]$FilterNames){ ## Reports Monitored Assets. ## Currently returns all categories for the selected devices. TODO: category-filtering. # From Documentation: # http://mothership.n-able.com/dms/javadoc_ei2/com/nable/nobj/ei2/ServerEI2_PortType.html#deviceAssetInfoExportDeviceWithSettings-java.lang.String-java.lang.String-com.nable.nobj.ei2.T_KeyPair:A- # # Use only ONE of the following options to limit information to certain devices # "TargetByDeviceID" - value for this key is an array of deviceids # "TargetByDeviceName" - value for this key is an array of devicenames # "TargetByFilterID" - value for this key is an array of filterids # "TargetByFilterName" - value for this key is an array filternames $this.KeyPairs = @() $KeyPair1 = $null ## Add only one of the parameters as KeyPair. by priority. If ($DeviceIDs){ $KeyPair1 = [PSObject]@{Key='TargetByDeviceID'; Value=$DeviceIDs;} # ForEach($DeviceID in $DeviceIDs){ # $KeyPair1 = [PSObject]@{Key='TargetByDeviceID'; Value=$DeviceID;} # $this.KeyPairs += $KeyPair1 # } }ElseIf($FilterIDs){ $KeyPair1 = [PSObject]@{Key='TargetByFilterID'; Value=$FilterIDs;} }ElseIF($DeviceNames){ $KeyPair1 = [PSObject]@{Key='TargetByDeviceName'; Value=$DeviceNames;} }ElseIf($FilterNames){ $KeyPair1 = [PSObject]@{Key='TargetByFilterName'; Value=$FilterNames;} } ## Do not continue if no filter is specified. ## Due to potential heavy server load. If (!$KeyPair1){ ## TODO: Throw Error Break } $this.KeyPairs += $KeyPair1 # ## Documentation On Inclusion/Exclusion: # ## Key = "InformationCategoriesInclusion" and Value = String[] {"asset.device", "asset.os"} then only information for these two categories will be returned. # ## Key = "InformationCategoriesExclusion" and Value = String[] {"asset.device", "asset.os"} # ## Work in Progress # $KeyPair2 = [PSObject]@{Key="InformationCategoriesInclusion"; Value=[Array]{"asset.device", "asset.os"};} # $KeyPair2 = [PSObject]@{Key="InformationCategoriesExclusion"; Value=[Array]{"asset.device", "asset.os"};} # $KeyPair2 = New-Object -TypeName ($this.namespace + '.tKeyPair') # $KeyPair2.Key = 'InformationCategoriesExclusion' # $KeyPair2.Value = [Array]{"asset.application", "asset.os"} # $this.KeyPairs += $KeyPair2 $this.rc = $null Try{ # $this.rc = $this.Connection.deviceAssetInfoExportDeviceWithSettings("0.0", $this.PlainUser(), $this.PlainPass(), $this.KeyPairs) #$this.rc = $this.Connection.deviceAssetInfoExport2("0.0", $this.PlainUser(), $this.PlainPass(), $this.KeyPairs) $this.rc = $this.GetNCData('deviceAssetInfoExportDeviceWithSettings',$this.KeyPairs,"0.0") } Catch { $this.Error = $_ $this.ErrorHandler() } ## Todo: Parameter for what to return: ## Flat Object (ProcessData1) or ## Multi-Dimesional Object (ProcessData2). # Return $this.ProcessData2($this.rc, "info") Return $this.ProcessData2($this.rc) } #EndRegion #Region NCentralAppData # ## To Do # ## TODO - User/Role/AccessGroup as user-object. # ## TODO - Filter/Rule list (Not available through API yet) # ## TODO - AccessGroupGet Method not functioning yet. [Object]AccessGroupList([Int]$ParentID){ ## List All Access Groups ## Mandatory valid CustomerID (SO/Customer/Site-level), does not seem to use it. ## Refresh / Clean KeyPair-container. $this.KeyPairs = @() ## Add parameters as KeyPairs. $KeyPair1 = [PSObject]@{Key='customerID'; Value=$ParentID;} $this.KeyPairs += $KeyPair1 $this.rc = $null Try{ # $this.rc = $this.Connection.accessGroupList($this.PlainUser(), $this.PlainPass(), $this.KeyPairs) $this.rc = $this.GetNCData('accessGroupList', $this.KeyPairs) } Catch { #$this.ErrorHandler($_) $this.Error = $_ $this.ErrorHandler() } Return $this.ProcessData1($this.rc) } [Object]AccessGroupGet([Int]$GroupID,[Int]$ParentID,[Boolean]$IsCustomerGroup){ ## List Access Groups details. Work in Progress. ## Uses groupID and customerGroup. Gets details for the specified AccessGroup. ## Mandatory parameters ?? Error: '1012 Mandatory settings not present' ## Refresh / Clean KeyPair-container. $this.KeyPairs = @() ## Add parameters as KeyPairs. $KeyPair1 = [PSObject]@{Key='groupID'; Value=$GroupID;} $this.KeyPairs += $KeyPair1 # $KeyPair2 = [PSObject]@{Key='customerID'; Value=$ParentID;} # $this.KeyPairs += $KeyPair2 # # $KeyPair3 = [PSObject]@{Key='customerGroup'; Value=$IsCustomerGroup;} # $this.KeyPairs += $KeyPair3 $this.rc = $null Try{ # $this.rc = $this.Connection.accessGroupGet($this.PlainUser(), $this.PlainPass(), $this.KeyPairs) $this.rc = $this.GetNCData('accessGroupGet', $this.KeyPairs) } Catch { $this.Error = $_ $this.ErrorHandler() } Return $this.ProcessData1($this.rc) } [Object]UserRoleList([Int]$ParentID){ ## List All User Roles ## Mandatory valid CustomerID (SO/Customer/Site-level), does not seem to use it. ## Refresh / Clean KeyPair-container. $this.KeyPairs = @() ## Add parameters as KeyPairs. $KeyPair1 = [PSObject]@{Key='customerID'; Value=$ParentID;} $this.KeyPairs += $KeyPair1 $this.rc = $null Try{ # $this.rc = $this.Connection.userRoleList($this.PlainUser(), $this.PlainPass(), $this.KeyPairs) $this.rc = $this.GetNCData('userRoleList', $this.KeyPairs) } Catch { $this.Error = $_ $this.ErrorHandler() } Return $this.ProcessData1($this.rc) } [Object]UserRoleGet([Int]$UserRoleID,[Int]$ParentID){ ## List User Role details. ## Refresh / Clean KeyPair-container. $this.KeyPairs = @() ## Add parameters as KeyPairs. $KeyPair1 = [PSObject]@{Key='userRoleID'; Value=$UserRoleID;} $this.KeyPairs += $KeyPair1 If($ParentID){ $KeyPair2 = [PSObject]@{Key='customerID'; Value=$ParentID;} $this.KeyPairs += $KeyPair2 } $this.rc = $null Try{ # $this.rc = $this.Connection.userRoleGet($this.PlainUser(), $this.PlainPass(), $this.KeyPairs) $this.rc = $this.GetNCData('userRoleGet', $this.KeyPairs) } Catch { $this.Error = $_ $this.ErrorHandler() } Return $this.ProcessData1($this.rc) } #EndRegion #EndRegion } Function NcConnected{ <# .Synopsis Checks or initiates the NCentral connection. .Description Checks or initiates the NCentral connection. Returns $true if a connection established. #> $NcConnected = $false If (!$Global:_NCSession){ # Write-Host "No connection to NCentral Server found.`r`nUsing 'New-NCentralConnection' to connect." New-NCentralConnection } ## Succesful connection? If ($Global:_NCSession){ $NcConnected = $true } Else{ Write-Host "No valid connection to NCentral Server." } Return $NcConnected } #EndRegion #Region PowerShell CmdLets # ## To Do # ## TODO - Error-handling at CmdLet Level. # ## TODO - Add Examples to in-line documentation. # ## TODO - Additional CmdLets (DataExport, PSA, CustomerObject, ...) # ## #Region Module-support Function New-NCentralConnection{ <# .Synopsis Connect to the NCentral server. .Description Connect to the NCentral server. Https is always used, since the data itself is unencrypted. The returned connection-object allows to extract and manipulate NCentral Data through methods of the NCentral_Connection Class. To show available Commands, type: Get-NCHelp .Parameter ServerFQDN Specify the Server DNS-name for this Connection. The server needs to have a valid certficate for HTTPS. .Parameter PSCredential PowerShell-Credential object containing Username and Password for N-Central access. No MFA. .Parameter JWT String Containing the JavaWebToken for N-Central access. .Parameter DefaultCustomerID Sets the default CustomerID for this instance. The CustomerID can be found in the customerlist. CustomerID 1 Root / System CustomerID 50 First ServiceOrganization (Default) .Example $PSUserCredential = Get-Credential -Message "Enter NCentral API-User credentials" New-NCentralConnection NCserver.domain.com $PSUserCredential .Example $NCentralFQDN = "<name>.<domain>" $SecurePass = ConvertTo-SecureString <PassWord> -AsPlainText -Force $PSUserCredential = New-Object PSCredential (<UserName>, $SecurePass) New-NCentralConnection $NCentralFQDN $PSUserCredential Use the 4 lines above inside a script for a fully-automated connection. #> [CmdletBinding()] Param( [Parameter(Mandatory=$false)][String]$ServerFQDN, [Parameter(Mandatory=$false)][PSCredential]$PSCredential, [Parameter(Mandatory=$false)][String]$JWT, [Parameter(Mandatory=$false)][Int]$DefaultCustomerID = 50 ) Begin{ ## Check parameters ## Clear the ServerFQDN if there is no . in it. Will create dialog. If ($ServerFQDN -notmatch "\.") { $ServerFQDN = $null } } Process{ ## Store the session in a global variable as the default connection. # Initiate the connection with the given information. # Prompts for additional information if needed. If ($ServerFQDN){ If ($PSCredential){ #Write-Host "Using Credentials" $Global:_NCSession = [NCentral_Connection]::New($ServerFQDN, $PSCredential) } Elseif($JWT){ #Write-Host "Using JWT" $Global:_NCSession = [NCentral_Connection]::New($ServerFQDN, $JWT) } Else { $Global:_NCSession = [NCentral_Connection]::New($ServerFQDN) } } Else { $Global:_NCSession = [NCentral_Connection]::New() } ## ToDo: Check for succesful connection. #Write-Host ("Connection to {0} is {1}." -f $Global:_NCSession.ConnectionURL,$Global:_NCSession.IsConnected) # Set the default CustomerID for this session. $Global:_NCSession.DefaultCustomerID = $DefaultCustomerID } End{ ## Return the initiated Class Write-Output $Global:_NCSession } } Function Get-NCHelp{ <# .Synopsis Shows a list of available PS-NCentral commands and the synopsis. .Description Shows a list of available PS-NCentral commands and the synopsis. #> Get-Command -Module PS-NCentral | Select-Object Name |Get-Help | Select-Object Name,Synopsis } Function Get-NCVersion{ <# .Synopsis Returns the N-Central Version(s) of the connected server. .Description Returns the N-Central Version(s) of the connected server. #> [CmdletBinding()] Param( [Parameter(Mandatory=$false, HelpMessage = 'Show API version info')] [Alias('FullVersionList','Full')] [Switch]$APIVersion, [Parameter(Mandatory=$false, HelpMessage = 'Show GUI version only')] [Alias('VersionOnly')] [Switch]$Plain, [Parameter(Mandatory=$false)]$NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } } Process{ } End{ ## API-version info If ($APIVersion){ Write-Output $NcSession.ConnectedVersion | Format-table } ## Connection info If ($Plain){ Write-Output $NcSession.NCVersion } Else{ Write-Output $NcSession } } } Function Get-NCTimeOut{ <# .Synopsis Returns the max. time in seconds to wait for data returning from a (Synchronous) NCentral API-request. .Description Shows the maximum time to wait for synchronous data-request. Dialog in seconds. #> [CmdletBinding()] Param( [Parameter(Mandatory=$false, HelpMessage = 'Existing NCentral_Connection')] $NcSession ) Begin{ If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } } Process{ # Write-Output ($NCSession.Connection.TimeOut/1000) Write-Output ($NCSession.RequestTimeOut) } End{} } Function Set-NCTimeOut{ <# .Synopsis Sets the max. time in seconds to wait for data returning from a (Synchronous) NCentral API-request. .Description Sets the maximum time to wait for synchronous data-request. Time in seconds. Range: 15-600. Default is 100. #> [CmdletBinding()] Param( [Parameter(Mandatory=$false, HelpMessage = 'TimeOut for NCentral Requests in Seconds')] [Int]$TimeOut, [Parameter(Mandatory=$false, HelpMessage = 'Existing NCentral_Connection')] $NcSession ) Begin{ If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } ## Limit Range. Set to Default (100000) if too small or no value is given. # $TimeOut = $TimeOut * 1000 If ($TimeOut -lt 15){ Write-Host "Minimum TimeOut is 15 Seconds. Is now reset to default; 100 seconds" $TimeOut = 100 } If ($TimeOut -gt 600){ Write-Host "Maximum TimeOut is 600 Seconds. Is now reset to Max; 600 seconds" $TimeOut = 600 } } Process{ # $NCSession.Connection.TimeOut = ($TimeOut * 1000) $NCSession.RequestTimeOut = $TimeOut # Write-Output ($NCSession.Connection.TimeOut) Write-Output ($NCSession.RequestTimeOut) } End{} } #EndRegion #Region Customers Function Get-NCServiceOrganizationList{ <# .Synopsis Returns a list of all ServiceOrganizations and their data. .Description Returns a list of all ServiceOrganizations and their data. #> [CmdletBinding()] Param( [Parameter(Mandatory=$false, HelpMessage = 'Existing NCentral_Connection')] $NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } } Process{ } End{ Write-Output $NcSession.CustomerList($true) } } Function Get-NCCustomerList{ <# .Synopsis Returns a list of all customers and their data. ChildrenOnly when CustomerID is specified. .Description Returns a list of all customers and their data. ChildrenOnly when CustomerID is specified. ## TODO - Integrate Custom-properties #> [CmdletBinding()] Param( [Parameter(Mandatory=$false, # ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Existing Customer ID')] ## Default-value is essential for output-selection. $CustomerID = 0, [Parameter(Mandatory=$false, HelpMessage = 'Existing NCentral_Connection')] $NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } } Process{ Write-Debug "CustomerID: $CustomerID" If ($CustomerID -eq 0){ ## Return all Customers # Write-Output $NcSession.CustomerList() $ReturnData = $NcSession.CustomerList() } Else{ ## Return direct children only. # Write-Output $NcSession.CustomerListChildren($CustomerID) $ReturnData = $NcSession.CustomerListChildren($CustomerID) } } End{ ## Alphabetical Columnnames $ReturnData | Select-Object ($ReturnData|Get-Member -type Noteproperty -ErrorAction SilentlyContinue).name -ErrorAction SilentlyContinue | ## Put important fields in front. Select-Object customerid,customername,externalid,externalid2,* -ErrorAction SilentlyContinue | Write-Output } } Function Set-NCCustomerDefault{ <# .Synopsis Sets the DefaultCustomerID to be used. .Description Sets the DefaultCustomerID to be used, when not supplied as parameter. Standard-value: 50 (First Service Organization created). #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, # ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Existing Customer ID')] $CustomerID, [Parameter(Mandatory=$false, HelpMessage = 'Existing NCentral_Connection')] $NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } } Process{ $NcSession.DefaultCustomerID = $CustomerID Write-Host ("Default CustomerID now set to: {0}" -f $CustomerID) } End{ } } Function Get-NCCustomerPropertyList{ <# .Synopsis Returns a list of all Custom-Properties for the selected CustomerID(s). .Description Returns a list of all Custom-Properties for the selected customers. If no customerIDs are supplied, data for all customers will be returned. ## TODO - Integrate this in the default NCCustomerList. #> [CmdletBinding()] Param( [Parameter(Mandatory=$false, # ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Array of Existing Customer IDs')] [Alias("CustomerID")] [Array]$CustomerIDs, [Parameter(Mandatory=$false, HelpMessage = 'No Sorting of the output')] [Alias('UnSorted')] [Switch]$NoSort, [Parameter(Mandatory=$false)]$NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } } Process{ If ($CustomerIDs){ # Write-Output $NcSession.OrganizationPropertyList($CustomerIDs) $ReturnData = $NcSession.OrganizationPropertyList($CustomerIDs) } Else{ # Write-Output $NcSession.OrganizationPropertyList() $ReturnData = $NcSession.OrganizationPropertyList() } } End{ If($NoSort){ $ReturnData | Write-Output } Else{ ## Alphabetical Columnnames $ReturnData | Select-Object ($ReturnData|Get-Member -type Noteproperty -ErrorAction SilentlyContinue).name -ErrorAction SilentlyContinue | ## Make CustomerID the first column. Select-Object customerid,* -ErrorAction SilentlyContinue | Write-Output } } } Function Set-NCCustomerProperty{ <# .Synopsis Fills the specified property(name) for the given CustomerID(s). .Description Fills the specified property(name) for the given CustomerID(s). This can be a default or custom property. CustomerID(s) must be supplied. Properties are cleared if no Value is supplied. #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, # ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Array of Existing Customer IDs')] [Alias("CustomerID")] [Array]$CustomerIDs, [Parameter(Mandatory=$true, # ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 1, HelpMessage = 'Name of the Customer Custom-Property')] [Alias("PropertyName")] [String]$PropertyLabel, [Parameter(Mandatory=$false, # ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 2, HelpMessage = 'Value for the Customer Property')] [String]$PropertyValue = '', [Parameter(Mandatory=$false)]$NcSession ) Begin{ #check parameters. Use defaults if needed/available $CustomerProperty = $false If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } If (!$CustomerIDs){ Write-Host "No CustomerID specified." Break } If (!$PropertyLabel){ Write-Host "No Property-name specified." Break } If (!$PropertyValue){ Write-Host "CustomerProperty '$PropertyLabel' will be cleared." } If ($NcSession.CustomerValidation -contains $PropertyLabel){ ## This is a standard CustomerProperty. $CustomerProperty = $true } } Process{ ForEach($CustomerID in $CustomerIDs ){ ## Differentiate between Standard(Customer) and Custom(Organization) properties. If ($CustomerProperty){ $NcSession.CustomerModify($CustomerID, $PropertyLabel, $PropertyValue) } Else{ $NcSession.OrganizationPropertyModify($CustomerID, $PropertyLabel, $PropertyValue) } } } End{ } } Function Get-NCProbeList{ <# .Synopsis Returns the Probes for the given CustomerID(s). .Description Returns the Probes for the given CustomerID(s). If no customerIDs are supplied, all probes will be returned. #> [CmdletBinding()] Param( [Parameter(Mandatory=$false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Existing Customer ID')] [Alias("CustomerID")] [Array]$CustomerIDs, [Parameter(Mandatory=$false)]$NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } If (!$CustomerIDs){ If (!$NcSession.DefaultCustomerID){ Write-Host "No CustomerID specified." Break } $CustomerIDs = $NcSession.DefaultCustomerID Write-Host ("Using current default CustomerID {0}." -f $CustomerIDs) } } Process{ ForEach ($CustomerID in $CustomerIDs){ $NcSession.DeviceList($CustomerID,'false','true')| Select-Object @{n="customerid"; e={$CustomerID}},customername,deviceid,longname,* -ErrorAction SilentlyContinue | Write-Output } } End{ } } #EndRegion #Region Devices Function Get-NCDeviceList{ <# .Synopsis Returns the Managed Devices for the given CustomerID(s) and Sites below. .Description Returns the Managed Devices for the given CustomerID(s) and Sites below. If no customerIDs are supplied, all managed devices will be returned. ## TODO - Confirmation if no CustomerID(s) are supplied (Full List). #> [CmdletBinding()] Param( [Parameter(Mandatory=$false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Existing Customer ID')] [Alias("CustomerID")] [Array]$CustomerIDs, [Parameter(Mandatory=$false, HelpMessage = 'No Sorting of the output')] [Alias('UnSorted')] [Switch]$NoSort, [Parameter(Mandatory=$false)]$NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } If (!$CustomerIDs){ If (!$NcSession.DefaultCustomerID){ Write-Host "No CustomerID specified." Break } $CustomerIDs = $NcSession.DefaultCustomerID Write-Host ("Using current default CustomerID {0}." -f $CustomerIDs) } } Process{ ForEach ($CustomerID in $CustomerIDs){ $ReturnData = $NcSession.DeviceList($CustomerID) If($NoSort){ $ReturnData | Write-Output } Else{ ## Alphabetical Columnnames $ReturnData | Select-Object ($ReturnData|Get-Member -type Noteproperty -ErrorAction SilentlyContinue).name -ErrorAction SilentlyContinue | ## CustomerID is not returned by default. Added as custom field. Select-Object @{n="customerid"; e={$CustomerID}},customername,sitename,deviceid,longname,* -ErrorAction SilentlyContinue | Write-Output } } } End{ } } Function Get-NCDeviceID{ <# .Synopsis Returns the DeviceID(s) for the given DeviceName(s). Case Sensitive, No Wildcards. .Description The returned objects contain extra information for verification. The supplied name(s) are Case Sensitive, No Wildcards allowed. Also not-managed devices are returned. Nothing is returned for names not found. #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, ValueFromPipeline = $true, # ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Array of existing Filter IDs')] # [Alias("Name")] [Array]$DeviceNames, [Parameter(Mandatory=$false)]$NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } If (!$DeviceNames){ Write-Host "No DeviceName(s) given." Break } } Process{ ## Collect the data for all Names. Case Sensitive, No Wildcards. ## Only Returns found devices. ForEach ($DeviceName in $DeviceNames){ ## Use the NameFilter of the DevicePropertyList to find the DeviceID for now. ## Limited Filter-options, but fast. $NcSession.DevicePropertyList($null,$DeviceName,$null,$null) | ## Add additional Info and return only selected fields/Columns Get-NCDeviceInfo | Select-Object DeviceID,LongName,DeviceClass,CustomerID,CustomerName,IsManagedAsset | Write-Output } } End{ } } Function Get-NCDeviceLocal{ <# .Synopsis Returns the DeviceID, CustomerID and some more Info for the Local Computer. .Description Queries the local ApplicationID and returns the NCentral DeviceID. No Parameters recquired. #> [CmdletBinding()] Param( ) Begin{ #check parameters. Use defaults if needed/available $ApplianceConfig = ("{0}\N-able Technologies\Windows Agent\config\ApplianceConfig.xml" -f ${Env:ProgramFiles(x86)}) $ServerConfig = ("{0}\N-able Technologies\Windows Agent\config\ServerConfig.xml" -f ${Env:ProgramFiles(x86)}) If (-not (Test-Path $ApplianceConfig -PathType leaf)){ Write-Host "No Local NCentral-agent Configuration found." Write-Host "Try using 'Get-NCDeviceID $Env:ComputerName'." Break } If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } } Process{ # Get appliance id $ApplianceXML = [xml](Get-Content -Path $ApplianceConfig) $ApplianceID = $ApplianceXML.ApplianceConfig.ApplianceID # Get management Info. $ServerXML = [xml](Get-Content -Path $ServerConfig) $ServerIP = $ServerXML.ServerConfig.ServerIP $ConnectIP = $NcSession.ConnectionURL If($ServerIP -ne $ConnectIP){ Write-Host "The Local Device is Managed by $ServerIP. You are connected to $ConnectIP." } $NcSession.DeviceGetAppliance($ApplianceID)| ## Return all Info, since already collected. Select-Object deviceid,longname,@{Name="managedby"; Expression={$ServerIP}},customerid,customername,deviceclass,licensemode,* -ErrorAction SilentlyContinue | Write-Output } End{ } } Function Get-NCDevicePropertyList{ <# .Synopsis Returns the Custom Properties of the DeviceID(s). .Description Returns the Custom Properties of the DeviceID(s). If no devviceIDs are supplied, all managed devices and their Custom Properties will be returned. ## TODO - Confirmation if no DeviceID(s) are supplied (Full List). Only warning now. #> [CmdletBinding()] Param( [Parameter(Mandatory=$false, # ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Existing Device ID')] [Alias("DeviceID")] [Array]$DeviceIDs, [Parameter(Mandatory=$false, HelpMessage = 'No Sorting of the output')] [Alias('UnSorted')] [Switch]$NoSort, [Parameter(Mandatory=$false)]$NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } } Process{ If ($DeviceIDs){ $ReturnData = $NcSession.DevicePropertyList($DeviceIDs,$null,$null,$null) } Else{ Write-Host "Generating a full DevicePropertyList may take some time." $ReturnData = $NcSession.DevicePropertyList($null,$null,$null,$null) Write-Host "Data retrieved, processing output." } } End{ If ($NoSort){ $ReturnData | Write-Output } Else{ ## Alphabetical Columnnames $ReturnData | Select-Object ($ReturnData|Get-Member -type Noteproperty -ErrorAction SilentlyContinue).name -ErrorAction SilentlyContinue | ## Make DeviceID the first column. Select-Object deviceid,* -ErrorAction SilentlyContinue | Write-Output } } } Function Get-NCDevicePropertyListFilter{ <# .Synopsis Returns the Custom Properties of the Devices within the FilterID(s). .Description Returns the Custom Properties of the Devices within the FilterID(s). A filterID must be supplied. Hoover over the filter in the GUI to reveal its ID. #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Array of existing Filter IDs')] [Alias("FilterID")] [Array]$FilterIDs, [Parameter(Mandatory=$false, HelpMessage = 'No Sorting of the output')] [Alias('UnSorted')] [Switch]$NoSort, [Parameter(Mandatory=$false)]$NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } If (!$FilterIDs){ Write-Host "No FilterIDs given." Break } } Process{ #Collect the data for all IDs. ForEach ($FilterID in $FilterIDs){ $ReturnData = $NcSession.DevicePropertyList($null,$null,$FilterID,$null) If($NoSort){ $ReturnData | Write-Output } Else{ ## Alphabetical Columnnames $ReturnData | Select-Object ($ReturnData|Get-Member -type Noteproperty -ErrorAction SilentlyContinue).name -ErrorAction SilentlyContinue | ## Make DeviceID the first column. Select-Object deviceid,* -ErrorAction SilentlyContinue | Write-Output } } } End{ } } Function Set-NCDeviceProperty{ <# .Synopsis Fills the Custom Property for the DeviceID(s). .Description Fills the Custom Property for the DeviceID(s). Properties are cleared if no Value is supplied. #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, # ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Existing Device IDs')] [Alias("DeviceID")] [Array]$DeviceIDs, [Parameter(Mandatory=$true, # ValueFromPipeline = $true, # ValueFromPipelineByPropertyName = $true, Position = 1, HelpMessage = 'Name of the Device Custom-Property')] [Alias("PropertyName")] [String]$PropertyLabel, [Parameter(Mandatory=$true, # ValueFromPipeline = $true, # ValueFromPipelineByPropertyName = $true, Position = 2, HelpMessage = 'Value of the Device Custom-Property')] [String]$PropertyValue, [Parameter(Mandatory=$false)]$NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } # If (!$DeviceIDs){ # ## Issue when value comes from pipeline. Use Parameter-validation. # Write-Host "No DeviceID specified." # Break # } If (!$PropertyLabel){ Write-Host "No Property-name specified." Break } If (!$PropertyValue){ Write-Host "DeviceProperty '$PropertyLabel' will be cleared." } } Process{ ForEach($DeviceID in $DeviceIDs ){ $NcSession.DevicePropertyModify($DeviceID, $PropertyLabel, $PropertyValue) } } End{ } } Function Get-NCDeviceInfo{ <# .Synopsis Returns the General details for the DeviceID(s). .Description Returns the General details for the DeviceID(s). DeviceID(s) must be supplied, as a parameter or by PipeLine. Use Get-NCDeviceObject tot retrieve ALL details of a device. #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, # ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Existing Device IDs')] # [ValidateScript({ $_ | ForEach-Object {(Get-Item $_).PSIsContainer}})] [Alias("DeviceID")] [Array]$DeviceIDs, [Parameter(Mandatory=$false)]$NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } } Process{ #Collect the data for all given IDs. ForEach ($DeviceID in $DeviceIDs){ $NcSession.DeviceGet($DeviceID)| Select-Object deviceid,longname,customerid,customername,deviceclass,licensemode,* -ErrorAction SilentlyContinue | Write-Output } } End{ } } Function Get-NCDeviceObject{ <# .Synopsis Returns a Device and all asset-properties as an object. .Description Returns a Device and all asset-properties as an object. The asset-properties may contain multiple entries. #> <# Work in Progress. Calls Ncentral_Connection.DeviceAssetInfoExportWithSettings Returns information as an [Array of] Multi-dimentional object(s) with array Properties. ToDo: Options to Include/Exclude properties from the N-Central query. Needed for Speed/Performance improvement. #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, # ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Existing Device IDs')] # [ValidateScript({ $_ | ForEach-Object {(Get-Item $_).PSIsContainer}})] [Alias("DeviceID")] [Array]$DeviceIDs, [Parameter(Mandatory=$false)]$NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } } Process{ #Collect the data for all IDs. ForEach ($DeviceID in $DeviceIDs){ $NcSession.DeviceAssetInfoExportDeviceWithSettings($DeviceID)| # Put General properties in front. # Select-Object deviceid,longname,customerid,deviceclass,* -ErrorAction SilentlyContinue | Write-Output } } End{ } } #EndRegion #Region Services and Tasks Function Get-NCActiveIssuesList{ <# .Synopsis Returns the Active Issues on the CustomerID-level and below. .Description Returns the Active Issues on the CustomerID-level and below. An additional Search/Filter-string can be supplied. If no customerID is supplied, Default Customer is used. The SiteID of the devices is returned (Not CustomerID). #> [CmdletBinding()] Param( [Parameter(Mandatory=$false, #ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Existing Customer ID')] [Int]$CustomerID, [Parameter(Mandatory=$false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 1, HelpMessage = 'Text to look for')] [String]$IssueSearchBy = "", [Parameter(Mandatory=$false)]$NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } If (!$CustomerID){ If (!$NcSession.DefaultCustomerID){ Write-Host "No CustomerID specified." Break } $CustomerID = $NcSession.DefaultCustomerID Write-Host ("Using current default CustomerID {0}." -f $CustomerID) } } Process{ $ReturnData = $NcSession.ActiveIssuesList($CustomerID, $IssueSearchBy) } End{ $ReturnData | ## Alphabetical Columnnames Select-Object ($ReturnData|Get-Member -type Noteproperty -ErrorAction SilentlyContinue).name -ErrorAction SilentlyContinue | ## Put important fields in front. Select-Object taskid,@{n="siteid"; e={$_.CustomerID}},CustomerName,DeviceID,DeviceName,DeviceClass,ServiceName,NotifState,TransitionTime,* -ErrorAction SilentlyContinue | # Sort-Object TransitionTime -Descending | Select-Object @{n="SiteID"; e={$_.CustomerID}},CustomerName,DeviceID,DeviceName,DeviceClass,ServiceName,TransitionTime,NotifState,* -ErrorAction SilentlyContinue | Write-Output } } Function Get-NCJobStatusList{ <# .Synopsis Returns the Scheduled Jobs on the CustomerID-level and below. .Description Returns the Scheduled Jobs on the CustomerID-level and below. Including Discovery Jobs If no customerID is supplied, all Jobs are returned. The SiteID of the devices is returned (Not CustomerID). #> [CmdletBinding()] Param( [Parameter(Mandatory=$false, #ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Existing Customer ID')] [Int]$CustomerID ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } If (!$CustomerID){ If (!$NcSession.DefaultCustomerID){ Write-Host "No CustomerID specified." Break } $CustomerID = $NcSession.DefaultCustomerID Write-Host ("Using current default CustomerID {0}." -f $CustomerID) } } Process{ $NcSession.JobStatusList($CustomerID)| Select-Object CustomerID,CustomerName,DeviceID,DeviceName,DeviceClass,JobName,ScheduledTime,* -ErrorAction SilentlyContinue | # Sort-Object ScheduledTime -Descending | Select-Object @{n="SiteID"; e={$_.CustomerID}},CustomerName,DeviceID,DeviceName,DeviceClass,ServiceName,TransitionTime,NotifState,* -ErrorAction SilentlyContinue | Write-Output } End{ } } Function Get-NCDeviceStatus{ <# .Synopsis Returns the Services for the DeviceID(s). .Description Returns the Services for the DeviceID(s). DeviceID(s) must be supplied, as a parameter or by PipeLine. #> [CmdletBinding()] Param( [Parameter(Mandatory=$true, # ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Existing Device IDs')] [Alias("DeviceID")] [Array]$DeviceIDs, [Parameter(Mandatory=$false)]$NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } } Process{ ForEach($DeviceID in $DeviceIDs){ $NcSession.DeviceGetStatus($DeviceID)| Select-Object deviceid,devicename,serviceid,modulename,statestatus,transitiontime,* -ErrorAction SilentlyContinue | Write-Output } } End{ } } #EndRegion #Region Access Control Function Get-NCAccessGroupList{ <# .Synopsis Returns the list of AccessGroups at the specified CustomerID level. .Description Returns the list of AccessGroups at the specified CustomerID level. #> [CmdletBinding()] Param( [Parameter(Mandatory=$false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Existing Customer ID')] [Int]$CustomerID, [Parameter(Mandatory=$false)]$NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } If (!$CustomerID){ If (!$NcSession.DefaultCustomerID){ Write-Host "No CustomerID specified." Break } $CustomerID = $NcSession.DefaultCustomerID Write-Host ("Using current default CustomerID {0}." -f $CustomerID) } } Process{ } End{ Write-Output $NcSession.AccessGroupList($CustomerID) } } Function Get-NCUserRoleList{ <# .Synopsis Returns the list of Roles at the specified CustomerID level. .Description Returns the list of Roles at the specified CustomerID level. #> [CmdletBinding()] Param( [Parameter(Mandatory=$false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Existing Customer ID')] [Int]$CustomerID, [Parameter(Mandatory=$false)]$NcSession ) Begin{ #check parameters. Use defaults if needed/available If (!$NcSession){ If (-not (NcConnected)){ Break } $NcSession = $Global:_NCSession } If (!$CustomerID){ If (!$NcSession.DefaultCustomerID){ Write-Host "No CustomerID specified." Break } $CustomerID = $NcSession.DefaultCustomerID Write-Host ("Using current default CustomerID {0}." -f $CustomerID) } } Process{ } End{ Write-Output $NcSession.UserRoleList($CustomerID) } } #EndRegion #EndRegion #Region Module management # Best practice - Export the individual Module-commands. Export-ModuleMember -Function Get-NCHelp, NcConnected, New-NCentralConnection, Get-NCTimeOut, Set-NCTimeOut, Get-NCServiceOrganizationList, Get-NCCustomerList, Set-NCCustomerDefault, Get-NCCustomerPropertyList, Set-NCCustomerProperty, Get-NCProbeList, Get-NCJobStatusList, Get-NCDeviceList, Get-NCDeviceID, Get-NCDeviceLocal, Get-NCDevicePropertyList, Get-NCDevicePropertyListFilter, Set-NCDeviceProperty, Get-NCActiveIssuesList, Get-NCDeviceInfo, Get-NCDeviceObject, Get-NCDeviceStatus, Get-NCAccessGroupList, Get-NCUserRoleList, Get-NCVersion Write-Debug "Module PS-NCentral loaded" #EndRegion |