├── APIv2
└── README.md
├── GetCDPFromAPI
├── GetCustomerListwithSites-Prompted.ps1
├── GetDeviceInfor-Prompted.ps1
├── GetFilteredDevicesPrinterInfo-Prompted.ps1
└── README.md
/APIv2/README.md:
--------------------------------------------------------------------------------
1 | # How To: N-Central API Automation
2 |
3 | ## Table of Content
4 |
5 | - [How To: N-Central API Automation](#how-to--n-central-api-automation)
6 | * [Table of Content](#table-of-content)
7 | - [Overview](#overview)
8 | - [Connecting](#connecting)
9 | * [PS-NCentral](#ps-ncentral)
10 | + [Multiple PS-NCentral server connections](#multiple-ps-ncentral-server-connections)
11 | * [PowerShell WebserviceProxy](#powershell-webserviceproxy)
12 | - [Performing Queries](#performing-queries)
13 | * [PS-NCentral](#ps-ncentral-1)
14 | + [Advanced PS-NCentral querying](#advanced-ps-ncentral-querying)
15 | * [PowerShell WebserviceProxy](#powershell-webserviceproxy-1)
16 | + [Bind to the namespace, using the Webserviceproxy](#bind-to-the-namespace--using-the-webserviceproxy)
17 | - [Updating a Value](#updating-a-value)
18 | * [PS-NCentral](#ps-ncentral-2)
19 | + [Updating with pipelining](#updating-with-pipelining)
20 | + [Updating Custom Device Properties](#updating-custom-device-properties)
21 | + [Custom Property options](#custom-property-options)
22 | - [Encoding](#encoding)
23 | - [Comma-Separated Values](#comma-separated-values)
24 | - [Format-properties](#format-properties)
25 | * [PowerShell WebserviceProxy](#powershell-webserviceproxy-2)
26 | + [Registration token injection](#registration-token-injection)
27 | + [Gather organization property ID](#gather-organization-property-id)
28 | + [Update customer property](#update-customer-property)
29 | + [Add new a new Customer](#add-new-a-new-customer)
30 | - [Appendix A – N-Central Web Service members](#appendix-a---n-central-web-service-members)
31 | - [Appendix B - PS-NCentral cmdlets](#appendix-b---ps-ncentral-cmdlets)
32 | - [Appendix C – GetAllCustomerProperties.ps1](#appendix-c---getallcustomerpropertiesps1)
33 | - [Appendix D – Customer Property variables](#appendix-d---customer-property-variables)
34 | - [Appendix E - All PS-Central Methods](#appendix-e---all-ps-central-methods)
35 | - [Appendix F - Common Error Codes](#appendix-f---common-error-codes)
36 | - [Appendix G - Issue Status](#appendix-g---issue-status)
37 | - [Appendix H - WebserviceProxy Alternative](#appendix-h---webserviceproxy-alternative)
38 | - [Credits](#credits)
39 |
40 | Table of contents generated with markdown-toc
41 |
42 |
43 | # Overview
44 |
45 | N-Central's API is a flexible, programmatic, object oriented, Java based interface by which developers can achieve integration and automation via native SOAP API calls.
46 |
47 | For the purposes of this guide we'll be covering connectivity and basic usage with PowerShell based automation through the PS-NCentral module, as well as native WebserviceProxy cmdlet.
48 |
49 | The information covering the PS-NCentral is useful for those with starting some experience with PowerShell or need to quickly put together code where module dependency isn't an issue, while the usage of the WebserviceProxy method is for those more familiar with object oriented coding or need code portatability. As of version 1.2 PS-NCentral uses PowerShell 7 for cross compatability to be able to run Windows/Linux or in an Azure function.
50 |
51 | PS-NCentral provides cmdlets for 17 Get cmdlets and 4 Set cmdlets (See Appendix B) that cover the majority, so should cover the majority of automation. This can be downloaded from: [https://github.com/ToschAutomatisering/PS-NCentral](https://github.com/ToschAutomatisering/PS-NCentral)
52 |
53 | Or installed from PS-Gallery with the cmdlet
54 |
55 | ```powershell
56 | Install-Module PS-NCentral
57 | ```
58 |
59 | # Connecting
60 |
61 | The first step required before connecting is to create a new automation account with appropriate role permissions. With N-Central 2020 or 12.3 HF4 and later you must **disable the MFA** requirement for the account, so use a long and complex password. The (preferred) API-Only account in N-Central 2021 needs to be set to \'mfa not needed\'.
62 |
63 | Once the account is created, select the API Authentication tab and click on the ' **Generate JSON Web Token**' button, save this **JWT** token somewhere secure, if you lose your JWT, you can generate another one at any time, but it will invalidate the previous one. If you update/change role permissions for the account automation account you will need to regenerate the token, as the asserted permissions are in the JWT.
64 |
65 | Note: Activating the MFA-setting after generating the token still blocks JWT-access, as well as an expired password for the originating account (90 days default).
66 |
67 | ## PS-NCentral
68 |
69 | Connecting to your N-Central service with PS-NCentral only needs to be done once per session. You first require the following information:
70 |
71 | - The fqdn of your N-Central server, ie: `n-central.mydomain.com`
72 | - The JWT from above
73 | - Username/Password (no MFA) for versions **before 1.2**.
74 |
75 | Then enter the following:
76 |
77 | **All versions**
78 |
79 | ```powershell
80 | #Import the PS-NCentral module
81 | import-module .\PS-NCentral.psm1 -Verbose
82 |
83 | #$credential = Get-Credential ## This line can be used for a dialog. Skip 2 below.
84 | $password = ConvertTo-SecureString "" -AsPlainText -Force
85 | $credential = New-Object System.Management.Automation.PSCredential ("", $password)
86 |
87 | #Connect to NC
88 | New-NCentralConnection -ServerFQDN "YOUR SERVER FQDN" -PSCredential $credential
89 | ```
90 |
91 | \* Might generate an error on some complex passwords. Avoid using a ^.
92 |
93 | **Version 1.2 and later**
94 |
95 | ```powershell
96 | #Import the PS-NCentral module
97 | import-module .\PS-NCentral.psm1 -Verbose
98 |
99 | #Connect to NC using the JWT directly
100 | New-NCentralConnection -ServerFQDN "YOUR SERVER FQDN" -JWT "YOUR JWT TOKEN"
101 | ```
102 |
103 | which is equivalent to:
104 |
105 | ```powershell
106 | #Import the PS-NCentral module
107 | import-module .\PS-NCentral.psm1 -Verbose
108 |
109 | #Credentials with JWT
110 | $password = ConvertTo-SecureString "YOUR JWT TOKEN" -AsPlainText -Force
111 | $credential = New-Object System.Management.Automation.PSCredential ("_JWT", $password)
112 |
113 | #Connect to NC
114 | New-NCentralConnection -ServerFQDN "YOUR SERVER FQDN" -PSCredential $credential
115 | ```
116 | If successful you will get an output similar to the below:
117 |
118 | |Property | Value|
119 | |--------|-----|
120 | | ConnectionURL | `n-central.mydomain.com` |
121 | | BindingURL | `https://n-central.mydomain.com/dms2/services2/ServerEI2?wsdl' |
122 | | AllProtocols | tls12,tls13 |
123 | | IsConnected | True |
124 | | RequestTimeOut | 100 |
125 | | NCVersion | 2020.1.5.425 |
126 | | DefaultCustomerID | 50 |
127 | | Error | |
128 |
129 | The session is now stored in the global **$\_NCSession** variable, and will automatically be used as default for following PS-NCentral commands.
130 |
131 | ### Multiple PS-NCentral server connections
132 |
133 | If you are an MSP with multiple N-Central servers, or have an NFC server for testing you can leverage the **-NCSession** parameter available on PS-NCentral cmdlets to quickly call other servers, this is available in all versions of PS-NCentral, but we'll use 1.2 as the example for brevity.
134 |
135 | Then enter the following:
136 | ```powershell
137 | #Connect to NC
138 | $Connection1 = New-NCentralConnection "$NCentralFQDN1" -JWT "$JWT1"
139 | $Connection2 = New-NCentralConnection "$NCentralFQDN2" -JWT "$JWT2"
140 |
141 | #Get the customer list from each server for later processing
142 | $NC1Customers = Get-NCCustomerList -NcSession $Connection1
143 | $NC2Customers = Get-NCCustomerList -NcSession $Connection2
144 | ```
145 |
146 | Another useful pameter when connecting is the **DefaultCustomerID**, this sets the default scope for when calling cmdlets such as Get-NCDeviceList without a parameter, so if I were to perform the following connection and function call it would only give me all devices associated with CustomerID 333
147 |
148 | ``` powershell
149 | New-NCentralConnection "$NCentralFQDN" -JWT "$JWT1" -DefaultCustomerID 333
150 | $Customer333Devices = Get-NCDeviceList
151 | ```
152 |
153 | You can use **Set-NCCustomerDefault** to change the value afterwards.
154 |
155 | ## PowerShell WebserviceProxy
156 |
157 | Notice the WebserviceProxy is discontinued after PowerShell version 5.1. You can find alternative code in [Appendix H - WebserviceProxy Alternative](#appendix-h---webserviceproxy-alternative)
158 |
159 |
160 | As a preface to the usage of the New-WebserviceProxy cmdlet, we will focus on the v2 rather than v1 legacy API as the v1 endpoint maybe deprecated at some point.
161 |
162 | The main differences between the v1 and v2 endpoints are:
163 |
164 | - The WSDL endpoint
165 | - Different classes, including the KeyPair constructor class used for adding custom settings for queries and update/change methods
166 | - V2 has all the newer methods available
167 |
168 | It will be necessary to review the Javadocs provided on your server for the lastest information on the classes and constructors, you can find them under your own N-Central server under `https://n-central.mydomain.com/dms/`
169 |
170 | If reviewing other WebserviceProxy powershell code on the internet, you can identify **v1**/legacy code as it will have the following in the binding URL string: **/dms/services/ServerEI?wsdl** while **v2** has **/dms2/services2/ServerEI2?wsdl**
171 |
172 | For connecting to webservice you will need the same information as with the PS-NCentral which connects in the same way underneath:
173 |
174 | - The fqdn of your N-Central server, ie: n-central.myserver.com
175 | - The JWT for the account
176 |
177 | With our examples we'll use v2 connections and classes, below is a common method seen in examples:
178 | ```powershell
179 | #Example host
180 | $serverHost = "n-central.myserver.com"
181 |
182 | # Bind to the namespace, using the Webserviceproxy
183 | $NWSNameSpace = "NAble" + ([guid]::NewGuid()).ToString().Substring(25)
184 | $bindingURL = "https://" + $serverHost + "/dms2/services2/ServerEI2?wsdl"
185 | $nws = New-Webserviceproxy $bindingURL -Namespace ($NWSNameSpace)
186 | ```
187 |
188 | ```$NWSNameSpace``` here can be most anything of your choosing, the point of the GUID generation is to ensure the namespace for the classes to be used inside the webservice are _unique_ to anything else on your system or current context, you could use a static namespace such as MyNCentralConnection or PowerShellIsAwesome.
189 |
190 | After you've run this the $nws variable will contain all the available public methods from the endpoint, you can interrogate this by running
191 | ```powershell
192 | $nws | Get-Member
193 | ```
194 | From this you will see a lot of | Event |s, Methods and Properties ie.
195 |
196 | |Name | MemberType |
197 | |----| ----------|
198 | |versionInfoGetCompleted || Event ||
199 | | Abort| Method |
200 | | accessGroupAdd | Method |
201 | | BeginaccessGroupAdd | Method |
202 | | BeginaccessGroupGet | Method |
203 |
204 |
205 | The above output has been shortened, see [Appendix A – N-Central Web Service members](#appendix-a---n-central-web-service-members) members for the complete output. In addition you will have a **Definition** column, and you will observe that your `$NWSNameSpace` is seen prefixed to the methods/classes noted in them. All classes/methods/constructors available in the Javadocs can be created and called upon through the `$nws` variable. Eg. The customerListmethod would be called with
206 |
207 | ```powershell
208 | $nws.customerList("", $JWT, $settings)
209 | ```
210 |
211 | As you will note when connecting with the `$nws` variable, at no point did you use your username or JWT, as you will observe in the `$nws.customerList` method called above, the $JWT is used in every get or set, and the username is simply `""` as the username is inside of the JWT string.
212 |
213 | Underneath the PS-NCentral module it saves these variables with each connection and re-uses each time a cmdlet is used.
214 |
215 | # Performing Queries
216 |
217 | ## PS-NCentral
218 |
219 | Performing queries with the PS-Central module is quick and easy, and several examples are provided in it's own documentation [here](https://github.com/ToschAutomatisering/PS-NCentral/blob/master/PS-NCentral_Examples.ps1) . The outcomes of the examples are fairly self explanatory. For our example we'll take a common query like the Customer table and join it with the Organisation properties table using the PS-NCentral cmdlets, then in the advanced section we'll give the same example using native cmdlets.
220 | ```powershell
221 | Import-Module PS-NCentral.psm1 -Verbose
222 |
223 | $ServerFQDN = n-central.myserver.com
224 | $JWT = "JWT TOKEN"
225 |
226 | #Connect to NC
227 | New-NCentralConnection -ServerFQDN $ServerFQDN -JWT $JWT
228 |
229 | #Grab the customer list/details
230 | $CustomerList = Get-NCCustomerList
231 |
232 | #Get the customer properties
233 | $CustomerPropertyList = Get-NCCustomerPropertyList
234 |
235 | #Create array list for table
236 | $CustomerReport = New-Object System.Collections.ArrayList
237 |
238 | #Merge
239 | foreach ($Customer in $CustomerList) {
240 | $Properties = $CustomerPropertyList | ?{$_.CustomerID -eq $Customer.customerid}
241 | $CustomerHashtable = [Ordered]@{}
242 | $Customer.psobject.properties | ?{$_.Name -ne 'customerid'} | %{$CustomerHashtable[$_.Name] = $_.Value}
243 | $PropertiesHashTable = [Ordered]@{}
244 | $Properties.psobject.properties | %{$PropertiesHashtable[$_.Name] = $_.Value}
245 | $ReportItem = $CustomerHashtable + $PropertiesHashTable
246 | $ReportItem = [PSCustomObject]$ReportItem
247 | $CustomerReport.Add($ReportItem) > $Null
248 | }
249 |
250 | #Output the report to the screen/Gridview
251 | $CustomerReport | Out-GridView
252 | ```
253 |
254 | The important parts of this example are the simple one line calls for the **New-CentralConnection** , **Get-NCCustomerList** and **Get-NCCustomerPropertyList**. With very little effort we can connect, retrieve the data then process into a single table for review.
255 |
256 | ### Advanced PS-NCentral querying
257 | The PS-NCentral module provides ease of access to N-Central API calls with normal **verb-noun** functions, but you can also perform a direct call through the internal connection class. We could replace the above function calls with these methods:
258 |
259 | ```powershell
260 | # Connect to NC
261 | $NCSession = New-NCentralConnection -ServerFQDN $ServerFQDN -JWT $JWT
262 |
263 | # Grab the customer list/details
264 | $CustomerList = $NCSession.CustomerList()
265 |
266 | # Get the customer properties
267 | $CustomerPropertyList = $NCSession.OrganizationPropertyList()
268 | ```
269 |
270 | We can get the list of all the underlying class connection methods by enumerating the members with `$_NCSession | Get-Member -MemberType Method` to see all 'inside' methods, which reflect the API-methods of N-Central ('http://mothership.n-able.com/dms/javadoc_ei2/com/nable/nobj/ei2/ServerEI2_PortType.html') where applicable.
271 |
272 | Most methods have 'Overloads'. These are selected based on the parameter-pattern eg. `([String], [String])` or `([String],[Int])`.
273 |
274 | ```powershell
275 | #Get the devices for customerid 100
276 | $Customer100Devices = $NCSession.DeviceList(100)
277 | #or
278 | $Customer100Devices = $NCSession.DeviceList(100,$true,$false)
279 |
280 | #Get the probes for customerid 100
281 | $Customer100Probes = $NCSession.DeviceList(100,$false,$true)
282 | ```
283 |
284 | For a list of all methods see [Appendix E - All PS-Central Methods](#appendix-e---all-ps-central-methods)
285 |
286 | ## PowerShell WebserviceProxy
287 |
288 | In this section we'll perform the same example as above but using the native cmdlets we'll go through an example of a fully functioning cmdlet that uses native cmdlet calls.
289 |
290 | ```powershell
291 | # Define the command-line parameters to be used by the script
292 | [CmdletBinding()]
293 | Param(
294 | [Parameter(Mandatory = $true)]$serverHost,
295 | [Parameter(Mandatory = $true)]$JWT
296 | )
297 | ```
298 |
299 | Here we establish the mandatory variables we'll be using to connect, in this case the username of the automation account used, the server URI and the Java Web Token
300 |
301 | We'll then connect using a static namespace, you can equally use the pseudo-unique namespace above.
302 |
303 | ```powershell
304 | $NWSNameSpace = "NAbleAPI"
305 | ```
306 |
307 | ### Bind to the namespace, using the Webserviceproxy
308 | ```powershell
309 | $bindingURL = "https://" + $serverHost + "/dms2/services2/ServerEI2?wsdl"
310 | $nws = New-Webserviceproxy $bindingURL -Namespace ($NWSNameSpace)
311 | ```
312 | For many API calls a list of settings are required, in the case of the `CustomerList()` method we need to specify if the service organisation should be listed or not. The JavaDocs specify you have to use the `EiKeyValue` KeyPair type or array of `EiKeyValuesList` per the Javadocs, but it is simpler to create an ArrayList and add a generic hashtable Key/Pair that will be automatically cast to the `EiKeyValue`.
313 |
314 | ```powershell
315 | $settings = New-Object System.Collections.ArrayList
316 | $settings.Add(@{key = "listSOs"; value = "True" })
317 | ```
318 |
319 | Next we wrap the steps of retrieving the Customer List and Organisation properties list with a try/catch block that exits if there is an error with retrieving the data.
320 | ```powershell
321 | #Attempt to connect
322 | Try {
323 | $CustomerList = $nws.customerList("", $JWT, $Settings)
324 | $OrgPropertiesList = $nws.organizationPropertyList("", $JWT, $null, $false)
325 | }
326 |
327 | Catch {
328 | Write-Host Could not connect: $($_.Exception.Message)
329 | exit
330 | }
331 | ```
332 |
333 | We then create a hash table of all the customer properties with the Customer ID as the Key and the Properties as the value.
334 |
335 | ```powershell
336 | $OrgPropertiesHashTable = @{}
337 | foreach ($Org in $OrgPropertiesList) {
338 | $CustomerOrgProps = @{}
339 | foreach ($p in $Org.properties) { $CustomerOrgProps[$p.label] = $p.value }
340 | $OrgPropertiesHashTable[$Org.customerId] = $CustomerOrgProps
341 | }
342 | ```
343 |
344 | In the next step we take create an ArrayList in preference to a simple array to increase performance on inserts, then enumerate through the customer list match a custom list of tables and join it to the properties Hash table and output it to the screen.
345 |
346 | ```powershell
347 | #Create customer report ArrayList
348 | $CustomersReport = New-Object System.Collections.ArrayList
349 |
350 | ForEach ($Entity in $CustomerList) {
351 | $CustomerAssetInfo = @{}
352 | #Custom select the required columns, use Ordered to keep them in the order we list them in
353 |
354 | ForEach ($item in $Entity.items) { $CustomerAssetInfo[$item.key] = $item.Value }
355 | $o = [Ordered]@{
356 | ID = $CustomerAssetInfo["customer.customerid"]
357 | Name = $CustomerAssetInfo["customer.customername"]
358 | parentID = $CustomerAssetInfo["customer.parentid"]
359 | RegistrationToken = $CustomerAssetInfo["customer.registrationtoken"]
360 | }
361 |
362 | #Retrieve the properties for the given customer ID
363 | $p = $OrgPropertiesHashTable[[int]$CustomerAssetInfo[customer.customerid]]
364 |
365 | #Merge the two hashtables
366 | $o = $o + $p
367 |
368 | #Cast the hashtable to a PSCustomObject
369 | $o = [PSCustomObject]$o
370 |
371 | #Add the PSCustomObject to our CustomersReport ArrayList
372 | $CustomersReport.Add($o) > $null
373 | }
374 |
375 | #Output to the screen
376 | $CustomersReport | Out-GridView
377 | ```
378 |
379 | For the complete script see [Appendix C – GetAllCustomerProperties.ps1](#appendix-c---getallcustomerpropertiesps1)
380 |
381 |
382 |
383 | Note that **WebServiceProxy** is **discontinued** by Microsoft in PowerShell versions after 5.1. You can find alternative code in [Appendix H - WebserviceProxy Alternative](#appendix-h---webserviceproxy-alternative)
384 |
385 |
386 | # Updating a Value
387 |
388 | A common case for updating a value would be automating the update/change of Organisation or Device properties. Examples of Organisation properties could be: tokens/keys for MSP applications deployed to devices, the customer name to pass through to a script for output or the N-Central API registration token for installation of the agent. Updating these properties is straightforward with either the web proxy or PS-NCentral cmdlets.
389 |
390 | At time of writing the normal way for a Registration Token to be generated is through the UI, requiring an administrator to navigate to every _customer_ and every _site_ and click on the **Get Registration Token button** under **Download Agent/Probe** ; this will be changed in future.
391 |
392 | If you do need to perform mass registration token updating/refreshing there is an AMP provided as a part of the InstallAgent 6 suite that has a workaround and can be found at [https://github.com/AngryProgrammerInside/InstallAgent/tree/master/AMPs](https://github.com/AngryProgrammerInside/InstallAgent/tree/master/AMPs)
393 |
394 | ## PS-NCentral
395 |
396 | In the example for PS-NCentral we'll take the Customer name from the Get-NCCustomerList and inject it into _custom_ property called **Agent – Registration Token**, this is useful if we need to programmatically inject token information into files or registry settings for later use. We'll assume we already have a connection to N-Central:
397 |
398 | ```powershell
399 | $CustomerList = Get-NCCustomerList
400 | foreach ($Customer in $CustomerList){
401 | Set-NCCustomerProperty -CustomerIDs $Customer.customerid -PropertyLabel "Agent - RegistrationToken" -PropertyValue $Customer.registrationtoken
402 | }
403 | ```
404 |
405 | Or if we wanted to take the customer's name and inject it into a custom property like **Reporting – Customer Name** to inject it into an AMP's output for easier to identify the device AMPs run across a service organization:
406 |
407 | ```powershell
408 | $CustomerList = Get-NCCustomerList
409 |
410 | foreach ($Customer in $CustomerList){
411 | Set-NCCustomerProperty -CustomerIDs $Customer.customerid -PropertyLabel "Reporting – Customer Name" -PropertyValue $Customer.customername
412 | }
413 | ```
414 | An advantage of the Set-NCCustomerProperty cmdlet is that it can distinguish between the default _customer_ properties, ie. zip/postalcode, street1, externalid, externalid2 and will use the appropriate method to update that. You can find the list of key names in the Java Docs, or refer to **Appendix D – Customer Property variables**.
415 |
416 | For our example, you may have a PSA or perhaps a spreadsheet, and we want to refresh the information from that data source into _customer_ properties. In our example we'll use a spreadsheet/CSV as our datasource, and assume we have already matched the CustomerID with the company name and we have a dataset as below:
417 |
418 | | **customerid** | **firstname** | **lastname** | **email** |
419 | | --- | --- | --- | --- |
420 | | 1 | Claire | Young | Claire.Young@email.com |
421 | | 2 | Benjamin | Metcalfe | Bmetacalfe@usa.com |
422 | | 3 | Kimberly | King | kk@asia.com |
423 | | 4 | Michael | Mills | Mmills@engineer.com |
424 | | 5 | Anthony | Jackson | 008Jac@mail.com |
425 |
426 | \
427 | You could then update the respective values in N-Central
428 | ```powershell
429 | $custData = Import-CSV C:\Temp\customerData.csv
430 |
431 | foreach ($Customer in $custData){
432 | #Gather properties to update
433 | $Properties = $Customer.psobject.properties | ?{$_.Name -ne 'customerid'}
434 |
435 | foreach ($Property in $Properties){
436 | #Update the property
437 | Set-NCCustomerProperty -CustomerIDs $Customer.customerid -PropertyLabel $Property -PropertyValue $Property.Value
438 | }
439 | }
440 | ```
441 | ### Updating with pipelining
442 | Another advantage of PS-NCentral is that you can easily pipeline information through and set it as a customer property, in the first example we will update the **Reporting - Customer Name** again except this time utilising the pipe:
443 | ```powershell
444 | Get-NCCustomerList | Set-NCCustomerProperty -PropertyLabel 'Reporting – Customer Name' -PropertyValue $_.customername
445 | ```
446 |
447 | In the second example we may have a custom table from a CSV or other source that has the following properties and values:
448 |
449 | | **customerid** | **CustomerSLA** |
450 | | --- | --- |
451 | | 123 | 1H |
452 | | 124 | 4H |
453 | | 221 | 8H |
454 | | 233 | 8H |
455 | | 321 | 8H |
456 |
457 | \
458 | We then have this table in a variable `$CustomerProps` and use it to populate a custom property called **'Reporting - Customer SLA'**
459 | ```powershell
460 | Get-NCCustomerList |
461 | Select-Object customerid, @{n="CustomerSLA"; e={$CustomerID = $_.customerid; (@($CustomerProps).where({ $_.customerID -eq $CustomerID })).CustomerSLA}} `
462 | | Where-Object {$_.CustomerSLA} `
463 | | % { Set-NCCustomerProperty -CustomerIDs $_.CustomerID -PropertyLabel 'Reporting – Customer SLA' -PropertyValue ($_.CustomerSLA -join ',') }
464 | ```
465 | When multiple records for a customerid are found in $Customerprops all values will be added comma-separated.
466 |
467 | The important parts of this example are the table-lookup
468 |
469 | ```
470 | (@().where( -eq )).
471 | ```
472 |
473 | and the filter to only return objects which had values added
474 |
475 | ```
476 | Where-Object {$_.}
477 | ```
478 |
479 | before setting the properties.
480 |
481 | ### Updating Custom Device Properties
482 | Another example would be where we may want to populate a Custom Device Property, in this case **'External ID'** based upon the CustomerID using in a customer table `$Customers`
483 | | **customerid** | **ExternalID** |
484 | | --- | --- |
485 | | 123 | 78409377 |
486 | | 124 | 78405890 |
487 | | 221 | 78404905 |
488 | | 233 | 78402984 |
489 | | 321 | 38940384 |
490 |
491 | ```powershell
492 | Get-NCDeviceList | `
493 | Select-Object DeviceID, `
494 | @{n="ExternalID"; e={$CustomerID = $_.customerid; (@($Customers).where({ $_.customerID -eq $CustomerID })).ExternalID}} | `
495 | Where-Object {$_.ExternalID} | %{Set-NCDeviceProperty -DeviceIDs $_.DeviceID -PropertyLabel 'ExternalID' -PropertyValue ($_.ExternalID -join ',')}
496 | ```
497 |
498 |
499 |
500 | ### Custom Property options
501 |
502 | These options are introduced in PS-NCentral version **1.3**.
503 |
504 | #### Encoding
505 |
506 | Use the **-Base64** option to Encode/Decode a CustomProperty when using Set or Get. Unicode (utf16) by default, -utf8 option available.
507 |
508 | **Convert-Base64** is available as a seperate command too.
509 |
510 |
511 |
512 | #### Comma-Separated Values
513 |
514 | When a Custom Property holds a string of (unique) Comma-seperated values you can easily Add or Remove a single value with the commands:
515 |
516 | - Add-NCCustomerPropertyValue
517 | - Add-NCDevicePropertyValue
518 | - Remove-NCCustomerPropertyValue
519 | - Remove-NCDevicePropertyValue
520 |
521 | Use Get-help \ to see the options.
522 |
523 |
524 |
525 | #### Format-properties
526 |
527 | Sometimes not all objects in a list have the same properties. This can become an issue when using **Format-Table** or **Output-CSV**, which only use the properties of the first object in the list.
528 |
529 | The **Format-Properties** cmdlet ensures all unique properties are added to all objects in a list. It is integrated in several PS-NCentral list-commands but also available as a seperate command.
530 |
531 |
532 |
533 | ## PowerShell WebserviceProxy
534 |
535 | Updating customer properties and without the PS-NCentral cmdlets can take several additional steps as PS-NCentral takes care of some busy work underneath.
536 |
537 | ### Registration token injection
538 |
539 | Let's first take the example of injecting taking the registration token from the **customerList** method and injecting it via the **organizationPropertyModify** method. As above we'll assume we have a connection `$nws` already and our list of customers is in the variable $CustomerList, take note of the line where gathering the value of the custom property with the id **123456789**.
540 | ```powershell
541 | ForEach ($Entity in $CustomerList) {
542 | $CustomerAssetInfo = @{}
543 | ForEach ($item in $Entity.items) { $CustomerAssetInfo[$item.key] = $item.Value }
544 |
545 | #Create a custom object for the data
546 | $CustomerObject = [Ordered]@{
547 | ID = $CustomerAssetInfo[customer.customerid]
548 | Name = $CustomerAssetInfo[customer.customername]
549 | parentID = $CustomerAssetInfo[customer.parentid]
550 | RegistrationToken = $CustomerAssetInfo[customer.registrationtoken]
551 | }
552 |
553 | #Skip any Registration tokens that are null/empty
554 | if ($null -eq $CustomerObject.RegistrationToken -or -eq $CustomerObject.RegistrationToken) {continue}
555 |
556 | #Gather the property value for the specific property ID
557 | $CustomerProperty = ($OrgPropertiesList | ?{$_.customerId -eq $CustomerObject.ID}).properties | ?{$_.propertyid -eq 123456789}
558 | $CustomerProperty.value = $CustomerObject.RegistrationToken
559 |
560 | #Create a new OrganizationProperties object and populate it
561 | $ModOrgProperties = New-Object $NWSNameSpace.OrganizationProperties
562 | $ModOrgProperties.customerId = $CustomerObject.ID
563 | $ModOrgProperties.customerIdSpecified = $true
564 | $ModOrgProperties.properties = $CustomerProperty
565 |
566 | #Inject the property
567 | $nws.organizationPropertyModify("",$JWT,$ModOrgProperties)
568 | }
569 | ```
570 | ### Gather organization property ID
571 |
572 | While the above code works in updating the specific customer org property, one must first interrogate the properties and their associated values in advance. While this is fine for scripts where you will always be updating the same **propertyid** , you may wish to implement a function that takes care of searching and retrieving the **propertyid**.
573 |
574 | PS-NCentral cmdlets use a class to retrieve this, we can convert it to a function for our use:
575 | ```powershell
576 | function Get-OrganizationPropertyID(
577 | [Int]$OrganizationID,
578 | [String]$PropertyName,
579 | [String]$JWT,
580 | [System.Web.Services.Protocols.SoapHttpClientProtocol]$NcConnection){
581 |
582 | ## Returns 0 (zero) if not found.
583 | $OrganizationPropertyID = 0
584 | $results = $null
585 | Try{
586 | #Gets the organization and all custom properties
587 | $results = $NcConnection.OrganizationPropertyList("", $JWT, $OrganizationID, $false)
588 | }
589 | Catch {
590 | $_.ErrorHandler
591 | }
592 |
593 | #Search through all properties and match the one with the same name
594 | ForEach ($OrganizationProperty in $results.properties){
595 | If($OrganizationProperty.label -eq $PropertyName){
596 | $OrganizationPropertyID = $OrganizationProperty.PropertyID
597 | }
598 | }
599 | Return $OrganizationPropertyID
600 | }
601 | ```
602 | We can then use the function to gather the property ID
603 |
604 | ```powershell
605 | #Get the property id for org 123 with the property name Agent – Registration token
606 | Get-OrganizationPropertyID -OrganizationID 123 -PropertyName "Agent - Registration Token" -JWT $JWT -NcConnection $nws
607 | ```
608 |
609 | The author notes that at time of writing, the **propertyid** appears to be the same for all customers/sites created at the same hierarchical level (System/SO/Customer/Site). For cases where you have multiple service organizations with the same named custom property created at the SO level they should be a different propertyid.
610 |
611 | For single SO deployments where the custom properties are created at the SO level they are globally unique, you could also create a lookup table for optimising your code to avoid performing a **propertyid** lookup for each update of a custom property, though we won't be covering that in this document.
612 |
613 | ### Update customer property
614 |
615 | Updating a _customer_ property such as the contact details or externalid values is done through the **customerModify** method, the method is called with the form:
616 |
617 | ```customerModify([string]username,[string]password,[ListEiKeyValue]settings)```
618 |
619 | You may note in the PS-NCentral example it can update one property, either *custom* or customer, in a single call; whereas the KeyValue list can contain one or all of the customer values shown in [Appendix D – Customer Property variables](#appendix-d---customer-property-variables) to be updated in a single call.
620 |
621 | We'll use an expanded data set from the PS-NCentral as we have more mandatory fields **customername** , **customerid** and **parentid** that are otherwise looked up by an internal helper function in PS-NCentral:
622 |
623 | | parentid | customerid | customername | firstname | lastname | email |
624 | | --- | --- | --- | --- | --- | --- |
625 | | 50 | 1 | Contoso | Claire | Young | `Claire.Young@email.com` |
626 | | 50 | 2 | Volcano Coffee | Benjamin | Metcalfe | `Bmetacalfe@usa.com` |
627 | | 50 | 3 | Northwind Traders | Kimberly | King | `kk@asia.com` |
628 | | 50 | 4 | WW Importers | Michael | Mills | `Mmills@engineer.com` |
629 | | 50 | 5 | Blue Yonder | Anthony | Jackson | `008Jac@mail.com` |
630 |
631 | You can retrieve the mandatory fields mentioned in the above table by using the `CustomerList()` covered previously.
632 |
633 | In the below example the data is imported, then we generate the appropriate KeyValue array and assuming use the same $nwsconnection variable and $NWSNameSpace from previous examples to connect and update the modified keys.
634 | ```powershell
635 | $custData = Import-CSV C:\Temp\customerData.csv
636 | foreach ($Customer in $custData){
637 | #Gather properties to update
638 | $Properties = $Customer.psobject.properties
639 | #Create an Arraylist of HashTables to update
640 | $ModifiedKeyList = New-Object System.Collections.ArrayList
641 | $Properties | ForEach-Object{
642 | $KeyPair = @{}
643 | $KeyPair.key = $_.Name
644 | $KeyPair.value = $_.Value
645 | $ModifiedKeyList.Add($KeyPair)
646 | }
647 | $nws.customerModify("",$JWT,$ModifiedKeyList)
648 | }
649 | ```
650 | ### Add new a new Customer
651 |
652 | Not every cmdlet is currently available in PS-NCentral, one such cmdlet that could be useful is the automation of the creation of customer accounts. In the below example we use the ```$nws``` connection from before and pass through a hashtable of some of the customer properties in in [Appendix D – Customer Property variables](#appendix-d---customer-property-variables), note there are two required fields: **customername** and **parentid**
653 |
654 | Combining the hashtable `$newcustomer` with the `$JWT` and `$nws` to the cmdlet it will create the customer. It will return the new CustomerID value once the job is completed.
655 | ```powershell
656 | $newcustomer = @{
657 | customername = "New Customer"
658 | parentid = "50"
659 | firstname = "john"
660 | lastname = "doe"
661 | email = "john.doe@contoso.com"
662 | city = "Melbourne"
663 | telephone = "0312345678"
664 | country = "AU"
665 | }
666 |
667 | function Add-NCCustomer(
668 | [Hashtable]$CustomerTable,
669 | [String]$JWT,
670 | [System.Web.Services.Protocols.SoapHttpClientProtocol]$NcConnection) {
671 | $CustomerAttributeList = New-Object System.Collections.ArrayList
672 | foreach ($key in $CustomerTable.Keys){
673 | $setting = @{key = $key; value = $CustomerTable[$key]}
674 | $CustomerAttributeList.Add($setting) > $null
675 | }
676 | $NcConnection.customerAdd("", $JWT, $CustomerAttributeList)
677 | }
678 |
679 | Add-NCCustomer -CustomerTable $newcustomer -JWT $JWT -NcConnection $nws
680 | ```
681 |
682 | At time of writing with PS-NCentral version 1.2 it is possible to use the CustomerAdd() method as it is exists inside the core class object now. While there is currently no Powershell function to call this, create a customer with it in the following way:
683 |
684 | ```powershell
685 | #Connect to NC
686 | $NCSession = New-NCentralConnection -ServerFQDN n-central.myserver.com -JWT $JWT
687 | $ParentId = 50
688 | $NewCustomerAttributes = @{
689 | firstname = "john"
690 | lastname = "doe"
691 | email = "john.doe@contoso.com"
692 | city = "Melbourne"
693 | telephone = "0312345678"
694 | country = "AU"
695 | }
696 |
697 | $NCSession.CustomerAdd("NewCustomerName",$ParentId,$NewCustomerAttributes)
698 | ```
699 | You can also create the customer without attributes and fill them out later if you wish by simply calling `$NCSession.CustomerAdd("NewCustomerName",$ParentId)`
700 |
701 | This function will return the value for the new Customer ID, you can then use that Id to perform further automation if needed.
702 |
703 | # Appendix A – N-Central Web Service members
704 |
705 | |Name |MemberType|
706 | |---- |----------|
707 | |accessGroupAddCompleted | Event |
708 | |accessGroupGetCompleted | Event |
709 | |accessGroupListCompleted | Event |
710 | |acknowledgeNotificationCompleted | Event |
711 | |activeIssuesListCompleted | Event |
712 | |customerAddCompleted | Event |
713 | |customerDeleteCompleted | Event |
714 | |customerListChildrenCompleted | Event |
715 | |customerListCompleted | Event |
716 | |customerModifyCompleted | Event |
717 | |deviceAssetInfoExportDeviceCompleted | Event |
718 | |deviceAssetInfoExportDeviceWithSettingsCompleted | Event |
719 | |deviceGetCompleted | Event |
720 | |deviceGetStatusCompleted | Event |
721 | |deviceListCompleted | Event |
722 | |devicePropertyListCompleted | Event |
723 | |devicePropertyModifyCompleted | Event |
724 | |Disposed | Event |
725 | |jobStatusListCompleted | Event |
726 | |lastExportResetCompleted | Event |
727 | |organizationPropertyListCompleted | Event |
728 | |organizationPropertyModifyCompleted | Event |
729 | |psaCreateCustomTicketCompleted | Event |
730 | |psaCredentialsValidateCompleted | Event |
731 | |psaGetCustomTicketCompleted | Event |
732 | |psaReopenCustomTicketCompleted | Event |
733 | |psaResolveCustomTicketCompleted | Event |
734 | |SOAddCompleted | Event |
735 | |taskPauseMonitoringCompleted | Event |
736 | |taskResumeMonitoringCompleted | Event |
737 | |userAddCompleted | Event |
738 | |userRoleAddCompleted | Event |
739 | |userRoleGetCompleted | Event |
740 | |userRoleListCompleted | Event |
741 | |versionInfoGetCompleted | Event |
742 | |Abort | Method |
743 | |accessGroupAdd | Method |
744 | |accessGroupAddAsync | Method |
745 | |accessGroupGet | Method |
746 | |accessGroupGetAsync | Method |
747 | |accessGroupList | Method |
748 | |accessGroupListAsync | Method |
749 | |acknowledgeNotification | Method |
750 | |acknowledgeNotificationAsync | Method |
751 | |activeIssuesList | Method |
752 | |activeIssuesListAsync | Method |
753 | |BeginaccessGroupAdd | Method |
754 | |BeginaccessGroupGet | Method |
755 | |BeginaccessGroupList | Method |
756 | |BeginacknowledgeNotification | Method |
757 | |BeginactiveIssuesList | Method |
758 | |BegincustomerAdd | Method |
759 | |BegincustomerDelete | Method |
760 | |BegincustomerList | Method |
761 | |BegincustomerListChildren | Method |
762 | |BegincustomerModify | Method |
763 | |BegindeviceAssetInfoExportDevice | Method |
764 | |BegindeviceAssetInfoExportDeviceWithSettings | Method |
765 | |BegindeviceGet | Method |
766 | |BegindeviceGetStatus | Method |
767 | |BegindeviceList | Method |
768 | |BegindevicePropertyList | Method |
769 | |BegindevicePropertyModify | Method |
770 | |BeginjobStatusList | Method |
771 | |BeginlastExportReset | Method |
772 | |BeginorganizationPropertyList | Method |
773 | |BeginorganizationPropertyModify | Method |
774 | |BeginpsaCreateCustomTicket | Method |
775 | |BeginpsaCredentialsValidate | Method |
776 | |BeginpsaGetCustomTicket | Method |
777 | |BeginpsaReopenCustomTicket | Method |
778 | |BeginpsaResolveCustomTicket | Method |
779 | |BeginSOAdd | Method |
780 | |BegintaskPauseMonitoring | Method |
781 | |BegintaskResumeMonitoring | Method |
782 | |BeginuserAdd | Method |
783 | |BeginuserRoleAdd | Method |
784 | |BeginuserRoleGet | Method |
785 | |BeginuserRoleList | Method |
786 | |BeginversionInfoGet | Method |
787 | |CancelAsync | Method |
788 | |CreateObjRef | Method |
789 | |customerAdd | Method |
790 | |customerAddAsync | Method |
791 | |customerDelete | Method |
792 | |customerDeleteAsync | Method |
793 | |customerList | Method |
794 | |customerListAsync | Method |
795 | |customerListChildren | Method |
796 | |customerListChildrenAsync | Method |
797 | |customerModify | Method |
798 | |customerModifyAsync | Method |
799 | |deviceAssetInfoExportDevice | Method |
800 | |deviceAssetInfoExportDeviceAsync | Method |
801 | |deviceAssetInfoExportDeviceWithSettings | Method |
802 | |deviceAssetInfoExportDeviceWithSettingsAsync | Method |
803 | |deviceGet | Method |
804 | |deviceGetAsync | Method |
805 | |deviceGetStatus | Method |
806 | |deviceGetStatusAsync | Method |
807 | |deviceList | Method |
808 | |deviceListAsync | Method |
809 | |devicePropertyList | Method |
810 | |devicePropertyListAsync | Method |
811 | |devicePropertyModify | Method |
812 | |devicePropertyModifyAsync | Method |
813 | |Discover | Method |
814 | |Dispose | Method |
815 | |EndaccessGroupAdd | Method |
816 | |EndaccessGroupGet | Method |
817 | |EndaccessGroupList | Method |
818 | |EndacknowledgeNotification | Method |
819 | |EndactiveIssuesList | Method |
820 | |EndcustomerAdd | Method |
821 | |EndcustomerDelete | Method |
822 | |EndcustomerList | Method |
823 | |EndcustomerListChildren | Method |
824 | |EndcustomerModify | Method |
825 | |EnddeviceAssetInfoExportDevice | Method |
826 | |EnddeviceAssetInfoExportDeviceWithSettings | Method |
827 | |EnddeviceGet | Method |
828 | |EnddeviceGetStatus | Method |
829 | |EnddeviceList | Method |
830 | |EnddevicePropertyList | Method |
831 | |EnddevicePropertyModify | Method |
832 | |EndjobStatusList | Method |
833 | |EndlastExportReset | Method |
834 | |EndorganizationPropertyList | Method |
835 | |EndorganizationPropertyModify | Method |
836 | |EndpsaCreateCustomTicket | Method |
837 | |EndpsaCredentialsValidate | Method |
838 | |EndpsaGetCustomTicket | Method |
839 | |EndpsaReopenCustomTicket | Method |
840 | |EndpsaResolveCustomTicket | Method |
841 | |EndSOAdd | Method |
842 | |EndtaskPauseMonitoring | Method |
843 | |EndtaskResumeMonitoring | Method |
844 | |EnduserAdd | Method |
845 | |EnduserRoleAdd | Method |
846 | |EnduserRoleGet | Method |
847 | |EnduserRoleList | Method |
848 | |EndversionInfoGet | Method |
849 | |Equals | Method |
850 | |GetHashCode | Method |
851 | |GetLifetimeService | Method |
852 | |GetType | Method |
853 | |InitializeLifetimeService | Method |
854 | |jobStatusList | Method |
855 | |jobStatusListAsync | Method |
856 | |lastExportReset | Method |
857 | |lastExportResetAsync | Method |
858 | |organizationPropertyList | Method |
859 | |organizationPropertyListAsync | Method |
860 | |organizationPropertyModify | Method |
861 | |organizationPropertyModifyAsync | Method |
862 | |psaCreateCustomTicket | Method |
863 | |psaCreateCustomTicketAsync | Method |
864 | |psaCredentialsValidate | Method |
865 | |psaCredentialsValidateAsync | Method |
866 | |psaGetCustomTicket | Method |
867 | |psaGetCustomTicketAsync | Method |
868 | |psaReopenCustomTicket | Method |
869 | |psaReopenCustomTicketAsync | Method |
870 | |psaResolveCustomTicket | Method |
871 | |psaResolveCustomTicketAsync | Method |
872 | |SOAdd | Method |
873 | |SOAddAsync | Method |
874 | |taskPauseMonitoring | Method |
875 | |taskPauseMonitoringAsync | Method |
876 | |taskResumeMonitoring | Method |
877 | |taskResumeMonitoringAsync | Method |
878 | |ToString | Method |
879 | |userAdd | Method |
880 | |userAddAsync | Method |
881 | |userRoleAdd | Method |
882 | |userRoleAddAsync | Method |
883 | |userRoleGet | Method |
884 | |userRoleGetAsync | Method |
885 | |userRoleList | Method |
886 | |userRoleListAsync | Method |
887 | |versionInfoGet | Method |
888 | |versionInfoGetAsync | Method |
889 | |AllowAutoRedirect | Property |
890 | |ClientCertificates | Property |
891 | |ConnectionGroupName | Property |
892 | |Container | Property |
893 | |CookieContainer | Property |
894 | |Credentials | Property |
895 | |EnableDecompression | Property |
896 | |PreAuthenticate | Property |
897 | |Proxy | Property |
898 | |RequestEncoding | Property |
899 | ||Site | Property |
900 | |SoapVersion | Property |
901 | |Timeout | Property |
902 | |UnsafeAuthenticatedConnectionSharing | Property |
903 | |Url | Property |
904 | |UseDefaultCredentials | Property |
905 | |UserAgent | Property |
906 |
907 | # Appendix B - PS-NCentral cmdlets
908 |
909 | | Command | Synopsis |
910 | | --- | --- |
911 | | Get-NCAccessGroupList | Returns the list of AccessGroups at the specified CustomerID level. |
912 | | Get-NCActiveIssuesList | Returns the Active Issues on the CustomerID-level and below. |
913 | | Get-NCCustomerList | Returns a list of all customers and their data. ChildrenOnly when CustomerID is specified. |
914 | | Get-NCCustomerPropertyList | Returns a list of all Custom-Properties for the selected CustomerID(s). |
915 | | Get-NCDeviceID | Returns the DeviceID(s) for the given DeviceName(s). Case Sensitive, No Wildcards. |
916 | | Get-NCDeviceInfo | Returns the General details for the DeviceID(s). |
917 | | Get-NCDeviceList | Returns the Managed Devices for the given CustomerID(s) and Sites below. |
918 | | Get-NCDeviceLocal | Returns the DeviceID, CustomerID and some more Info for the Local Computer. |
919 | | Get-NCDeviceObject | Returns a Device and all asset-properties as an object. |
920 | | Get-NCDevicePropertyList | Returns the Custom Properties of the DeviceID(s). |
921 | | Get-NCDevicePropertyListFilter | Returns the Custom Properties of the Devices within the Filter(s). |
922 | | Get-NCDeviceStatus | Returns the Services for the DeviceID(s). |
923 | | Get-NCHelp | Shows a list of available PS-NCentral commands and the synopsis. |
924 | | Get-NCJobStatusList | Returns the Scheduled Jobs on the CustomerID-level and below. |
925 | | Get-NCProbeList | Returns the Probes for the given CustomerID(s). |
926 | | Get-NCServiceOrganizationList | Returns a list of all ServiceOrganizations and their data. |
927 | | Get-NCTimeOut | Returns the max. time in seconds to wait for data returning from a (Synchronous) NCentral API-request. |
928 | | Get-NCUserRoleList | Returns the list of Roles at the specified CustomerID level. |
929 | | NcConnected | Checks or initiates the NCentral connection. |
930 | | New-NCentralConnection | Connect to the NCentral server. |
931 | | Set-NCCustomerProperty | Fills the specified property(name) for the given CustomerID(s). |
932 | | Set-NCDeviceProperty | Fills the Custom Property for the DeviceID(s). |
933 | | Set-NCTimeOut | Sets the max. time in seconds to wait for data returning from a (Synchronous) NCentral API-request. |
934 |
935 |
936 | # Appendix C – GetAllCustomerProperties.ps1
937 |
938 | ```powershell
939 | # Define the command-line parameters to be used by the script
940 | [CmdletBinding()]
941 | Param(
942 | [Parameter(Mandatory = $true)]$serverHost,
943 | [Parameter(Mandatory = $true)]$JWT
944 | )
945 | # Generate a pseudo-unique namespace to use with the New-WebServiceProxy
946 | $NWSNameSpace = NAble + ([guid]::NewGuid()).ToString().Substring(25)
947 |
948 | # Bind to the namespace, using the Webserviceproxy
949 | $bindingURL = "https://" + $serverHost + "/dms2/services2/ServerEI2?wsdl"
950 | $nws = New-Webserviceproxy $bindingURL -Namespace ($NWSNameSpace)
951 |
952 | # Set up and execute the query
953 | $Settings = New-Object System.Collections.ArrayList
954 | $Settings.Add(@{key = "listSOs"; value = "True" })
955 |
956 | #Attempt to connect
957 | Try {
958 | $CustomerList = $nws.customerList("", $JWT, $Settings)
959 | $OrgPropertiesList = $nws.organizationPropertyList("", $JWT, $null, $false)
960 | }
961 | Catch {
962 | Write-Host Could not connect: $($_.Exception.Message)
963 | exit
964 | }
965 |
966 | $OrgPropertiesHashTable = @{}
967 | foreach ($Org in $OrgPropertiesList) {
968 | $CustomerOrgProps = @{}
969 | foreach ($p in $Org.properties) { $CustomerOrgProps[$p.label] = $p.value }
970 | $OrgPropertiesHashTable[$Org.customerId] = $CustomerOrgProps
971 |
972 | }
973 |
974 | #Create customer report ArrayList
975 | $CustomersReport = New-Object System.Collections.ArrayList
976 | ForEach ($Entity in $CustomerList) {
977 | $CustomerAssetInfo = @{}
978 |
979 | #Custom select the required columns, us Ordered to keep them in the order we list them in
980 | ForEach ($item in $Entity.items) { $CustomerAssetInfo[$item.key] = $item.Value }
981 | $o = [Ordered]@{
982 | ID = $CustomerAssetInfo[customer.customerid]
983 | Name = $CustomerAssetInfo[customer.customername]
984 | parentID = $CustomerAssetInfo[customer.parentid]
985 | RegistrationToken = $CustomerAssetInfo[customer.registrationtoken]
986 | }
987 |
988 | #Retrieve the properties for the given customer ID
989 | $p = $OrgPropertiesHashTable[[int]$CustomerAssetInfo[customer.customerid]]
990 |
991 | #Merge the two hashtables
992 | $o = $o + $p
993 | #Cast the hashtable to a PSCustomObject
994 | $o = [PSCustomObject]$o
995 |
996 | #Add the PSCustomObject to our CustomersReport ArrayLIst
997 | $CustomersReport.Add($o) > $null
998 | }
999 |
1000 | #Output to the screen
1001 | $CustomersReport | Out-GridView
1002 | ```
1003 |
1004 | # Appendix D – Customer Property variables
1005 |
1006 | These are the default properties returned in the customerlist. After connecting using PS-NCentral this list can also be found in the customervalidation property.
1007 |
1008 | ```powershell
1009 | $_ncsession.customervalidation
1010 | ```
1011 |
1012 | - **postalcode** - (Value) Customer's zip/ postal code.
1013 | - **street1** - (Value) Address line 1 for the customer. Maximum of 100 characters.
1014 | - **street2** - (Value) Address line 2 for the customer. Maximum of 100 characters.
1015 | - **city** - (Value) Customer's city.
1016 | - **stateprov** - (Value) Customer's state/ province.
1017 | - **phone** - (Value) Phone number of the customer.
1018 | - **country** - (Value) Customer's country. Two character country code, see http://en.wikipedia.org/wiki/ISO\_3166-1\_alpha-2 for a list of country codes.
1019 | - **externalid** - (Value) An external reference id.
1020 | - **externalid2** - (Value) A second external reference id.
1021 | - **contactfirstname** - (Value) Customer contact's first name.
1022 | - **contactlastname** - (Value) Customer contact's last name.
1023 | - **contacttitle** - (Value) Customer contact's title.
1024 | - **contactdepartment** - (Value) Customer contact's department.
1025 | - **contactphonenumber** - (Value) Customer contact's telephone number.
1026 | - **contactext** - (Value) Customer contact's telephone extension.
1027 | - **contactemail** - (Value) Customer contact's email. Maximum of 100 characters.
1028 | - **registrationtoken** - (ReadOnly) For agent/probe-install validation.
1029 | - **licensetype** - (Value) The default license type of new devices for the customer. Must be Professional or Essential. Default is Essential.
1030 |
1031 | # Appendix E - All PS-Central Methods
1032 | | Name |
1033 | | --- |
1034 | |AccessGroupGet|
1035 | |AccessGroupList|
1036 | |ActiveIssuesList|
1037 | |Connect|
1038 | |CustomerAdd|
1039 | |CustomerList|
1040 | |CustomerListChildren|
1041 | |CustomerModify|
1042 | |DeviceAssetInfoExportDevice|
1043 | |DeviceAssetInfoExportDeviceWithSettings|
1044 | |DeviceGet|
1045 | |DeviceGetAppliance|
1046 | |DeviceGetStatus|
1047 | |DeviceList|
1048 | |DevicePropertyID|
1049 | |DevicePropertyList|
1050 | |DevicePropertyModify|
1051 | |Equals|
1052 | |ErrorHandler|
1053 | |GetHashCode|
1054 | |GetType|
1055 | |JobStatusList|
1056 | |OrganizationPropertyID|
1057 | |OrganizationPropertyList|
1058 | |OrganizationPropertyModify|
1059 | |ProcessData1|
1060 | |ProcessData2|
1061 | |ToString|
1062 | |UserRoleGet|
1063 | |UserRoleList|
1064 |
1065 | # Appendix F - Common Error Codes
1066 |
1067 | \# Connection-error (https): There was an error downloading ..
1068 |
1069 | \# 1012 - Thrown when mandatory settings are not present in "settings".
1070 |
1071 | \# 2001 - Required parameter is null - Thrown when null values are entered as inputs.
1072 |
1073 | \# 2001 - Unsupported version - Thrown when a version not specified above is entered as input.
1074 |
1075 | \# 2001 - Thrown when a bad username-password combination is input, or no PSA integration has been set up.
1076 |
1077 | \# 2100 - Thrown when invalid MSP N-central credentials are input.
1078 |
1079 | \# 2100 - Thrown when MSP-N-central credentials with MFA are used.
1080 |
1081 | \# 3010 - Maximum number of users reached.
1082 |
1083 | \# 3012 - Specified email address is already assigned to another user.
1084 |
1085 | \# 3014 - Creation of a user for the root customer (CustomerID 1) is not permitted.
1086 |
1087 | \# 3014 - When adding a user, must not be an LDAP user.
1088 |
1089 | \# 3020 - Account is locked
1090 |
1091 | \# 3022 - Customer/Site already exists.
1092 |
1093 | \# 3026 - Customer name length has exceeded 120 characters.
1094 |
1095 | \# 4000 - SessionID not found or has expired.
1096 |
1097 | \# 5000 - An unexpected exception occurred.
1098 |
1099 | \# 5000 - Query failed.
1100 |
1101 | \# 5000 - javax.validation.ValidationException: Unable to validate UI session --> often an expired password, even when using JWT.
1102 |
1103 | \# 9910 - Service Organization already exists.
1104 |
1105 |
1106 |
1107 | # Appendix G - Issue Status
1108 |
1109 | These codes can be used with the **-IssueStatus** option of the **Get-NCActiveIssuesList** command. In v1.3 code 1 and 5 naming was incorrect (swapped)
1110 |
1111 | ```
1112 | 1 No Data
1113 | 2 Stale
1114 | 3 Normal --> Nothing returned
1115 | 4 Warning
1116 | 5 Failed
1117 | 6 Misconfigured
1118 | 7 Disconnected
1119 |
1120 | 11 Unacknowledged
1121 | 12 Acknowledged
1122 | ```
1123 |
1124 | The API does not allow combinations of these filters.
1125 |
1126 | - **1-7** are reflected in the **notifstate**-property.
1127 | - **11** and **12** relate to the properties **numberofactivenotification** and **numberofacknowledgednotification**.
1128 |
1129 |
1130 |
1131 | # Appendix H - WebserviceProxy Alternative
1132 |
1133 | The command **WebServiceProxy** is **discontinued** by Microsoft in PowerShell versions after 5.1. Below you can find an example of retrieving data with **Invoke-RestMethod** and compare it to the use of WebserviceProxy.
1134 |
1135 | ```PowerShell
1136 | ## Retrieving data from N-Central by SOAP-API
1137 |
1138 | # Settings
1139 | $Servername = "ServerFQDN"
1140 | $UserName = "API-User-noMFA" ## Or "" when using JWT
1141 | $Password = "P@ssword" ## Or JWT (preferred)
1142 |
1143 | # Function for retrieving data without Webserviceproxy.
1144 | # Works for most (but not all!!) Methods in
1145 | # https://mothership.n-able.com/dms/javadoc_ei2/com/nable/nobj/ei2/ServerEI2_PortType.html
1146 | # Note: Complex passwords may contain characters that invalidate the SOAP-request.
1147 | Function GetNCData([String]$APIMethod,[String]$Username,[String]$PassOrJWT,$KeyPairs){
1148 |
1149 | ## Process Keys
1150 | $MyKeys=""
1151 | ForEach($KeyPair in $KeyPairs){
1152 | $MyKeys = $MyKeys + ("
1153 |
1154 | {0}
1155 | {1}
1156 | " -f ($KeyPair.Key),($KeyPair.Value))
1157 | }
1158 |
1159 | ## Build SoapRequest (last line must be left-lined for terminating @")
1160 | $MySoapRequest =(@"
1161 |
1162 |
1163 |
1164 |
1165 | {1}
1166 | {2}{3}
1167 |
1168 |
1169 |
1170 | "@ -f $APIMethod, $Username, $PassOrJWT, $MyKeys)
1171 | #Write-Host $MySoapRequest ## For Debug/Educational purpose
1172 |
1173 | ## Request DataSet
1174 | $FullResponse = $null
1175 | Try{
1176 | $FullResponse = Invoke-RestMethod -Uri $BindingURL -body $MySoapRequest -Method POST
1177 | }
1178 | Catch{
1179 | Write-Host ("Could not connect: {0}." -f $_.Exception.Message )
1180 | exit
1181 | }
1182 |
1183 | ## Process Returned DataSet
1184 | $ReturnClass = $FullResponse.envelope.body | Get-Member -MemberType Property
1185 | $ReturnProperty = $ReturnClass[0].Name
1186 |
1187 | Return $FullResponse.envelope.body.$ReturnProperty.return
1188 | }
1189 | # End of Function GetNCData
1190 |
1191 | #Start of Main Script
1192 | # Extract local configuration Info.
1193 | $ApplianceConfig = ("{0}\N-able Technologies\Windows Agent\config\ApplianceConfig.xml" -f ${Env:ProgramFiles(x86)})
1194 | # Get appliance id
1195 | $ApplianceXML = [xml](Get-Content -Path $ApplianceConfig)
1196 | $ApplianceID = $ApplianceXML.ApplianceConfig.ApplianceID
1197 |
1198 | # Prepare Connection
1199 | $BindingURL = ("https://{0}/dms2/services2/ServerEI2?wsdl" -f $ServerName)
1200 |
1201 | ## Add one or more keypairs to the array, depending on method parameter needs.
1202 | $KeyPairs = @()
1203 | $KeyPair = [PSObject]@{Key='applianceID'; Value=$ApplianceID;}
1204 | $KeyPairs += $KeyPair
1205 |
1206 | ## Pre Powershell 7 : Method using WebserviceProxy
1207 | #$Connection = New-Webserviceproxy $BindingURL
1208 |
1209 | # Get data from N-Central. Old and New line for comparison and easy conversion of existing scripts.
1210 | #$rc = $Connection.deviceGet($UserName, $Password, $KeyPairs)
1211 | $rc = GetNCData 'deviceGet' $UserName $Password $KeyPairs
1212 |
1213 | # Extract the Customer-ID and display.
1214 | $CustomerID = ($rc.info | where-object {$_.key -eq "device.customerid"}).value
1215 | $CustomerID
1216 | ```
1217 |
1218 |
1219 |
1220 |
1221 |
1222 | # Credits
1223 | Special Thanks go to the following Partners and Community Members for their contributions to the **NC-API-Documentation**
1224 | * David Brooks of Premier Technology Solutions
1225 | * Adriaan Sluis of Tosch for PS-NCentral and notes
1226 | * Joshua Bennet of Impact Networking for notes on EiKeyValue usage
1227 |
--------------------------------------------------------------------------------
/GetCDPFromAPI:
--------------------------------------------------------------------------------
1 | Clear-Host
2 |
3 | @"
4 | CDPFromAPI.ps1
5 |
6 | The script retrieves the Custom Device Properties of all devices
7 |
8 | The API user requires the following role permissions:
9 | Devices->LAN/WAN Devices
10 | * Custom Device Properties - Manage
11 | * LAN/WAN Devices Settings - Manage
12 |
13 | Created by: Jon Czerwinski, Cohn Consulting Corporation
14 | Date: December 3, 2018
15 | Version: 1.0
16 |
17 | "@
18 |
19 | #
20 | # Generate a pseudo-unique namespace to use with the New-WebServiceProxy and
21 | # associated types.
22 | #
23 | # By controlling the namespace, the script becomes portable and is not
24 | # dependent upon the endpoint url the webservice is connecting. However, this
25 | # introduces another complexity because once the namespace is defined within a
26 | # powershell session, it cannot be reused, nor can it be undefined. As long as
27 | # all the calls are made to the existing webserviceproxy, then everything would be
28 | # OK. But, if you try to rerun the script without closing and reopening the
29 | # powershell session, you will get an error.
30 | #
31 | # One way around this is to create a unique namespace each time the script is run.
32 | # We do this by using the last 'word' of a GUID appended to our base namespace 'NAble'.
33 | # This means our type names for parameters (such as T_KeyPair) now have a dynamic
34 | # type. We could pass types to each new-object call using "$NWSNameSpace.T_KeyPair",
35 | # and I find it more readable to define our 'dynamic' types here and use the typenames
36 | # in variables when calling New-Object.
37 | #
38 | $NWSNameSpace = "NAble" + ([guid]::NewGuid()).ToString().Substring(25)
39 | $KeyPairType = "$NWSNameSpace.T_KeyPair"
40 | $DevicePropertyType = "$NWSNameSpace.DeviceProperty"
41 | $DevicePropertiesType = "$NWSNameSpace.DeviceProperties"
42 |
43 | Write-Output "Using Namespace $NWSNameSpace"
44 | Write-Output " "
45 |
46 |
47 | #
48 | # Locate the Windows Agent Config folder
49 | #
50 | # By querying the Windows Agent Service path, the folder will be correctly identified
51 | # even if it's not on the C: drive.
52 | #
53 | $AgentConfigFolder = (gwmi win32_service -filter "Name like 'Windows Agent Service'").PathName
54 | $AgentConfigFolder = $AgentConfigFolder.Replace("bin\agent.exe", "config").Replace('"','')
55 |
56 |
57 | #
58 | # Get the N-Central server out of the ServerConfig.xml file
59 | #
60 | function Get-NCentralSvr() {
61 | $ConfigXML = [xml](Get-Content "$Script:AgentConfigFolder\ServerConfig.xml")
62 | $ConfigXML.ServerConfig.ServerIP
63 | }
64 |
65 |
66 | #
67 | # Get the device's ApplianceID out of the ApplianceConfig.xml file
68 | #
69 | function Get-ApplianceID() {
70 | $ConfigXML = [xml](Get-Content "$Script:AgentConfigFolder\ApplianceConfig.xml")
71 | $ConfigXML.ApplianceConfig.ApplianceID
72 | }
73 |
74 |
75 | #
76 | # Determine where the N-Central server is
77 | #
78 | $serverHost = Read-Host "Enter the fqdn of the N-Central Server "
79 |
80 | #
81 | # Get credentials
82 | # We could read them as plain text and then create a SecureString from it
83 | # By reading it as a SecureString, the password is obscured on entry
84 | #
85 | # We still have to extract a plain-text version of the password to pass to
86 | # the API call.
87 | #
88 | $username = Read-Host "Enter N-Central user id "
89 | $secpasswd = Read-Host "Enter password " -AsSecureString
90 |
91 | $creds = New-Object System.Management.Automation.PSCredential ("\$username", $secpasswd)
92 | $password = $creds.GetNetworkCredential().Password
93 |
94 | $bindingURL = "https://" + $serverHost + "/dms/services/ServerEI?wsdl"
95 | $nws = New-Webserviceproxy $bindingURL -credential $creds -Namespace ($NWSNameSpace)
96 |
97 | #
98 | # Set up and execute the query
99 | #
100 | $DevProps = $nws.devicePropertyList(
101 | $username,
102 | $password,
103 | $null, # Pass nulls and get *all devices*
104 | $null,
105 | $null,
106 | $null,
107 | $false
108 | )
109 |
110 | ($DevProps).Count
111 | Foreach ($Device in $DevProps) {
112 | $Device.Properties | ft *
113 | }
114 |
--------------------------------------------------------------------------------
/GetCustomerListwithSites-Prompted.ps1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/N-able/API/7c2fb35a0902ea533e1fa516937f583c06d24fee/GetCustomerListwithSites-Prompted.ps1
--------------------------------------------------------------------------------
/GetDeviceInfor-Prompted.ps1:
--------------------------------------------------------------------------------
1 | Clear-Host
2 |
3 | @"
4 | GetDeviceInfo-Prompted.ps1
5 |
6 | This script reads the Windows Agent config files to determine
7 | its appliance ID and the fqdn of the N-Central server. It then
8 | prompts the user for credentials and queries the N-Central server
9 | for device information.
10 |
11 | It returns the device's name as displayed in N-Central, the
12 | CustomerID the device is associated with, and the Customer Name.
13 |
14 | Created by: Jon Czerwinski, Cohn Consulting Corporation
15 | Date: November 10, 2013
16 | Version: 1.0
17 |
18 | "@
19 |
20 | #
21 | # Locate the Windows Agent Config folder
22 | #
23 | # By querying the Windows Agent Service path, the folder will be correctly identified
24 | # even if it's not on the C: drive.
25 | #
26 | $AgentConfigFolder = (gwmi win32_service -filter "Name like 'Windows Agent Service'").PathName
27 | $AgentConfigFolder = $AgentConfigFolder.Replace("bin\agent.exe", "config").Replace('"','')
28 |
29 |
30 | #
31 | # Get the N-Central server out of the ServerConfig.xml file
32 | #
33 | function Get-NCentralSvr() {
34 | $ConfigXML = [xml](Get-Content "$Script:AgentConfigFolder\ServerConfig.xml")
35 | $ConfigXML.ServerConfig.ServerIP
36 | }
37 |
38 |
39 | #
40 | # Get the device's ApplianceID out of the ApplianceConfig.xml file
41 | #
42 | function Get-ApplianceID() {
43 | $ConfigXML = [xml](Get-Content "$Script:AgentConfigFolder\ApplianceConfig.xml")
44 | $ConfigXML.ApplianceConfig.ApplianceID
45 | }
46 |
47 |
48 | #
49 | # Determine who we are and where the N-Central server is
50 | #
51 | $serverHost = Get-NCentralSvr
52 | $applianceID = Get-ApplianceID
53 |
54 |
55 | #
56 | # Get credentials
57 | # We could read them as plain text and then create a SecureString from it
58 | # By reading it as a SecureString, the password is obscured on entry
59 | #
60 | # We still have to extract a plain-text version of the password to pass to
61 | # the API call.
62 | #
63 | $username = Read-Host "Enter N-Central user id"
64 | $secpasswd = Read-Host "Enter password" -AsSecureString
65 |
66 | $creds = New-Object System.Management.Automation.PSCredential ("\$username", $secpasswd)
67 | $password = $creds.GetNetworkCredential().Password
68 |
69 | $bindingURL = "https://" + $serverHost + "/dms/services/ServerEI?wsdl"
70 | $nws = New-Webserviceproxy $bindingURL -credential $creds
71 |
72 |
73 | #
74 | # Feedback entered and discovered parameters
75 | #
76 | Write-Host
77 | Write-Host "I am appliance - $applianceID - and my N-Central server is - $serverHost"
78 | Write-Host "I will connect as $username with password $password"
79 | Write-Host
80 |
81 |
82 | #
83 | # Set up and execute the query
84 | #
85 | $KeyPairs = @()
86 |
87 | $KeyPair = New-Object Microsoft.PowerShell.Commands.NewWebserviceProxy.AutogeneratedTypes.WebServiceProxy1com_dms_services_ServerEI_wsdl.T_KeyPair
88 | $KeyPair.Key = 'applianceID'
89 | $KeyPair.Value = $applianceID
90 | $KeyPairs += $KeyPair
91 |
92 | $rc = $nws.deviceGet($username, $password, $KeyPairs)
93 |
94 | <#
95 | #
96 | # Dump all device info
97 | #
98 | foreach ($device in $rc) {
99 | foreach ($item in $device.Info) {
100 | Write-Host $item.Key ":"
101 | Write-Host $item.Value
102 | Write-Host
103 | }
104 | }
105 | #>
106 |
107 |
108 | #
109 | # Extract and return
110 | # N-Central device name
111 | # CustomerID
112 | # Customer Name
113 | #
114 | foreach ($device in $rc) {
115 | $DeviceInfo = @{}
116 |
117 | foreach ($item in $device.Info) {$DeviceInfo[$item.key] = $item.Value}
118 |
119 | Write-Host "N-Central Device Name: " $DeviceInfo['device.longname']
120 | Write-Host "Customer ID: " $DeviceInfo['device.customerid']
121 | Write-Host "Customer Name: " $DeviceInfo['device.customername']
122 | Write-Host
123 |
124 | Remove-Variable DeviceInfo
125 | }
126 |
--------------------------------------------------------------------------------
/GetFilteredDevicesPrinterInfo-Prompted.ps1:
--------------------------------------------------------------------------------
1 | Clear-Host
2 |
3 | @"
4 | GetDeviceFilteredPrinterInfo-Prompted.ps1
5 |
6 | This script outputs printer information for all devices matching the given
7 | N-Central filter. The script prompts for five paramters:
8 |
9 | N-Central server name
10 | N-Central userid
11 | N-Central password
12 | N-Central filter
13 | Output CSV filename
14 |
15 | Created by: Jon Czerwinski, Cohn Consulting Corporation
16 | Date: December 16, 2013
17 | Version: 1.0
18 |
19 | "@
20 |
21 |
22 | #
23 | # Determine where the N-Central server is
24 | #
25 | $serverHost = Read-Host "Enter the fqdn of the N-Central Server "
26 |
27 |
28 | #
29 | # Generate a pseudo-unique namespace to use with the New-WebServiceProxy and
30 | # associated types.
31 | #
32 | # By controlling the namespace, the script becomes portable and is not
33 | # dependent upon the endpoint url the webservice is connecting. However, this
34 | # introduces another complexity because once the namespace is defined within a
35 | # powershell session, it cannot be reused, nor can it be undefined. As long as
36 | # all the calls are made to the existing webserviceproxy, then everything would be
37 | # OK. But, if you try to rerun the script without closing and reopening the
38 | # powershell session, you will get an error.
39 | #
40 | # One way around this is to create a unique namespace each time the script is run.
41 | # We do this by using the last 'word' of a GUID appended to our base namespace 'NAble'.
42 | # This means our type names for parameters (such as T_KeyPair) now have a dynamic
43 | # type. We could pass types to each new-object call using "$NWSNameSpace.T_KeyPair",
44 | # and I find it more readable to define our 'dynamic' types here and use the typenames
45 | # in variables when calling New-Object.
46 | #
47 | $NWSNameSpace = "NAble" + ([guid]::NewGuid()).ToString().Substring(25)
48 | $KeyPairType = "$NWSNameSpace.T_KeyPair"
49 | $KeyValueType = "$NWSNameSpace.T_KeyValue"
50 |
51 |
52 | #
53 | # Create PrinterData type to hold printer name and port
54 | #
55 | Add-Type -TypeDefinition @"
56 | public class PrinterData {
57 | public string CustomerName;
58 | public string ComputerName;
59 | public string PrinterName;
60 | public string PrinterPort;
61 | }
62 | "@
63 |
64 |
65 | #
66 | # Get credentials
67 | # We could read them as plain text and then create a SecureString from it
68 | # By reading it as a SecureString, the password is obscured on entry
69 | #
70 | # We still have to extract a plain-text version of the password to pass to
71 | # the API call.
72 | #
73 | $username = Read-Host "Enter N-Central user id "
74 | $secpasswd = Read-Host "Enter password " -AsSecureString
75 |
76 | $creds = New-Object System.Management.Automation.PSCredential ("\$username", $secpasswd)
77 | $password = $creds.GetNetworkCredential().Password
78 |
79 | $bindingURL = "https://" + $serverHost + "/dms/services/ServerEI?wsdl"
80 | $nws = New-Webserviceproxy $bindingURL -credential $creds -Namespace ($NWSNameSpace)
81 |
82 |
83 | #
84 | # Get the filter name to use
85 | #
86 | Write-Host
87 | $FilterName = (Read-Host "Enter the exact filter name ").Trim()
88 |
89 |
90 | #
91 | # Select the output file
92 | #
93 | Write-Host
94 | $CSVFile = (Read-Host "Enter the CSV output filename ").Trim()
95 |
96 |
97 | #
98 | # Set up and execute the query
99 | #
100 | $KeyPairs = @()
101 |
102 | $KeyPair = New-Object -TypeName $KeyValueType
103 | $KeyPair.Key = 'TargetByFilterName'
104 | $KeyPair.Value = $FilterName
105 | $KeyPairs += $KeyPair
106 |
107 | $KeyPair = New-Object -TypeName $KeyValueType
108 | $KeyPair.Key = 'InformationCategoriesInclusion'
109 | $KeyPair.Value = @("asset.customer", "asset.device", "asset.printer")
110 | $KeyPairs += $KeyPair
111 |
112 | $rc = $nws.DeviceAssetInfoExport2("0.0", $username, $password, $KeyPairs)
113 |
114 |
115 | #
116 | # Set up the printers array, then populate with the printer name and port
117 | #
118 | $Printers = @()
119 |
120 | foreach ($device in $rc) {
121 | $DeviceAssetInfo = @{}
122 | foreach ($item in $device.Info) {$DeviceAssetInfo[$item.key] = $item.Value}
123 |
124 | $CustomerName = $DeviceAssetInfo['asset.customer.customername']
125 | $ComputerName = $DeviceAssetInfo['asset.device.longname']
126 | $index = 0
127 |
128 | While ($DeviceAssetInfo["asset.printer.name.$index"]) {
129 | $Printer = New-Object PrinterData
130 | $Printer.CustomerName = $CustomerName
131 | $Printer.ComputerName = $ComputerName
132 | $Printer.PrinterName = $DeviceAssetInfo["asset.printer.name.$index"]
133 | $Printer.PrinterPort = $DeviceAssetInfo["asset.printer.port.$index"]
134 |
135 | $Script:Printers += $Printer
136 | $index ++
137 | }
138 |
139 | If ($index -gt 0) {
140 | Write-Host "Found $index printers on $CustomerName - $ComputerName"
141 | }
142 |
143 | Remove-Variable DeviceAssetInfo
144 | }
145 |
146 | $Printers | Export-Csv -Path $CSVFile -NoTypeInformation -Force
147 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # API
2 | ## Contents
3 | | Type | Name | API Version | Contents |
4 | | --- | -----| -----|-------- |
5 | | Folder | **APIv2** | v2 | Contains documentation and scripting examples for version 2 of the N-Central API in 2020.x, covering creating connections, queries, updating values, adding customers with native web proxy services and the PS-Ncentral powershell module by Tosch |
6 | | File | GetCDPFromAPI | v1 |The script retrieves the Custom Device Properties of all devices |
7 | | File | GetCustomerListwithSites-Prompted.ps1 | v1 | This script outputs the customer list |
8 | | File | GetDeviceInfor-Prompted.ps1 | v1 | Reads Windows Agent config for the appliance ID and the fqdn of the N-Central server. Prompts the user for credentials and queries the N-Central server for device information. |
9 | |File | GetFilteredDevicesPrinterInfo-Prompted.ps1 | v1 | This script outputs printer information for all devices matching the given N-Central filter |
10 |
11 |
--------------------------------------------------------------------------------