[{"data":1,"prerenderedAt":4339},["ShallowReactive",2],{"post:\u002F2025\u002F08\u002F20\u002Fpowershell-connectwise-sync-configuration-items-from-discovery-scans\u002F":3},{"post":4,"newer":4298,"older":4308,"related":4319,"series":4337},{"id":5,"title":6,"body":7,"canonical":4279,"categories":4280,"date":4283,"description":4284,"extension":4285,"featured":4286,"hero":4287,"image":4287,"meta":4288,"navigation":1031,"path":4289,"readingTime":383,"seo":4290,"series":4287,"seriesOrder":4287,"sites":4291,"source":4287,"stem":4292,"tags":4293,"updated":4287,"url":4296,"__hash__":4297},"blog\u002Fblog\u002F2025\u002F08\u002F20\u002Fpowershell-connectwise-sync-configuration-items-from-discovery-scans.md","PowerShell: ConnectWise – Sync Configurations from Discovery Scans",{"type":8,"value":9,"toc":4271},"minimark",[10,14,19,110,114,248,255,259,271,534,537,579,585,671,679,685,731,735,4080,4084,4225,4229,4267],[11,12,13],"p",{},"Discovery tools are good at finding what's actually on a network. PSA tools like ConnectWise PSA (Manage) are good at billing, ticketing and reporting against what's supposed to be there. The gap between the two is where configuration items go stale: a switch gets replaced, nobody updates the CI, and six months later a report says you're managing hardware that's in a dumpster. This script takes a CSV export from a discovery scan and reconciles it against a company's configurations through the ConnectWise REST API. It loads the company's existing configurations once, matches each discovered device by serial number, then MAC address, then name, sends a JSON Patch for fields that changed, and creates a configuration for anything it can't match.",[15,16,18],"h2",{"id":17},"requirements","Requirements",[20,21,22,26,45,56,67,84],"ul",{},[23,24,25],"li",{},"Windows PowerShell 5.1 or PowerShell 7.",[23,27,28,29,33,34,37,38,37,41,44],{},"An ",[30,31,32],"strong",{},"API member"," in ConnectWise PSA (",[30,35,36],{},"System"," > ",[30,39,40],{},"Members",[30,42,43],{},"API Members",") with a public\u002Fprivate key pair, assigned a security role that can inquire on companies and add\u002Fedit configurations. The private key is only shown when it's generated, so store it straight away.",[23,46,47,48,51,52,55],{},"A ",[30,49,50],{},"clientId"," from the ConnectWise Developer Network (developer.connectwise.com). Every request must carry it in a ",[53,54,50],"code",{}," header.",[23,57,58,59,62,63,66],{},"Your ConnectWise ",[30,60,61],{},"company ID"," (the login company code) and the API host for your region, for example ",[53,64,65],{},"api-na.myconnectwise.net",".",[23,68,69,70,73,74,73,77,73,80,83],{},"Configuration types (for example ",[53,71,72],{},"Server",", ",[53,75,76],{},"Network Device",[53,78,79],{},"Printer",[53,81,82],{},"Workstation",") and manufacturers already created in PSA. The script looks them up by name and doesn't create reference data.",[23,85,86,87,73,90,73,93,73,96,73,99,73,102,105,106,109],{},"A discovery CSV with ",[53,88,89],{},"Hostname",[53,91,92],{},"IPAddress",[53,94,95],{},"MacAddress",[53,97,98],{},"DeviceType",[53,100,101],{},"Manufacturer",[53,103,104],{},"Model"," and ",[53,107,108],{},"SerialNumber"," columns.",[15,111,113],{"id":112},"parameters","Parameters",[115,116,117,136],"table",{},[118,119,120],"thead",{},[121,122,123,127,130,133],"tr",{},[124,125,126],"th",{},"Name",[124,128,129],{},"Type",[124,131,132],{},"Required",[124,134,135],{},"Description",[137,138,139,156,170,186,200,215,229],"tbody",{},[121,140,141,147,150,153],{},[142,143,144],"td",{},[53,145,146],{},"CsvPath",[142,148,149],{},"String",[142,151,152],{},"Yes",[142,154,155],{},"Path to the discovery export CSV.",[121,157,158,163,165,167],{},[142,159,160],{},[53,161,162],{},"CompanyIdentifier",[142,164,149],{},[142,166,152],{},[142,168,169],{},"Identifier (short name) of the customer company the configurations belong to.",[121,171,172,177,179,181],{},[142,173,174],{},[53,175,176],{},"CWServer",[142,178,149],{},[142,180,152],{},[142,182,183,184,66],{},"API host name, for example ",[53,185,65],{},[121,187,188,193,195,197],{},[142,189,190],{},[53,191,192],{},"CWCompanyId",[142,194,149],{},[142,196,152],{},[142,198,199],{},"Your ConnectWise login company ID, used in authentication.",[121,201,202,207,210,212],{},[142,203,204],{},[53,205,206],{},"Credential",[142,208,209],{},"PSCredential",[142,211,152],{},[142,213,214],{},"API member keys: user name = public key, password = private key.",[121,216,217,222,224,226],{},[142,218,219],{},[53,220,221],{},"ClientId",[142,223,149],{},[142,225,152],{},[142,227,228],{},"The clientId issued on the Developer Network.",[121,230,231,236,239,242],{},[142,232,233],{},[53,234,235],{},"DelayMilliseconds",[142,237,238],{},"Int",[142,240,241],{},"No",[142,243,244,245,66],{},"Pause between write calls, to stay under API throttling on large imports. Defaults to ",[53,246,247],{},"200",[11,249,250,251,254],{},"The script supports ",[53,252,253],{},"-WhatIf",", which reports what would be created or updated without calling the write endpoints.",[15,256,258],{"id":257},"usage","Usage",[11,260,261,262,267,268,270],{},"If the scan came from the ",[263,264,266],"a",{"href":265},"\u002F2026\u002F01\u002F07\u002Fpython-discovery-fingerprint-every-device-on-a-subnet\u002F","Python subnet fingerprint script",", reshape its columns into the sync's schema first. ",[53,269,98],{}," is a guess from the vendor, so review it before importing:",[272,273,278],"pre",{"className":274,"code":275,"language":276,"meta":277,"style":277},"language-powershell shiki shiki-themes github-dark","Import-Csv -Path \".\\site-a-fingerprint.csv\" | ForEach-Object {\n    [PSCustomObject]@{\n        Hostname     = if ($_.reverse_dns) { ($_.reverse_dns -split '\\.')[0].ToUpper() } else { \"\" }\n        IPAddress    = $_.ip_address\n        MacAddress   = $_.mac_address\n        DeviceType   = if ($_.vendor -match \"Cisco|Ubiquiti|Aruba|Juniper\") { \"switch\" } elseif ($_.vendor -match \"HP|Brother|Lexmark\") { \"printer\" } else { \"workstation\" }\n        Manufacturer = $_.vendor\n        Model        = \"\"\n        SerialNumber = \"\"\n    }\n} | Export-Csv -Path \"C:\\Discovery\\site-a-scan.csv\" -NoTypeInformation\n","powershell","",[53,279,280,310,328,381,395,408,470,483,494,504,510],{"__ignoreMap":277},[281,282,285,289,293,297,301,304,307],"span",{"class":283,"line":284},"line",1,[281,286,288],{"class":287},"sDLfK","Import-Csv",[281,290,292],{"class":291},"snl16"," -",[281,294,296],{"class":295},"s95oV","Path ",[281,298,300],{"class":299},"sU2Wk","\".\\site-a-fingerprint.csv\"",[281,302,303],{"class":291}," |",[281,305,306],{"class":287}," ForEach-Object",[281,308,309],{"class":295}," {\n",[281,311,313,316,319,322,325],{"class":283,"line":312},2,[281,314,315],{"class":295},"    [",[281,317,318],{"class":291},"PSCustomObject",[281,320,321],{"class":295},"]",[281,323,324],{"class":291},"@",[281,326,327],{"class":295},"{\n",[281,329,331,334,337,340,343,346,349,351,354,357,360,363,366,369,372,375,378],{"class":283,"line":330},3,[281,332,333],{"class":295},"        Hostname     ",[281,335,336],{"class":291},"=",[281,338,339],{"class":291}," if",[281,341,342],{"class":295}," (",[281,344,345],{"class":287},"$_",[281,347,348],{"class":295},".reverse_dns) { (",[281,350,345],{"class":287},[281,352,353],{"class":295},".reverse_dns ",[281,355,356],{"class":291},"-split",[281,358,359],{"class":299}," '\\.'",[281,361,362],{"class":295},")[",[281,364,365],{"class":287},"0",[281,367,368],{"class":295},"].ToUpper() } ",[281,370,371],{"class":291},"else",[281,373,374],{"class":295}," { ",[281,376,377],{"class":299},"\"\"",[281,379,380],{"class":295}," }\n",[281,382,384,387,389,392],{"class":283,"line":383},4,[281,385,386],{"class":295},"        IPAddress    ",[281,388,336],{"class":291},[281,390,391],{"class":287}," $_",[281,393,394],{"class":295},".ip_address\n",[281,396,398,401,403,405],{"class":283,"line":397},5,[281,399,400],{"class":295},"        MacAddress   ",[281,402,336],{"class":291},[281,404,391],{"class":287},[281,406,407],{"class":295},".mac_address\n",[281,409,411,414,416,418,420,422,425,428,431,434,437,440,443,445,447,449,451,454,456,459,461,463,465,468],{"class":283,"line":410},6,[281,412,413],{"class":295},"        DeviceType   ",[281,415,336],{"class":291},[281,417,339],{"class":291},[281,419,342],{"class":295},[281,421,345],{"class":287},[281,423,424],{"class":295},".vendor ",[281,426,427],{"class":291},"-match",[281,429,430],{"class":299}," \"Cisco|Ubiquiti|Aruba|Juniper\"",[281,432,433],{"class":295},") { ",[281,435,436],{"class":299},"\"switch\"",[281,438,439],{"class":295}," } ",[281,441,442],{"class":291},"elseif",[281,444,342],{"class":295},[281,446,345],{"class":287},[281,448,424],{"class":295},[281,450,427],{"class":291},[281,452,453],{"class":299}," \"HP|Brother|Lexmark\"",[281,455,433],{"class":295},[281,457,458],{"class":299},"\"printer\"",[281,460,439],{"class":295},[281,462,371],{"class":291},[281,464,374],{"class":295},[281,466,467],{"class":299},"\"workstation\"",[281,469,380],{"class":295},[281,471,473,476,478,480],{"class":283,"line":472},7,[281,474,475],{"class":295},"        Manufacturer ",[281,477,336],{"class":291},[281,479,391],{"class":287},[281,481,482],{"class":295},".vendor\n",[281,484,486,489,491],{"class":283,"line":485},8,[281,487,488],{"class":295},"        Model        ",[281,490,336],{"class":291},[281,492,493],{"class":299}," \"\"\n",[281,495,497,500,502],{"class":283,"line":496},9,[281,498,499],{"class":295},"        SerialNumber ",[281,501,336],{"class":291},[281,503,493],{"class":299},[281,505,507],{"class":283,"line":506},10,[281,508,509],{"class":295},"    }\n",[281,511,513,516,519,522,524,526,529,531],{"class":283,"line":512},11,[281,514,515],{"class":295},"} ",[281,517,518],{"class":291},"|",[281,520,521],{"class":287}," Export-Csv",[281,523,292],{"class":291},[281,525,296],{"class":295},[281,527,528],{"class":299},"\"C:\\Discovery\\site-a-scan.csv\"",[281,530,292],{"class":291},[281,532,533],{"class":295},"NoTypeInformation\n",[11,535,536],{},"Store the API keys once as a credential file readable only by you (DPAPI-protected, so it only decrypts for the same user on the same machine):",[272,538,540],{"className":274,"code":539,"language":276,"meta":277,"style":277},"Get-Credential -Message \"User name = public key, password = private key\" | Export-Clixml -Path \"$env:USERPROFILE\\cw-api.xml\"\n",[53,541,542],{"__ignoreMap":277},[281,543,544,547,549,552,555,557,560,562,564,567,570,573,576],{"class":283,"line":284},[281,545,546],{"class":287},"Get-Credential",[281,548,292],{"class":291},[281,550,551],{"class":295},"Message ",[281,553,554],{"class":299},"\"User name = public key, password = private key\"",[281,556,303],{"class":291},[281,558,559],{"class":287}," Export-Clixml",[281,561,292],{"class":291},[281,563,296],{"class":295},[281,565,566],{"class":299},"\"",[281,568,569],{"class":295},"$",[281,571,572],{"class":287},"env:",[281,574,575],{"class":295},"USERPROFILE",[281,577,578],{"class":299},"\\cw-api.xml\"\n",[11,580,581,582,584],{},"Run with ",[53,583,253],{}," first:",[272,586,588],{"className":274,"code":587,"language":276,"meta":277,"style":277},"$cred = Import-Clixml -Path \"$env:USERPROFILE\\cw-api.xml\"\n.\\Sync-CWConfigurationsFromDiscovery.ps1 -CsvPath \"C:\\Discovery\\site-a-scan.csv\" -CompanyIdentifier \"ACMECORP\" -CWServer \"api-na.myconnectwise.net\" -CWCompanyId \"\u003Ccompany-id>\" -Credential $cred -ClientId \"\u003Cclient-id>\" -WhatIf\n",[53,589,590,614],{"__ignoreMap":277},[281,591,592,595,597,600,602,604,606,608,610,612],{"class":283,"line":284},[281,593,594],{"class":295},"$cred ",[281,596,336],{"class":291},[281,598,599],{"class":287}," Import-Clixml",[281,601,292],{"class":291},[281,603,296],{"class":295},[281,605,566],{"class":299},[281,607,569],{"class":295},[281,609,572],{"class":287},[281,611,575],{"class":295},[281,613,578],{"class":299},[281,615,616,618,621,623,626,628,630,633,636,638,641,644,646,649,652,654,657,660,663,666,668],{"class":283,"line":312},[281,617,66],{"class":295},[281,619,620],{"class":287},"\\Sync-CWConfigurationsFromDiscovery.ps1",[281,622,292],{"class":291},[281,624,625],{"class":295},"CsvPath ",[281,627,528],{"class":299},[281,629,292],{"class":291},[281,631,632],{"class":295},"CompanyIdentifier ",[281,634,635],{"class":299},"\"ACMECORP\"",[281,637,292],{"class":291},[281,639,640],{"class":295},"CWServer ",[281,642,643],{"class":299},"\"api-na.myconnectwise.net\"",[281,645,292],{"class":291},[281,647,648],{"class":295},"CWCompanyId ",[281,650,651],{"class":299},"\"\u003Ccompany-id>\"",[281,653,292],{"class":291},[281,655,656],{"class":295},"Credential $cred ",[281,658,659],{"class":291},"-",[281,661,662],{"class":295},"ClientId ",[281,664,665],{"class":299},"\"\u003Cclient-id>\"",[281,667,292],{"class":291},[281,669,670],{"class":295},"WhatIf\n",[272,672,677],{"className":673,"code":675,"language":676,"meta":277},[674],"language-text","Codebase: v4_6_release\u002F  Company: ACMECORP (id 250)  Existing configurations: 412\nWhat if: Performing the operation \"PATCH ipAddress (10.10.1.1 -> 10.10.1.2)\" on target \"SW-CORE-01 (config 4821, matched on serialNumber)\".\nWhat if: Performing the operation \"Create configuration (type Network Device)\" on target \"AP-FLOOR3-07\".\n38 discovered device(s): 1 updated, 1 created, 35 unchanged, 1 skipped.\n","text",[53,678,675],{"__ignoreMap":277},[11,680,681,682,684],{},"Drop ",[53,683,253],{}," to apply, and schedule it after each recurring discovery scan:",[272,686,688],{"className":274,"code":687,"language":276,"meta":277,"style":277},".\\Sync-CWConfigurationsFromDiscovery.ps1 -CsvPath \"C:\\Discovery\\site-a-scan.csv\" -CompanyIdentifier \"ACMECORP\" -CWServer \"api-na.myconnectwise.net\" -CWCompanyId \"\u003Ccompany-id>\" -Credential $cred -ClientId \"\u003Cclient-id>\"\n",[53,689,690],{"__ignoreMap":277},[281,691,692,694,696,698,700,702,704,706,708,710,712,714,716,718,720,722,724,726,728],{"class":283,"line":284},[281,693,66],{"class":295},[281,695,620],{"class":287},[281,697,292],{"class":291},[281,699,625],{"class":295},[281,701,528],{"class":299},[281,703,292],{"class":291},[281,705,632],{"class":295},[281,707,635],{"class":299},[281,709,292],{"class":291},[281,711,640],{"class":295},[281,713,643],{"class":299},[281,715,292],{"class":291},[281,717,648],{"class":295},[281,719,651],{"class":299},[281,721,292],{"class":291},[281,723,656],{"class":295},[281,725,659],{"class":291},[281,727,662],{"class":295},[281,729,730],{"class":299},"\"\u003Cclient-id>\"\n",[15,732,734],{"id":733},"script","Script",[272,736,738],{"className":274,"code":737,"language":276,"meta":277,"style":277},"\u003C#\n.SYNOPSIS\n    Reconciles a discovery scan CSV against ConnectWise PSA configuration items.\n.DESCRIPTION\n    Reads a discovery export CSV (Hostname, IPAddress, MacAddress, DeviceType, Manufacturer, Model,\n    SerialNumber). Resolves the API codebase, looks up the target company by identifier, and loads all\n    of that company's configurations with paging, plus configuration types and manufacturers. Each\n    discovered device is matched to an existing configuration by serial number, then MAC address, then\n    name. A match gets a JSON Patch for any of ipAddress, macAddress, serialNumber or modelNumber that\n    changed; no match creates a new configuration of the mapped type. Uses the ConnectWise PSA REST API\n    (apis\u002F3.0) with API member Basic authentication and the clientId header.\n.PARAMETER CsvPath\n    Path to the discovery export CSV.\n.PARAMETER CompanyIdentifier\n    Identifier (short name) of the customer company the configurations belong to.\n.PARAMETER CWServer\n    API host name, for example api-na.myconnectwise.net.\n.PARAMETER CWCompanyId\n    Your ConnectWise login company ID, used in authentication.\n.PARAMETER Credential\n    API member keys: user name = public key, password = private key.\n.PARAMETER ClientId\n    The clientId issued on the Developer Network.\n.PARAMETER DelayMilliseconds\n    Pause between write calls, to stay under API throttling on large imports. Defaults to 200.\n.EXAMPLE\n    .\\Sync-CWConfigurationsFromDiscovery.ps1 -CsvPath \"C:\\Discovery\\site-a-scan.csv\" -CompanyIdentifier \"ACMECORP\" -CWServer \"api-na.myconnectwise.net\" -CWCompanyId \"\u003Ccompany-id>\" -Credential $cred -ClientId \"\u003Cclient-id>\" -WhatIf\n.NOTES\n    Author  : Thomas Lasswell (https:\u002F\u002Fwww.techcolumnist.com)\n    Version : 1.0 (2025-08-20)\n    Requires: PowerShell 5.1 or 7, a ConnectWise PSA API member with company inquire and configuration add\u002Fedit rights\n#>\n[CmdletBinding(SupportsShouldProcess = $true)]\nparam(\n    [Parameter(Mandatory = $true)]\n    [string]$CsvPath,\n\n    [Parameter(Mandatory = $true)]\n    [string]$CompanyIdentifier,\n\n    [Parameter(Mandatory = $true)]\n    [string]$CWServer,\n\n    [Parameter(Mandatory = $true)]\n    [string]$CWCompanyId,\n\n    [Parameter(Mandatory = $true)]\n    [System.Management.Automation.PSCredential]$Credential,\n\n    [Parameter(Mandatory = $true)]\n    [string]$ClientId,\n\n    [Parameter(Mandatory = $false)]\n    [int]$DelayMilliseconds = 200\n)\n\n$ErrorActionPreference = 'Stop'\n\n# Basic auth: base64(\"\u003CcompanyId>+\u003CpublicKey>:\u003CprivateKey>\"). The braces stop PowerShell reading \"$name:\" as a scope specifier.\n$publicKey = $Credential.UserName\n$privateKey = $Credential.GetNetworkCredential().Password\n$authBytes = [System.Text.Encoding]::UTF8.GetBytes(\"${CWCompanyId}+${publicKey}:${privateKey}\")\n$headers = @{\n    Authorization = \"Basic \" + [System.Convert]::ToBase64String($authBytes)\n    clientId      = $ClientId\n    Accept        = \"application\u002Fjson\"\n}\n\nfunction Invoke-CWApi {\n    param(\n        [string]$Method = 'Get',\n        [string]$Path,\n        [hashtable]$Query,\n        $Body\n    )\n\n    $uri = \"$script:apiBase\u002F$Path\"\n    if ($Query) {\n        $pairs = foreach ($key in $Query.Keys) {\n            \"{0}={1}\" -f $key, [uri]::EscapeDataString([string]$Query[$key])\n        }\n        $uri += \"?\" + ($pairs -join \"&\")\n    }\n\n    $params = @{ Uri = $uri; Method = $Method; Headers = $headers }\n    if ($null -ne $Body) {\n        # -InputObject (not the pipeline) so a one-element patch array stays a JSON array.\n        $params['Body'] = [System.Text.Encoding]::UTF8.GetBytes((ConvertTo-Json -InputObject $Body -Depth 6))\n        $params['ContentType'] = 'application\u002Fjson'\n    }\n    return Invoke-RestMethod @params\n}\n\nfunction Get-CWAll {\n    param([string]$Path, [string]$Conditions)\n\n    # pageSize is capped at 1000; keep asking until a short page comes back.\n    $page = 1\n    $results = New-Object -TypeName System.Collections.Generic.List[object]\n    do {\n        $query = @{ page = $page; pageSize = 1000 }\n        if ($Conditions) {\n            $query['conditions'] = $Conditions\n        }\n        $batch = @(Invoke-CWApi -Path $Path -Query $query)\n        foreach ($item in $batch) {\n            $results.Add($item)\n        }\n        $page++\n    } while ($batch.Count -eq 1000)\n    return $results\n}\n\nfunction ConvertTo-NormalMac {\n    param([string]$Mac)\n    if ([string]::IsNullOrWhiteSpace($Mac)) {\n        return \"\"\n    }\n    return ($Mac -replace '[^0-9A-Fa-f]', '').ToUpper()\n}\n\nfunction Get-DeviceTypeName {\n    param([string]$DeviceType)\n\n    switch -Wildcard ($DeviceType) {\n        \"*server*\" { return \"Server\" }\n        \"*switch*\" { return \"Network Device\" }\n        \"*router*\" { return \"Network Device\" }\n        \"*firewall*\" { return \"Network Device\" }\n        \"*access point*\" { return \"Network Device\" }\n        \"*printer*\" { return \"Printer\" }\n        default { return \"Workstation\" }\n    }\n}\n\n# The codebase (for example \"v4_6_release\u002F\") is published per company at \u002Flogin\u002Fcompanyinfo\u002F\u003CcompanyId>.\n$companyInfo = Invoke-RestMethod -Uri \"https:\u002F\u002F$CWServer\u002Flogin\u002Fcompanyinfo\u002F$CWCompanyId\" -Method Get -Headers $headers\n$codebase = $companyInfo.Codebase.Trim('\u002F')\n$script:apiBase = \"https:\u002F\u002F$CWServer\u002F$codebase\u002Fapis\u002F3.0\"\n\n$company = @(Invoke-CWApi -Path \"company\u002Fcompanies\" -Query @{ conditions = \"identifier=`\"$CompanyIdentifier`\"\" })\nif ($company.Count -ne 1) {\n    throw \"Expected one company with identifier '$CompanyIdentifier', found $($company.Count).\"\n}\n$companyId = $company[0].id\n\n$existing = Get-CWAll -Path \"company\u002Fconfigurations\" -Conditions \"company\u002Fid=$companyId\"\n$types = @{}\nforeach ($type in (Get-CWAll -Path \"company\u002Fconfigurations\u002Ftypes\")) {\n    $types[$type.name] = $type.id\n}\n$manufacturers = @{}\nforeach ($manufacturer in (Get-CWAll -Path \"procurement\u002Fmanufacturers\")) {\n    $manufacturers[$manufacturer.name] = $manufacturer.id\n}\n\nWrite-Host \"Codebase: $codebase\u002F  Company: $CompanyIdentifier (id $companyId)  Existing configurations: $($existing.Count)\"\n\n# Index existing configurations for matching. Hashtables are case-insensitive by default.\n$bySerial = @{}\n$byMac = @{}\n$byName = @{}\nforeach ($config in $existing) {\n    if ($config.serialNumber) { $bySerial[$config.serialNumber.Trim()] = $config }\n    $mac = ConvertTo-NormalMac -Mac $config.macAddress\n    if ($mac) { $byMac[$mac] = $config }\n    if ($config.name) { $byName[$config.name.Trim()] = $config }\n}\n\n$devices = @(Import-Csv -Path $CsvPath)\n$created = 0\n$updated = 0\n$unchanged = 0\n$skipped = 0\n\nforeach ($device in $devices) {\n    $hostname = \"$($device.Hostname)\".Trim()\n    $serial = \"$($device.SerialNumber)\".Trim()\n    $mac = ConvertTo-NormalMac -Mac $device.MacAddress\n\n    if (-not $hostname -and -not $serial -and -not $mac) {\n        Write-Warning \"Skipping a row with no hostname, serial number or MAC address.\"\n        $skipped++\n        continue\n    }\n\n    $match = $null\n    $matchedOn = $null\n    if ($serial -and $bySerial.ContainsKey($serial)) {\n        $match = $bySerial[$serial]\n        $matchedOn = 'serialNumber'\n    } elseif ($mac -and $byMac.ContainsKey($mac)) {\n        $match = $byMac[$mac]\n        $matchedOn = 'macAddress'\n    } elseif ($hostname -and $byName.ContainsKey($hostname)) {\n        $match = $byName[$hostname]\n        $matchedOn = 'name'\n    }\n\n    if ($match) {\n        # Only fields the scan actually has a value for are compared, so blanks never wipe PSA data.\n        $operations = New-Object -TypeName System.Collections.Generic.List[object]\n        $changes = New-Object -TypeName System.Collections.Generic.List[string]\n        $fields = [ordered]@{\n            ipAddress    = \"$($device.IPAddress)\".Trim()\n            macAddress   = \"$($device.MacAddress)\".Trim()\n            serialNumber = $serial\n            modelNumber  = \"$($device.Model)\".Trim()\n        }\n        foreach ($field in $fields.Keys) {\n            $newValue = $fields[$field]\n            $oldValue = \"$($match.$field)\".Trim()\n            $same = if ($field -eq 'macAddress') { (ConvertTo-NormalMac -Mac $oldValue) -eq $mac } else { $oldValue -eq $newValue }\n            if ($newValue -and -not $same) {\n                $operations.Add([PSCustomObject]@{ op = \"replace\"; path = \"\u002F$field\"; value = $newValue })\n                $changes.Add(\"$field ($oldValue -> $newValue)\")\n            }\n        }\n\n        if ($operations.Count -eq 0) {\n            $unchanged++\n            continue\n        }\n\n        if ($PSCmdlet.ShouldProcess(\"$($match.name) (config $($match.id), matched on $matchedOn)\", \"PATCH $($changes -join ', ')\")) {\n            Invoke-CWApi -Method Patch -Path \"company\u002Fconfigurations\u002F$($match.id)\" -Body $operations.ToArray() | Out-Null\n            Write-Host \"Updated $($match.name): $($changes -join ', ')\"\n            Start-Sleep -Milliseconds $DelayMilliseconds\n        }\n        $updated++\n        continue\n    }\n\n    if (-not $hostname) {\n        Write-Warning \"No match for serial '$serial' \u002F MAC '$mac' and no hostname to create it with - skipped.\"\n        $skipped++\n        continue\n    }\n\n    $typeName = Get-DeviceTypeName -DeviceType $device.DeviceType\n    if (-not $types.ContainsKey($typeName)) {\n        Write-Warning \"Configuration type '$typeName' doesn't exist in PSA - skipped $hostname.\"\n        $skipped++\n        continue\n    }\n\n    if ($PSCmdlet.ShouldProcess($hostname, \"Create configuration (type $typeName)\")) {\n        $newConfig = [ordered]@{\n            name         = $hostname\n            type         = @{ id = $types[$typeName] }\n            company      = @{ id = $companyId }\n            ipAddress    = \"$($device.IPAddress)\".Trim()\n            macAddress   = \"$($device.MacAddress)\".Trim()\n            serialNumber = $serial\n            modelNumber  = \"$($device.Model)\".Trim()\n        }\n        if ($device.Manufacturer -and $manufacturers.ContainsKey($device.Manufacturer.Trim())) {\n            $newConfig['manufacturer'] = @{ id = $manufacturers[$device.Manufacturer.Trim()] }\n        }\n        $result = Invoke-CWApi -Method Post -Path \"company\u002Fconfigurations\" -Body $newConfig\n        Write-Host \"Created $hostname (config $($result.id), type $typeName)\"\n        Start-Sleep -Milliseconds $DelayMilliseconds\n    }\n    $created++\n}\n\nWrite-Host \"$($devices.Count) discovered device(s): $updated updated, $created created, $unchanged unchanged, $skipped skipped.\"\n",[53,739,740,746,753,758,765,770,775,780,785,790,795,800,811,817,827,833,843,849,859,865,875,881,891,897,907,913,921,927,935,941,947,953,959,984,993,1012,1026,1033,1050,1062,1067,1084,1096,1101,1118,1130,1135,1152,1165,1170,1187,1199,1204,1222,1238,1244,1249,1260,1265,1271,1282,1293,1331,1344,1366,1377,1388,1394,1399,1411,1419,1437,1449,1462,1468,1474,1479,1506,1515,1535,1563,1569,1594,1599,1604,1632,1648,1654,1694,1709,1714,1726,1731,1736,1746,1767,1772,1778,1789,1811,1819,1844,1853,1869,1874,1899,1913,1919,1924,1933,1952,1960,1965,1970,1980,1992,2005,2013,2018,2040,2045,2050,2060,2072,2077,2088,2104,2119,2133,2147,2161,2176,2191,2196,2201,2206,2212,2251,2267,2292,2297,2346,2364,2391,2396,2412,2417,2447,2460,2486,2497,2502,2514,2537,2548,2553,2558,2593,2598,2604,2616,2628,2640,2653,2666,2681,2693,2705,2710,2715,2734,2745,2755,2765,2775,2780,2793,2817,2840,2854,2859,2888,2897,2905,2911,2916,2921,2932,2942,2955,2966,2977,2992,3002,3012,3027,3037,3047,3052,3057,3065,3071,3089,3107,3126,3149,3172,3183,3206,3211,3224,3235,3263,3306,3322,3362,3388,3394,3399,3404,3419,3427,3433,3438,3443,3511,3549,3583,3594,3599,3607,3612,3617,3622,3634,3654,3661,3666,3671,3676,3691,3703,3722,3729,3734,3739,3744,3767,3785,3796,3814,3831,3852,3873,3882,3903,3908,3921,3943,3948,3974,4004,4014,4019,4027,4032,4037],{"__ignoreMap":277},[281,741,742],{"class":283,"line":284},[281,743,745],{"class":744},"sAwPA","\u003C#\n",[281,747,748,750],{"class":283,"line":312},[281,749,66],{"class":287},[281,751,752],{"class":291},"SYNOPSIS\n",[281,754,755],{"class":283,"line":330},[281,756,757],{"class":744},"    Reconciles a discovery scan CSV against ConnectWise PSA configuration items.\n",[281,759,760,762],{"class":283,"line":383},[281,761,66],{"class":287},[281,763,764],{"class":291},"DESCRIPTION\n",[281,766,767],{"class":283,"line":397},[281,768,769],{"class":744},"    Reads a discovery export CSV (Hostname, IPAddress, MacAddress, DeviceType, Manufacturer, Model,\n",[281,771,772],{"class":283,"line":410},[281,773,774],{"class":744},"    SerialNumber). Resolves the API codebase, looks up the target company by identifier, and loads all\n",[281,776,777],{"class":283,"line":472},[281,778,779],{"class":744},"    of that company's configurations with paging, plus configuration types and manufacturers. Each\n",[281,781,782],{"class":283,"line":485},[281,783,784],{"class":744},"    discovered device is matched to an existing configuration by serial number, then MAC address, then\n",[281,786,787],{"class":283,"line":496},[281,788,789],{"class":744},"    name. A match gets a JSON Patch for any of ipAddress, macAddress, serialNumber or modelNumber that\n",[281,791,792],{"class":283,"line":506},[281,793,794],{"class":744},"    changed; no match creates a new configuration of the mapped type. Uses the ConnectWise PSA REST API\n",[281,796,797],{"class":283,"line":512},[281,798,799],{"class":744},"    (apis\u002F3.0) with API member Basic authentication and the clientId header.\n",[281,801,803,805,808],{"class":283,"line":802},12,[281,804,66],{"class":287},[281,806,807],{"class":291},"PARAMETER",[281,809,810],{"class":291}," CsvPath\n",[281,812,814],{"class":283,"line":813},13,[281,815,816],{"class":744},"    Path to the discovery export CSV.\n",[281,818,820,822,824],{"class":283,"line":819},14,[281,821,66],{"class":287},[281,823,807],{"class":291},[281,825,826],{"class":291}," CompanyIdentifier\n",[281,828,830],{"class":283,"line":829},15,[281,831,832],{"class":744},"    Identifier (short name) of the customer company the configurations belong to.\n",[281,834,836,838,840],{"class":283,"line":835},16,[281,837,66],{"class":287},[281,839,807],{"class":291},[281,841,842],{"class":291}," CWServer\n",[281,844,846],{"class":283,"line":845},17,[281,847,848],{"class":744},"    API host name, for example api-na.myconnectwise.net.\n",[281,850,852,854,856],{"class":283,"line":851},18,[281,853,66],{"class":287},[281,855,807],{"class":291},[281,857,858],{"class":291}," CWCompanyId\n",[281,860,862],{"class":283,"line":861},19,[281,863,864],{"class":744},"    Your ConnectWise login company ID, used in authentication.\n",[281,866,868,870,872],{"class":283,"line":867},20,[281,869,66],{"class":287},[281,871,807],{"class":291},[281,873,874],{"class":291}," Credential\n",[281,876,878],{"class":283,"line":877},21,[281,879,880],{"class":744},"    API member keys: user name = public key, password = private key.\n",[281,882,884,886,888],{"class":283,"line":883},22,[281,885,66],{"class":287},[281,887,807],{"class":291},[281,889,890],{"class":291}," ClientId\n",[281,892,894],{"class":283,"line":893},23,[281,895,896],{"class":744},"    The clientId issued on the Developer Network.\n",[281,898,900,902,904],{"class":283,"line":899},24,[281,901,66],{"class":287},[281,903,807],{"class":291},[281,905,906],{"class":291}," DelayMilliseconds\n",[281,908,910],{"class":283,"line":909},25,[281,911,912],{"class":744},"    Pause between write calls, to stay under API throttling on large imports. Defaults to 200.\n",[281,914,916,918],{"class":283,"line":915},26,[281,917,66],{"class":287},[281,919,920],{"class":291},"EXAMPLE\n",[281,922,924],{"class":283,"line":923},27,[281,925,926],{"class":744},"    .\\Sync-CWConfigurationsFromDiscovery.ps1 -CsvPath \"C:\\Discovery\\site-a-scan.csv\" -CompanyIdentifier \"ACMECORP\" -CWServer \"api-na.myconnectwise.net\" -CWCompanyId \"\u003Ccompany-id>\" -Credential $cred -ClientId \"\u003Cclient-id>\" -WhatIf\n",[281,928,930,932],{"class":283,"line":929},28,[281,931,66],{"class":287},[281,933,934],{"class":291},"NOTES\n",[281,936,938],{"class":283,"line":937},29,[281,939,940],{"class":744},"    Author  : Thomas Lasswell (https:\u002F\u002Fwww.techcolumnist.com)\n",[281,942,944],{"class":283,"line":943},30,[281,945,946],{"class":744},"    Version : 1.0 (2025-08-20)\n",[281,948,950],{"class":283,"line":949},31,[281,951,952],{"class":744},"    Requires: PowerShell 5.1 or 7, a ConnectWise PSA API member with company inquire and configuration add\u002Fedit rights\n",[281,954,956],{"class":283,"line":955},32,[281,957,958],{"class":744},"#>\n",[281,960,962,965,968,971,975,978,981],{"class":283,"line":961},33,[281,963,964],{"class":295},"[",[281,966,967],{"class":287},"CmdletBinding",[281,969,970],{"class":295},"(",[281,972,974],{"class":973},"s9osk","SupportsShouldProcess",[281,976,977],{"class":291}," =",[281,979,980],{"class":287}," $true",[281,982,983],{"class":295},")]\n",[281,985,987,990],{"class":283,"line":986},34,[281,988,989],{"class":291},"param",[281,991,992],{"class":295},"(\n",[281,994,996,998,1001,1003,1006,1008,1010],{"class":283,"line":995},35,[281,997,315],{"class":295},[281,999,1000],{"class":287},"Parameter",[281,1002,970],{"class":295},[281,1004,1005],{"class":973},"Mandatory",[281,1007,977],{"class":291},[281,1009,980],{"class":287},[281,1011,983],{"class":295},[281,1013,1015,1017,1020,1023],{"class":283,"line":1014},36,[281,1016,315],{"class":295},[281,1018,1019],{"class":291},"string",[281,1021,1022],{"class":295},"]$CsvPath",[281,1024,1025],{"class":291},",\n",[281,1027,1029],{"class":283,"line":1028},37,[281,1030,1032],{"emptyLinePlaceholder":1031},true,"\n",[281,1034,1036,1038,1040,1042,1044,1046,1048],{"class":283,"line":1035},38,[281,1037,315],{"class":295},[281,1039,1000],{"class":287},[281,1041,970],{"class":295},[281,1043,1005],{"class":973},[281,1045,977],{"class":291},[281,1047,980],{"class":287},[281,1049,983],{"class":295},[281,1051,1053,1055,1057,1060],{"class":283,"line":1052},39,[281,1054,315],{"class":295},[281,1056,1019],{"class":291},[281,1058,1059],{"class":295},"]$CompanyIdentifier",[281,1061,1025],{"class":291},[281,1063,1065],{"class":283,"line":1064},40,[281,1066,1032],{"emptyLinePlaceholder":1031},[281,1068,1070,1072,1074,1076,1078,1080,1082],{"class":283,"line":1069},41,[281,1071,315],{"class":295},[281,1073,1000],{"class":287},[281,1075,970],{"class":295},[281,1077,1005],{"class":973},[281,1079,977],{"class":291},[281,1081,980],{"class":287},[281,1083,983],{"class":295},[281,1085,1087,1089,1091,1094],{"class":283,"line":1086},42,[281,1088,315],{"class":295},[281,1090,1019],{"class":291},[281,1092,1093],{"class":295},"]$CWServer",[281,1095,1025],{"class":291},[281,1097,1099],{"class":283,"line":1098},43,[281,1100,1032],{"emptyLinePlaceholder":1031},[281,1102,1104,1106,1108,1110,1112,1114,1116],{"class":283,"line":1103},44,[281,1105,315],{"class":295},[281,1107,1000],{"class":287},[281,1109,970],{"class":295},[281,1111,1005],{"class":973},[281,1113,977],{"class":291},[281,1115,980],{"class":287},[281,1117,983],{"class":295},[281,1119,1121,1123,1125,1128],{"class":283,"line":1120},45,[281,1122,315],{"class":295},[281,1124,1019],{"class":291},[281,1126,1127],{"class":295},"]$CWCompanyId",[281,1129,1025],{"class":291},[281,1131,1133],{"class":283,"line":1132},46,[281,1134,1032],{"emptyLinePlaceholder":1031},[281,1136,1138,1140,1142,1144,1146,1148,1150],{"class":283,"line":1137},47,[281,1139,315],{"class":295},[281,1141,1000],{"class":287},[281,1143,970],{"class":295},[281,1145,1005],{"class":973},[281,1147,977],{"class":291},[281,1149,980],{"class":287},[281,1151,983],{"class":295},[281,1153,1155,1157,1160,1163],{"class":283,"line":1154},48,[281,1156,315],{"class":295},[281,1158,1159],{"class":291},"System.Management.Automation.PSCredential",[281,1161,1162],{"class":295},"]$Credential",[281,1164,1025],{"class":291},[281,1166,1168],{"class":283,"line":1167},49,[281,1169,1032],{"emptyLinePlaceholder":1031},[281,1171,1173,1175,1177,1179,1181,1183,1185],{"class":283,"line":1172},50,[281,1174,315],{"class":295},[281,1176,1000],{"class":287},[281,1178,970],{"class":295},[281,1180,1005],{"class":973},[281,1182,977],{"class":291},[281,1184,980],{"class":287},[281,1186,983],{"class":295},[281,1188,1190,1192,1194,1197],{"class":283,"line":1189},51,[281,1191,315],{"class":295},[281,1193,1019],{"class":291},[281,1195,1196],{"class":295},"]$ClientId",[281,1198,1025],{"class":291},[281,1200,1202],{"class":283,"line":1201},52,[281,1203,1032],{"emptyLinePlaceholder":1031},[281,1205,1207,1209,1211,1213,1215,1217,1220],{"class":283,"line":1206},53,[281,1208,315],{"class":295},[281,1210,1000],{"class":287},[281,1212,970],{"class":295},[281,1214,1005],{"class":973},[281,1216,977],{"class":291},[281,1218,1219],{"class":287}," $false",[281,1221,983],{"class":295},[281,1223,1225,1227,1230,1233,1235],{"class":283,"line":1224},54,[281,1226,315],{"class":295},[281,1228,1229],{"class":291},"int",[281,1231,1232],{"class":295},"]$DelayMilliseconds ",[281,1234,336],{"class":291},[281,1236,1237],{"class":287}," 200\n",[281,1239,1241],{"class":283,"line":1240},55,[281,1242,1243],{"class":295},")\n",[281,1245,1247],{"class":283,"line":1246},56,[281,1248,1032],{"emptyLinePlaceholder":1031},[281,1250,1252,1255,1257],{"class":283,"line":1251},57,[281,1253,1254],{"class":287},"$ErrorActionPreference",[281,1256,977],{"class":291},[281,1258,1259],{"class":299}," 'Stop'\n",[281,1261,1263],{"class":283,"line":1262},58,[281,1264,1032],{"emptyLinePlaceholder":1031},[281,1266,1268],{"class":283,"line":1267},59,[281,1269,1270],{"class":744},"# Basic auth: base64(\"\u003CcompanyId>+\u003CpublicKey>:\u003CprivateKey>\"). The braces stop PowerShell reading \"$name:\" as a scope specifier.\n",[281,1272,1274,1277,1279],{"class":283,"line":1273},60,[281,1275,1276],{"class":295},"$publicKey ",[281,1278,336],{"class":291},[281,1280,1281],{"class":295}," $Credential.UserName\n",[281,1283,1285,1288,1290],{"class":283,"line":1284},61,[281,1286,1287],{"class":295},"$privateKey ",[281,1289,336],{"class":291},[281,1291,1292],{"class":295}," $Credential.GetNetworkCredential().Password\n",[281,1294,1296,1299,1301,1304,1307,1310,1312,1315,1318,1321,1324,1327,1329],{"class":283,"line":1295},62,[281,1297,1298],{"class":295},"$authBytes ",[281,1300,336],{"class":291},[281,1302,1303],{"class":295}," [",[281,1305,1306],{"class":291},"System.Text.Encoding",[281,1308,1309],{"class":295},"]::UTF8.GetBytes(",[281,1311,566],{"class":299},[281,1313,1314],{"class":295},"${CWCompanyId}",[281,1316,1317],{"class":299},"+",[281,1319,1320],{"class":295},"${publicKey}",[281,1322,1323],{"class":299},":",[281,1325,1326],{"class":295},"${privateKey}",[281,1328,566],{"class":299},[281,1330,1243],{"class":295},[281,1332,1334,1337,1339,1342],{"class":283,"line":1333},63,[281,1335,1336],{"class":295},"$headers ",[281,1338,336],{"class":291},[281,1340,1341],{"class":291}," @",[281,1343,327],{"class":295},[281,1345,1347,1350,1352,1355,1358,1360,1363],{"class":283,"line":1346},64,[281,1348,1349],{"class":295},"    Authorization ",[281,1351,336],{"class":291},[281,1353,1354],{"class":299}," \"Basic \"",[281,1356,1357],{"class":291}," +",[281,1359,1303],{"class":295},[281,1361,1362],{"class":291},"System.Convert",[281,1364,1365],{"class":295},"]::ToBase64String($authBytes)\n",[281,1367,1369,1372,1374],{"class":283,"line":1368},65,[281,1370,1371],{"class":295},"    clientId      ",[281,1373,336],{"class":291},[281,1375,1376],{"class":295}," $ClientId\n",[281,1378,1380,1383,1385],{"class":283,"line":1379},66,[281,1381,1382],{"class":295},"    Accept        ",[281,1384,336],{"class":291},[281,1386,1387],{"class":299}," \"application\u002Fjson\"\n",[281,1389,1391],{"class":283,"line":1390},67,[281,1392,1393],{"class":295},"}\n",[281,1395,1397],{"class":283,"line":1396},68,[281,1398,1032],{"emptyLinePlaceholder":1031},[281,1400,1402,1405,1409],{"class":283,"line":1401},69,[281,1403,1404],{"class":291},"function",[281,1406,1408],{"class":1407},"svObZ"," Invoke-CWApi",[281,1410,309],{"class":295},[281,1412,1414,1417],{"class":283,"line":1413},70,[281,1415,1416],{"class":291},"    param",[281,1418,992],{"class":295},[281,1420,1422,1425,1427,1430,1432,1435],{"class":283,"line":1421},71,[281,1423,1424],{"class":295},"        [",[281,1426,1019],{"class":291},[281,1428,1429],{"class":295},"]$Method ",[281,1431,336],{"class":291},[281,1433,1434],{"class":299}," 'Get'",[281,1436,1025],{"class":291},[281,1438,1440,1442,1444,1447],{"class":283,"line":1439},72,[281,1441,1424],{"class":295},[281,1443,1019],{"class":291},[281,1445,1446],{"class":295},"]$Path",[281,1448,1025],{"class":291},[281,1450,1452,1454,1457,1460],{"class":283,"line":1451},73,[281,1453,1424],{"class":295},[281,1455,1456],{"class":291},"hashtable",[281,1458,1459],{"class":295},"]$Query",[281,1461,1025],{"class":291},[281,1463,1465],{"class":283,"line":1464},74,[281,1466,1467],{"class":295},"        $Body\n",[281,1469,1471],{"class":283,"line":1470},75,[281,1472,1473],{"class":295},"    )\n",[281,1475,1477],{"class":283,"line":1476},76,[281,1478,1032],{"emptyLinePlaceholder":1031},[281,1480,1482,1485,1487,1490,1492,1494,1497,1500,1503],{"class":283,"line":1481},77,[281,1483,1484],{"class":295},"    $uri ",[281,1486,336],{"class":291},[281,1488,1489],{"class":299}," \"",[281,1491,569],{"class":295},[281,1493,733],{"class":291},[281,1495,1496],{"class":295},":apiBase",[281,1498,1499],{"class":299},"\u002F",[281,1501,1502],{"class":295},"$Path",[281,1504,1505],{"class":299},"\"\n",[281,1507,1509,1512],{"class":283,"line":1508},78,[281,1510,1511],{"class":291},"    if",[281,1513,1514],{"class":295}," ($Query) {\n",[281,1516,1518,1521,1523,1526,1529,1532],{"class":283,"line":1517},79,[281,1519,1520],{"class":295},"        $pairs ",[281,1522,336],{"class":291},[281,1524,1525],{"class":291}," foreach",[281,1527,1528],{"class":295}," ($key ",[281,1530,1531],{"class":291},"in",[281,1533,1534],{"class":295}," $Query.Keys) {\n",[281,1536,1538,1541,1544,1547,1550,1552,1555,1558,1560],{"class":283,"line":1537},80,[281,1539,1540],{"class":299},"            \"{0}={1}\"",[281,1542,1543],{"class":291}," -f",[281,1545,1546],{"class":295}," $key",[281,1548,1549],{"class":291},",",[281,1551,1303],{"class":295},[281,1553,1554],{"class":291},"uri",[281,1556,1557],{"class":295},"]::EscapeDataString([",[281,1559,1019],{"class":291},[281,1561,1562],{"class":295},"]$Query[$key])\n",[281,1564,1566],{"class":283,"line":1565},81,[281,1567,1568],{"class":295},"        }\n",[281,1570,1572,1575,1578,1581,1583,1586,1589,1592],{"class":283,"line":1571},82,[281,1573,1574],{"class":295},"        $uri ",[281,1576,1577],{"class":291},"+=",[281,1579,1580],{"class":299}," \"?\"",[281,1582,1357],{"class":291},[281,1584,1585],{"class":295}," ($pairs ",[281,1587,1588],{"class":291},"-join",[281,1590,1591],{"class":299}," \"&\"",[281,1593,1243],{"class":295},[281,1595,1597],{"class":283,"line":1596},83,[281,1598,509],{"class":295},[281,1600,1602],{"class":283,"line":1601},84,[281,1603,1032],{"emptyLinePlaceholder":1031},[281,1605,1607,1610,1612,1614,1617,1619,1622,1624,1627,1629],{"class":283,"line":1606},85,[281,1608,1609],{"class":295},"    $params ",[281,1611,336],{"class":291},[281,1613,1341],{"class":291},[281,1615,1616],{"class":295},"{ Uri ",[281,1618,336],{"class":291},[281,1620,1621],{"class":295}," $uri; Method ",[281,1623,336],{"class":291},[281,1625,1626],{"class":295}," $Method; Headers ",[281,1628,336],{"class":291},[281,1630,1631],{"class":295}," $headers }\n",[281,1633,1635,1637,1639,1642,1645],{"class":283,"line":1634},86,[281,1636,1511],{"class":291},[281,1638,342],{"class":295},[281,1640,1641],{"class":287},"$null",[281,1643,1644],{"class":291}," -ne",[281,1646,1647],{"class":295}," $Body) {\n",[281,1649,1651],{"class":283,"line":1650},87,[281,1652,1653],{"class":744},"        # -InputObject (not the pipeline) so a one-element patch array stays a JSON array.\n",[281,1655,1657,1660,1663,1666,1668,1670,1672,1675,1678,1680,1683,1685,1688,1691],{"class":283,"line":1656},88,[281,1658,1659],{"class":295},"        $params[",[281,1661,1662],{"class":299},"'Body'",[281,1664,1665],{"class":295},"] ",[281,1667,336],{"class":291},[281,1669,1303],{"class":295},[281,1671,1306],{"class":291},[281,1673,1674],{"class":295},"]::UTF8.GetBytes((",[281,1676,1677],{"class":287},"ConvertTo-Json",[281,1679,292],{"class":291},[281,1681,1682],{"class":295},"InputObject $Body ",[281,1684,659],{"class":291},[281,1686,1687],{"class":295},"Depth ",[281,1689,1690],{"class":287},"6",[281,1692,1693],{"class":295},"))\n",[281,1695,1697,1699,1702,1704,1706],{"class":283,"line":1696},89,[281,1698,1659],{"class":295},[281,1700,1701],{"class":299},"'ContentType'",[281,1703,1665],{"class":295},[281,1705,336],{"class":291},[281,1707,1708],{"class":299}," 'application\u002Fjson'\n",[281,1710,1712],{"class":283,"line":1711},90,[281,1713,509],{"class":295},[281,1715,1717,1720,1723],{"class":283,"line":1716},91,[281,1718,1719],{"class":291},"    return",[281,1721,1722],{"class":287}," Invoke-RestMethod",[281,1724,1725],{"class":295}," @params\n",[281,1727,1729],{"class":283,"line":1728},92,[281,1730,1393],{"class":295},[281,1732,1734],{"class":283,"line":1733},93,[281,1735,1032],{"emptyLinePlaceholder":1031},[281,1737,1739,1741,1744],{"class":283,"line":1738},94,[281,1740,1404],{"class":291},[281,1742,1743],{"class":1407}," Get-CWAll",[281,1745,309],{"class":295},[281,1747,1749,1751,1754,1756,1758,1760,1762,1764],{"class":283,"line":1748},95,[281,1750,1416],{"class":291},[281,1752,1753],{"class":295},"([",[281,1755,1019],{"class":291},[281,1757,1446],{"class":295},[281,1759,1549],{"class":291},[281,1761,1303],{"class":295},[281,1763,1019],{"class":291},[281,1765,1766],{"class":295},"]$Conditions)\n",[281,1768,1770],{"class":283,"line":1769},96,[281,1771,1032],{"emptyLinePlaceholder":1031},[281,1773,1775],{"class":283,"line":1774},97,[281,1776,1777],{"class":744},"    # pageSize is capped at 1000; keep asking until a short page comes back.\n",[281,1779,1781,1784,1786],{"class":283,"line":1780},98,[281,1782,1783],{"class":295},"    $page ",[281,1785,336],{"class":291},[281,1787,1788],{"class":287}," 1\n",[281,1790,1792,1795,1797,1800,1802,1805,1808],{"class":283,"line":1791},99,[281,1793,1794],{"class":295},"    $results ",[281,1796,336],{"class":291},[281,1798,1799],{"class":287}," New-Object",[281,1801,292],{"class":291},[281,1803,1804],{"class":295},"TypeName System.Collections.Generic.List[",[281,1806,1807],{"class":291},"object",[281,1809,1810],{"class":295},"]\n",[281,1812,1814,1817],{"class":283,"line":1813},100,[281,1815,1816],{"class":291},"    do",[281,1818,309],{"class":295},[281,1820,1822,1825,1827,1829,1832,1834,1837,1839,1842],{"class":283,"line":1821},101,[281,1823,1824],{"class":295},"        $query ",[281,1826,336],{"class":291},[281,1828,1341],{"class":291},[281,1830,1831],{"class":295},"{ page ",[281,1833,336],{"class":291},[281,1835,1836],{"class":295}," $page; pageSize ",[281,1838,336],{"class":291},[281,1840,1841],{"class":287}," 1000",[281,1843,380],{"class":295},[281,1845,1847,1850],{"class":283,"line":1846},102,[281,1848,1849],{"class":291},"        if",[281,1851,1852],{"class":295}," ($Conditions) {\n",[281,1854,1856,1859,1862,1864,1866],{"class":283,"line":1855},103,[281,1857,1858],{"class":295},"            $query[",[281,1860,1861],{"class":299},"'conditions'",[281,1863,1665],{"class":295},[281,1865,336],{"class":291},[281,1867,1868],{"class":295}," $Conditions\n",[281,1870,1872],{"class":283,"line":1871},104,[281,1873,1568],{"class":295},[281,1875,1877,1880,1882,1884,1886,1889,1891,1894,1896],{"class":283,"line":1876},105,[281,1878,1879],{"class":295},"        $batch ",[281,1881,336],{"class":291},[281,1883,1341],{"class":291},[281,1885,970],{"class":295},[281,1887,1888],{"class":287},"Invoke-CWApi",[281,1890,292],{"class":291},[281,1892,1893],{"class":295},"Path $Path ",[281,1895,659],{"class":291},[281,1897,1898],{"class":295},"Query $query)\n",[281,1900,1902,1905,1908,1910],{"class":283,"line":1901},106,[281,1903,1904],{"class":291},"        foreach",[281,1906,1907],{"class":295}," ($item ",[281,1909,1531],{"class":291},[281,1911,1912],{"class":295}," $batch) {\n",[281,1914,1916],{"class":283,"line":1915},107,[281,1917,1918],{"class":295},"            $results.Add($item)\n",[281,1920,1922],{"class":283,"line":1921},108,[281,1923,1568],{"class":295},[281,1925,1927,1930],{"class":283,"line":1926},109,[281,1928,1929],{"class":295},"        $page",[281,1931,1932],{"class":291},"++\n",[281,1934,1936,1939,1942,1945,1948,1950],{"class":283,"line":1935},110,[281,1937,1938],{"class":295},"    } ",[281,1940,1941],{"class":291},"while",[281,1943,1944],{"class":295}," ($batch.Count ",[281,1946,1947],{"class":291},"-eq",[281,1949,1841],{"class":287},[281,1951,1243],{"class":295},[281,1953,1955,1957],{"class":283,"line":1954},111,[281,1956,1719],{"class":291},[281,1958,1959],{"class":295}," $results\n",[281,1961,1963],{"class":283,"line":1962},112,[281,1964,1393],{"class":295},[281,1966,1968],{"class":283,"line":1967},113,[281,1969,1032],{"emptyLinePlaceholder":1031},[281,1971,1973,1975,1978],{"class":283,"line":1972},114,[281,1974,1404],{"class":291},[281,1976,1977],{"class":1407}," ConvertTo-NormalMac",[281,1979,309],{"class":295},[281,1981,1983,1985,1987,1989],{"class":283,"line":1982},115,[281,1984,1416],{"class":291},[281,1986,1753],{"class":295},[281,1988,1019],{"class":291},[281,1990,1991],{"class":295},"]$Mac)\n",[281,1993,1995,1997,2000,2002],{"class":283,"line":1994},116,[281,1996,1511],{"class":291},[281,1998,1999],{"class":295}," ([",[281,2001,1019],{"class":291},[281,2003,2004],{"class":295},"]::IsNullOrWhiteSpace($Mac)) {\n",[281,2006,2008,2011],{"class":283,"line":2007},117,[281,2009,2010],{"class":291},"        return",[281,2012,493],{"class":299},[281,2014,2016],{"class":283,"line":2015},118,[281,2017,509],{"class":295},[281,2019,2021,2023,2026,2029,2032,2034,2037],{"class":283,"line":2020},119,[281,2022,1719],{"class":291},[281,2024,2025],{"class":295}," ($Mac ",[281,2027,2028],{"class":291},"-replace",[281,2030,2031],{"class":299}," '[^0-9A-Fa-f]'",[281,2033,1549],{"class":291},[281,2035,2036],{"class":299}," ''",[281,2038,2039],{"class":295},").ToUpper()\n",[281,2041,2043],{"class":283,"line":2042},120,[281,2044,1393],{"class":295},[281,2046,2048],{"class":283,"line":2047},121,[281,2049,1032],{"emptyLinePlaceholder":1031},[281,2051,2053,2055,2058],{"class":283,"line":2052},122,[281,2054,1404],{"class":291},[281,2056,2057],{"class":1407}," Get-DeviceTypeName",[281,2059,309],{"class":295},[281,2061,2063,2065,2067,2069],{"class":283,"line":2062},123,[281,2064,1416],{"class":291},[281,2066,1753],{"class":295},[281,2068,1019],{"class":291},[281,2070,2071],{"class":295},"]$DeviceType)\n",[281,2073,2075],{"class":283,"line":2074},124,[281,2076,1032],{"emptyLinePlaceholder":1031},[281,2078,2080,2083,2085],{"class":283,"line":2079},125,[281,2081,2082],{"class":291},"    switch",[281,2084,292],{"class":291},[281,2086,2087],{"class":295},"Wildcard ($DeviceType) {\n",[281,2089,2091,2094,2096,2099,2102],{"class":283,"line":2090},126,[281,2092,2093],{"class":299},"        \"*server*\"",[281,2095,374],{"class":295},[281,2097,2098],{"class":291},"return",[281,2100,2101],{"class":299}," \"Server\"",[281,2103,380],{"class":295},[281,2105,2107,2110,2112,2114,2117],{"class":283,"line":2106},127,[281,2108,2109],{"class":299},"        \"*switch*\"",[281,2111,374],{"class":295},[281,2113,2098],{"class":291},[281,2115,2116],{"class":299}," \"Network Device\"",[281,2118,380],{"class":295},[281,2120,2122,2125,2127,2129,2131],{"class":283,"line":2121},128,[281,2123,2124],{"class":299},"        \"*router*\"",[281,2126,374],{"class":295},[281,2128,2098],{"class":291},[281,2130,2116],{"class":299},[281,2132,380],{"class":295},[281,2134,2136,2139,2141,2143,2145],{"class":283,"line":2135},129,[281,2137,2138],{"class":299},"        \"*firewall*\"",[281,2140,374],{"class":295},[281,2142,2098],{"class":291},[281,2144,2116],{"class":299},[281,2146,380],{"class":295},[281,2148,2150,2153,2155,2157,2159],{"class":283,"line":2149},130,[281,2151,2152],{"class":299},"        \"*access point*\"",[281,2154,374],{"class":295},[281,2156,2098],{"class":291},[281,2158,2116],{"class":299},[281,2160,380],{"class":295},[281,2162,2164,2167,2169,2171,2174],{"class":283,"line":2163},131,[281,2165,2166],{"class":299},"        \"*printer*\"",[281,2168,374],{"class":295},[281,2170,2098],{"class":291},[281,2172,2173],{"class":299}," \"Printer\"",[281,2175,380],{"class":295},[281,2177,2179,2182,2184,2186,2189],{"class":283,"line":2178},132,[281,2180,2181],{"class":291},"        default",[281,2183,374],{"class":295},[281,2185,2098],{"class":291},[281,2187,2188],{"class":299}," \"Workstation\"",[281,2190,380],{"class":295},[281,2192,2194],{"class":283,"line":2193},133,[281,2195,509],{"class":295},[281,2197,2199],{"class":283,"line":2198},134,[281,2200,1393],{"class":295},[281,2202,2204],{"class":283,"line":2203},135,[281,2205,1032],{"emptyLinePlaceholder":1031},[281,2207,2209],{"class":283,"line":2208},136,[281,2210,2211],{"class":744},"# The codebase (for example \"v4_6_release\u002F\") is published per company at \u002Flogin\u002Fcompanyinfo\u002F\u003CcompanyId>.\n",[281,2213,2215,2218,2220,2222,2224,2227,2230,2233,2236,2239,2241,2243,2246,2248],{"class":283,"line":2214},137,[281,2216,2217],{"class":295},"$companyInfo ",[281,2219,336],{"class":291},[281,2221,1722],{"class":287},[281,2223,292],{"class":291},[281,2225,2226],{"class":295},"Uri ",[281,2228,2229],{"class":299},"\"https:\u002F\u002F",[281,2231,2232],{"class":295},"$CWServer",[281,2234,2235],{"class":299},"\u002Flogin\u002Fcompanyinfo\u002F",[281,2237,2238],{"class":295},"$CWCompanyId",[281,2240,566],{"class":299},[281,2242,292],{"class":291},[281,2244,2245],{"class":295},"Method Get ",[281,2247,659],{"class":291},[281,2249,2250],{"class":295},"Headers $headers\n",[281,2252,2254,2257,2259,2262,2265],{"class":283,"line":2253},138,[281,2255,2256],{"class":295},"$codebase ",[281,2258,336],{"class":291},[281,2260,2261],{"class":295}," $companyInfo.Codebase.Trim(",[281,2263,2264],{"class":299},"'\u002F'",[281,2266,1243],{"class":295},[281,2268,2270,2272,2274,2277,2279,2282,2284,2286,2289],{"class":283,"line":2269},139,[281,2271,569],{"class":295},[281,2273,733],{"class":291},[281,2275,2276],{"class":295},":apiBase ",[281,2278,336],{"class":291},[281,2280,2281],{"class":299}," \"https:\u002F\u002F",[281,2283,2232],{"class":295},[281,2285,1499],{"class":299},[281,2287,2288],{"class":295},"$codebase",[281,2290,2291],{"class":299},"\u002Fapis\u002F3.0\"\n",[281,2293,2295],{"class":283,"line":2294},140,[281,2296,1032],{"emptyLinePlaceholder":1031},[281,2298,2300,2303,2305,2307,2309,2311,2313,2315,2318,2320,2323,2325,2328,2330,2333,2336,2339,2341,2343],{"class":283,"line":2299},141,[281,2301,2302],{"class":295},"$company ",[281,2304,336],{"class":291},[281,2306,1341],{"class":291},[281,2308,970],{"class":295},[281,2310,1888],{"class":287},[281,2312,292],{"class":291},[281,2314,296],{"class":295},[281,2316,2317],{"class":299},"\"company\u002Fcompanies\"",[281,2319,292],{"class":291},[281,2321,2322],{"class":295},"Query ",[281,2324,324],{"class":291},[281,2326,2327],{"class":295},"{ conditions ",[281,2329,336],{"class":291},[281,2331,2332],{"class":299}," \"identifier=",[281,2334,2335],{"class":287},"`\"",[281,2337,2338],{"class":295},"$CompanyIdentifier",[281,2340,2335],{"class":287},[281,2342,566],{"class":299},[281,2344,2345],{"class":295}," })\n",[281,2347,2349,2352,2355,2358,2361],{"class":283,"line":2348},142,[281,2350,2351],{"class":291},"if",[281,2353,2354],{"class":295}," ($company.Count ",[281,2356,2357],{"class":291},"-ne",[281,2359,2360],{"class":287}," 1",[281,2362,2363],{"class":295},") {\n",[281,2365,2367,2370,2373,2375,2378,2380,2382,2385,2388],{"class":283,"line":2366},143,[281,2368,2369],{"class":291},"    throw",[281,2371,2372],{"class":299}," \"Expected one company with identifier '",[281,2374,2338],{"class":295},[281,2376,2377],{"class":299},"', found ",[281,2379,569],{"class":291},[281,2381,970],{"class":299},[281,2383,2384],{"class":295},"$company.Count",[281,2386,2387],{"class":299},")",[281,2389,2390],{"class":299},".\"\n",[281,2392,2394],{"class":283,"line":2393},144,[281,2395,1393],{"class":295},[281,2397,2399,2402,2404,2407,2409],{"class":283,"line":2398},145,[281,2400,2401],{"class":295},"$companyId ",[281,2403,336],{"class":291},[281,2405,2406],{"class":295}," $company[",[281,2408,365],{"class":287},[281,2410,2411],{"class":295},"].id\n",[281,2413,2415],{"class":283,"line":2414},146,[281,2416,1032],{"emptyLinePlaceholder":1031},[281,2418,2420,2423,2425,2427,2429,2431,2434,2436,2439,2442,2445],{"class":283,"line":2419},147,[281,2421,2422],{"class":295},"$existing ",[281,2424,336],{"class":291},[281,2426,1743],{"class":287},[281,2428,292],{"class":291},[281,2430,296],{"class":295},[281,2432,2433],{"class":299},"\"company\u002Fconfigurations\"",[281,2435,292],{"class":291},[281,2437,2438],{"class":295},"Conditions ",[281,2440,2441],{"class":299},"\"company\u002Fid=",[281,2443,2444],{"class":295},"$companyId",[281,2446,1505],{"class":299},[281,2448,2450,2453,2455,2457],{"class":283,"line":2449},148,[281,2451,2452],{"class":295},"$types ",[281,2454,336],{"class":291},[281,2456,1341],{"class":291},[281,2458,2459],{"class":295},"{}\n",[281,2461,2463,2466,2469,2471,2473,2476,2478,2480,2483],{"class":283,"line":2462},149,[281,2464,2465],{"class":291},"foreach",[281,2467,2468],{"class":295}," ($type ",[281,2470,1531],{"class":291},[281,2472,342],{"class":295},[281,2474,2475],{"class":287},"Get-CWAll",[281,2477,292],{"class":291},[281,2479,296],{"class":295},[281,2481,2482],{"class":299},"\"company\u002Fconfigurations\u002Ftypes\"",[281,2484,2485],{"class":295},")) {\n",[281,2487,2489,2492,2494],{"class":283,"line":2488},150,[281,2490,2491],{"class":295},"    $types[$type.name] ",[281,2493,336],{"class":291},[281,2495,2496],{"class":295}," $type.id\n",[281,2498,2500],{"class":283,"line":2499},151,[281,2501,1393],{"class":295},[281,2503,2505,2508,2510,2512],{"class":283,"line":2504},152,[281,2506,2507],{"class":295},"$manufacturers ",[281,2509,336],{"class":291},[281,2511,1341],{"class":291},[281,2513,2459],{"class":295},[281,2515,2517,2519,2522,2524,2526,2528,2530,2532,2535],{"class":283,"line":2516},153,[281,2518,2465],{"class":291},[281,2520,2521],{"class":295}," ($manufacturer ",[281,2523,1531],{"class":291},[281,2525,342],{"class":295},[281,2527,2475],{"class":287},[281,2529,292],{"class":291},[281,2531,296],{"class":295},[281,2533,2534],{"class":299},"\"procurement\u002Fmanufacturers\"",[281,2536,2485],{"class":295},[281,2538,2540,2543,2545],{"class":283,"line":2539},154,[281,2541,2542],{"class":295},"    $manufacturers[$manufacturer.name] ",[281,2544,336],{"class":291},[281,2546,2547],{"class":295}," $manufacturer.id\n",[281,2549,2551],{"class":283,"line":2550},155,[281,2552,1393],{"class":295},[281,2554,2556],{"class":283,"line":2555},156,[281,2557,1032],{"emptyLinePlaceholder":1031},[281,2559,2561,2564,2567,2569,2572,2574,2577,2579,2582,2584,2586,2589,2591],{"class":283,"line":2560},157,[281,2562,2563],{"class":287},"Write-Host",[281,2565,2566],{"class":299}," \"Codebase: ",[281,2568,2288],{"class":295},[281,2570,2571],{"class":299},"\u002F  Company: ",[281,2573,2338],{"class":295},[281,2575,2576],{"class":299}," (id ",[281,2578,2444],{"class":295},[281,2580,2581],{"class":299},")  Existing configurations: ",[281,2583,569],{"class":291},[281,2585,970],{"class":299},[281,2587,2588],{"class":295},"$existing.Count",[281,2590,2387],{"class":299},[281,2592,1505],{"class":299},[281,2594,2596],{"class":283,"line":2595},158,[281,2597,1032],{"emptyLinePlaceholder":1031},[281,2599,2601],{"class":283,"line":2600},159,[281,2602,2603],{"class":744},"# Index existing configurations for matching. Hashtables are case-insensitive by default.\n",[281,2605,2607,2610,2612,2614],{"class":283,"line":2606},160,[281,2608,2609],{"class":295},"$bySerial ",[281,2611,336],{"class":291},[281,2613,1341],{"class":291},[281,2615,2459],{"class":295},[281,2617,2619,2622,2624,2626],{"class":283,"line":2618},161,[281,2620,2621],{"class":295},"$byMac ",[281,2623,336],{"class":291},[281,2625,1341],{"class":291},[281,2627,2459],{"class":295},[281,2629,2631,2634,2636,2638],{"class":283,"line":2630},162,[281,2632,2633],{"class":295},"$byName ",[281,2635,336],{"class":291},[281,2637,1341],{"class":291},[281,2639,2459],{"class":295},[281,2641,2643,2645,2648,2650],{"class":283,"line":2642},163,[281,2644,2465],{"class":291},[281,2646,2647],{"class":295}," ($config ",[281,2649,1531],{"class":291},[281,2651,2652],{"class":295}," $existing) {\n",[281,2654,2656,2658,2661,2663],{"class":283,"line":2655},164,[281,2657,1511],{"class":291},[281,2659,2660],{"class":295}," ($config.serialNumber) { $bySerial[$config.serialNumber.Trim()] ",[281,2662,336],{"class":291},[281,2664,2665],{"class":295}," $config }\n",[281,2667,2669,2672,2674,2676,2678],{"class":283,"line":2668},165,[281,2670,2671],{"class":295},"    $mac ",[281,2673,336],{"class":291},[281,2675,1977],{"class":287},[281,2677,292],{"class":291},[281,2679,2680],{"class":295},"Mac $config.macAddress\n",[281,2682,2684,2686,2689,2691],{"class":283,"line":2683},166,[281,2685,1511],{"class":291},[281,2687,2688],{"class":295}," ($mac) { $byMac[$mac] ",[281,2690,336],{"class":291},[281,2692,2665],{"class":295},[281,2694,2696,2698,2701,2703],{"class":283,"line":2695},167,[281,2697,1511],{"class":291},[281,2699,2700],{"class":295}," ($config.name) { $byName[$config.name.Trim()] ",[281,2702,336],{"class":291},[281,2704,2665],{"class":295},[281,2706,2708],{"class":283,"line":2707},168,[281,2709,1393],{"class":295},[281,2711,2713],{"class":283,"line":2712},169,[281,2714,1032],{"emptyLinePlaceholder":1031},[281,2716,2718,2721,2723,2725,2727,2729,2731],{"class":283,"line":2717},170,[281,2719,2720],{"class":295},"$devices ",[281,2722,336],{"class":291},[281,2724,1341],{"class":291},[281,2726,970],{"class":295},[281,2728,288],{"class":287},[281,2730,292],{"class":291},[281,2732,2733],{"class":295},"Path $CsvPath)\n",[281,2735,2737,2740,2742],{"class":283,"line":2736},171,[281,2738,2739],{"class":295},"$created ",[281,2741,336],{"class":291},[281,2743,2744],{"class":287}," 0\n",[281,2746,2748,2751,2753],{"class":283,"line":2747},172,[281,2749,2750],{"class":295},"$updated ",[281,2752,336],{"class":291},[281,2754,2744],{"class":287},[281,2756,2758,2761,2763],{"class":283,"line":2757},173,[281,2759,2760],{"class":295},"$unchanged ",[281,2762,336],{"class":291},[281,2764,2744],{"class":287},[281,2766,2768,2771,2773],{"class":283,"line":2767},174,[281,2769,2770],{"class":295},"$skipped ",[281,2772,336],{"class":291},[281,2774,2744],{"class":287},[281,2776,2778],{"class":283,"line":2777},175,[281,2779,1032],{"emptyLinePlaceholder":1031},[281,2781,2783,2785,2788,2790],{"class":283,"line":2782},176,[281,2784,2465],{"class":291},[281,2786,2787],{"class":295}," ($device ",[281,2789,1531],{"class":291},[281,2791,2792],{"class":295}," $devices) {\n",[281,2794,2796,2799,2801,2803,2805,2807,2810,2812,2814],{"class":283,"line":2795},177,[281,2797,2798],{"class":295},"    $hostname ",[281,2800,336],{"class":291},[281,2802,1489],{"class":299},[281,2804,569],{"class":291},[281,2806,970],{"class":299},[281,2808,2809],{"class":295},"$device.Hostname",[281,2811,2387],{"class":299},[281,2813,566],{"class":299},[281,2815,2816],{"class":295},".Trim()\n",[281,2818,2820,2823,2825,2827,2829,2831,2834,2836,2838],{"class":283,"line":2819},178,[281,2821,2822],{"class":295},"    $serial ",[281,2824,336],{"class":291},[281,2826,1489],{"class":299},[281,2828,569],{"class":291},[281,2830,970],{"class":299},[281,2832,2833],{"class":295},"$device.SerialNumber",[281,2835,2387],{"class":299},[281,2837,566],{"class":299},[281,2839,2816],{"class":295},[281,2841,2843,2845,2847,2849,2851],{"class":283,"line":2842},179,[281,2844,2671],{"class":295},[281,2846,336],{"class":291},[281,2848,1977],{"class":287},[281,2850,292],{"class":291},[281,2852,2853],{"class":295},"Mac $device.MacAddress\n",[281,2855,2857],{"class":283,"line":2856},180,[281,2858,1032],{"emptyLinePlaceholder":1031},[281,2860,2862,2864,2866,2869,2872,2875,2878,2881,2883,2885],{"class":283,"line":2861},181,[281,2863,1511],{"class":291},[281,2865,342],{"class":295},[281,2867,2868],{"class":291},"-not",[281,2870,2871],{"class":295}," $hostname ",[281,2873,2874],{"class":291},"-and",[281,2876,2877],{"class":291}," -not",[281,2879,2880],{"class":295}," $serial ",[281,2882,2874],{"class":291},[281,2884,2877],{"class":291},[281,2886,2887],{"class":295}," $mac) {\n",[281,2889,2891,2894],{"class":283,"line":2890},182,[281,2892,2893],{"class":287},"        Write-Warning",[281,2895,2896],{"class":299}," \"Skipping a row with no hostname, serial number or MAC address.\"\n",[281,2898,2900,2903],{"class":283,"line":2899},183,[281,2901,2902],{"class":295},"        $skipped",[281,2904,1932],{"class":291},[281,2906,2908],{"class":283,"line":2907},184,[281,2909,2910],{"class":291},"        continue\n",[281,2912,2914],{"class":283,"line":2913},185,[281,2915,509],{"class":295},[281,2917,2919],{"class":283,"line":2918},186,[281,2920,1032],{"emptyLinePlaceholder":1031},[281,2922,2924,2927,2929],{"class":283,"line":2923},187,[281,2925,2926],{"class":295},"    $match ",[281,2928,336],{"class":291},[281,2930,2931],{"class":287}," $null\n",[281,2933,2935,2938,2940],{"class":283,"line":2934},188,[281,2936,2937],{"class":295},"    $matchedOn ",[281,2939,336],{"class":291},[281,2941,2931],{"class":287},[281,2943,2945,2947,2950,2952],{"class":283,"line":2944},189,[281,2946,1511],{"class":291},[281,2948,2949],{"class":295}," ($serial ",[281,2951,2874],{"class":291},[281,2953,2954],{"class":295}," $bySerial.ContainsKey($serial)) {\n",[281,2956,2958,2961,2963],{"class":283,"line":2957},190,[281,2959,2960],{"class":295},"        $match ",[281,2962,336],{"class":291},[281,2964,2965],{"class":295}," $bySerial[$serial]\n",[281,2967,2969,2972,2974],{"class":283,"line":2968},191,[281,2970,2971],{"class":295},"        $matchedOn ",[281,2973,336],{"class":291},[281,2975,2976],{"class":299}," 'serialNumber'\n",[281,2978,2980,2982,2984,2987,2989],{"class":283,"line":2979},192,[281,2981,1938],{"class":295},[281,2983,442],{"class":291},[281,2985,2986],{"class":295}," ($mac ",[281,2988,2874],{"class":291},[281,2990,2991],{"class":295}," $byMac.ContainsKey($mac)) {\n",[281,2993,2995,2997,2999],{"class":283,"line":2994},193,[281,2996,2960],{"class":295},[281,2998,336],{"class":291},[281,3000,3001],{"class":295}," $byMac[$mac]\n",[281,3003,3005,3007,3009],{"class":283,"line":3004},194,[281,3006,2971],{"class":295},[281,3008,336],{"class":291},[281,3010,3011],{"class":299}," 'macAddress'\n",[281,3013,3015,3017,3019,3022,3024],{"class":283,"line":3014},195,[281,3016,1938],{"class":295},[281,3018,442],{"class":291},[281,3020,3021],{"class":295}," ($hostname ",[281,3023,2874],{"class":291},[281,3025,3026],{"class":295}," $byName.ContainsKey($hostname)) {\n",[281,3028,3030,3032,3034],{"class":283,"line":3029},196,[281,3031,2960],{"class":295},[281,3033,336],{"class":291},[281,3035,3036],{"class":295}," $byName[$hostname]\n",[281,3038,3040,3042,3044],{"class":283,"line":3039},197,[281,3041,2971],{"class":295},[281,3043,336],{"class":291},[281,3045,3046],{"class":299}," 'name'\n",[281,3048,3050],{"class":283,"line":3049},198,[281,3051,509],{"class":295},[281,3053,3055],{"class":283,"line":3054},199,[281,3056,1032],{"emptyLinePlaceholder":1031},[281,3058,3060,3062],{"class":283,"line":3059},200,[281,3061,1511],{"class":291},[281,3063,3064],{"class":295}," ($match) {\n",[281,3066,3068],{"class":283,"line":3067},201,[281,3069,3070],{"class":744},"        # Only fields the scan actually has a value for are compared, so blanks never wipe PSA data.\n",[281,3072,3074,3077,3079,3081,3083,3085,3087],{"class":283,"line":3073},202,[281,3075,3076],{"class":295},"        $operations ",[281,3078,336],{"class":291},[281,3080,1799],{"class":287},[281,3082,292],{"class":291},[281,3084,1804],{"class":295},[281,3086,1807],{"class":291},[281,3088,1810],{"class":295},[281,3090,3092,3095,3097,3099,3101,3103,3105],{"class":283,"line":3091},203,[281,3093,3094],{"class":295},"        $changes ",[281,3096,336],{"class":291},[281,3098,1799],{"class":287},[281,3100,292],{"class":291},[281,3102,1804],{"class":295},[281,3104,1019],{"class":291},[281,3106,1810],{"class":295},[281,3108,3110,3113,3115,3117,3120,3122,3124],{"class":283,"line":3109},204,[281,3111,3112],{"class":295},"        $fields ",[281,3114,336],{"class":291},[281,3116,1303],{"class":295},[281,3118,3119],{"class":291},"ordered",[281,3121,321],{"class":295},[281,3123,324],{"class":291},[281,3125,327],{"class":295},[281,3127,3129,3132,3134,3136,3138,3140,3143,3145,3147],{"class":283,"line":3128},205,[281,3130,3131],{"class":295},"            ipAddress    ",[281,3133,336],{"class":291},[281,3135,1489],{"class":299},[281,3137,569],{"class":291},[281,3139,970],{"class":299},[281,3141,3142],{"class":295},"$device.IPAddress",[281,3144,2387],{"class":299},[281,3146,566],{"class":299},[281,3148,2816],{"class":295},[281,3150,3152,3155,3157,3159,3161,3163,3166,3168,3170],{"class":283,"line":3151},206,[281,3153,3154],{"class":295},"            macAddress   ",[281,3156,336],{"class":291},[281,3158,1489],{"class":299},[281,3160,569],{"class":291},[281,3162,970],{"class":299},[281,3164,3165],{"class":295},"$device.MacAddress",[281,3167,2387],{"class":299},[281,3169,566],{"class":299},[281,3171,2816],{"class":295},[281,3173,3175,3178,3180],{"class":283,"line":3174},207,[281,3176,3177],{"class":295},"            serialNumber ",[281,3179,336],{"class":291},[281,3181,3182],{"class":295}," $serial\n",[281,3184,3186,3189,3191,3193,3195,3197,3200,3202,3204],{"class":283,"line":3185},208,[281,3187,3188],{"class":295},"            modelNumber  ",[281,3190,336],{"class":291},[281,3192,1489],{"class":299},[281,3194,569],{"class":291},[281,3196,970],{"class":299},[281,3198,3199],{"class":295},"$device.Model",[281,3201,2387],{"class":299},[281,3203,566],{"class":299},[281,3205,2816],{"class":295},[281,3207,3209],{"class":283,"line":3208},209,[281,3210,1568],{"class":295},[281,3212,3214,3216,3219,3221],{"class":283,"line":3213},210,[281,3215,1904],{"class":291},[281,3217,3218],{"class":295}," ($field ",[281,3220,1531],{"class":291},[281,3222,3223],{"class":295}," $fields.Keys) {\n",[281,3225,3227,3230,3232],{"class":283,"line":3226},211,[281,3228,3229],{"class":295},"            $newValue ",[281,3231,336],{"class":291},[281,3233,3234],{"class":295}," $fields[$field]\n",[281,3236,3238,3241,3243,3245,3247,3249,3252,3254,3257,3259,3261],{"class":283,"line":3237},212,[281,3239,3240],{"class":295},"            $oldValue ",[281,3242,336],{"class":291},[281,3244,1489],{"class":299},[281,3246,569],{"class":291},[281,3248,970],{"class":299},[281,3250,3251],{"class":295},"$match",[281,3253,66],{"class":299},[281,3255,3256],{"class":295},"$field",[281,3258,2387],{"class":299},[281,3260,566],{"class":299},[281,3262,2816],{"class":295},[281,3264,3266,3269,3271,3273,3275,3277,3280,3283,3286,3288,3291,3293,3296,3298,3301,3303],{"class":283,"line":3265},213,[281,3267,3268],{"class":295},"            $same ",[281,3270,336],{"class":291},[281,3272,339],{"class":291},[281,3274,3218],{"class":295},[281,3276,1947],{"class":291},[281,3278,3279],{"class":299}," 'macAddress'",[281,3281,3282],{"class":295},") { (",[281,3284,3285],{"class":287},"ConvertTo-NormalMac",[281,3287,292],{"class":291},[281,3289,3290],{"class":295},"Mac $oldValue) ",[281,3292,1947],{"class":291},[281,3294,3295],{"class":295}," $mac } ",[281,3297,371],{"class":291},[281,3299,3300],{"class":295}," { $oldValue ",[281,3302,1947],{"class":291},[281,3304,3305],{"class":295}," $newValue }\n",[281,3307,3309,3312,3315,3317,3319],{"class":283,"line":3308},214,[281,3310,3311],{"class":291},"            if",[281,3313,3314],{"class":295}," ($newValue ",[281,3316,2874],{"class":291},[281,3318,2877],{"class":291},[281,3320,3321],{"class":295}," $same) {\n",[281,3323,3325,3328,3330,3332,3334,3337,3339,3342,3345,3347,3350,3352,3354,3357,3359],{"class":283,"line":3324},215,[281,3326,3327],{"class":295},"                $operations.Add([",[281,3329,318],{"class":291},[281,3331,321],{"class":295},[281,3333,324],{"class":291},[281,3335,3336],{"class":295},"{ op ",[281,3338,336],{"class":291},[281,3340,3341],{"class":299}," \"replace\"",[281,3343,3344],{"class":295},"; path ",[281,3346,336],{"class":291},[281,3348,3349],{"class":299}," \"\u002F",[281,3351,3256],{"class":295},[281,3353,566],{"class":299},[281,3355,3356],{"class":295},"; value ",[281,3358,336],{"class":291},[281,3360,3361],{"class":295}," $newValue })\n",[281,3363,3365,3368,3370,3372,3374,3377,3380,3383,3386],{"class":283,"line":3364},216,[281,3366,3367],{"class":295},"                $changes.Add(",[281,3369,566],{"class":299},[281,3371,3256],{"class":295},[281,3373,342],{"class":299},[281,3375,3376],{"class":295},"$oldValue",[281,3378,3379],{"class":299}," -> ",[281,3381,3382],{"class":295},"$newValue",[281,3384,3385],{"class":299},")\"",[281,3387,1243],{"class":295},[281,3389,3391],{"class":283,"line":3390},217,[281,3392,3393],{"class":295},"            }\n",[281,3395,3397],{"class":283,"line":3396},218,[281,3398,1568],{"class":295},[281,3400,3402],{"class":283,"line":3401},219,[281,3403,1032],{"emptyLinePlaceholder":1031},[281,3405,3407,3409,3412,3414,3417],{"class":283,"line":3406},220,[281,3408,1849],{"class":291},[281,3410,3411],{"class":295}," ($operations.Count ",[281,3413,1947],{"class":291},[281,3415,3416],{"class":287}," 0",[281,3418,2363],{"class":295},[281,3420,3422,3425],{"class":283,"line":3421},221,[281,3423,3424],{"class":295},"            $unchanged",[281,3426,1932],{"class":291},[281,3428,3430],{"class":283,"line":3429},222,[281,3431,3432],{"class":291},"            continue\n",[281,3434,3436],{"class":283,"line":3435},223,[281,3437,1568],{"class":295},[281,3439,3441],{"class":283,"line":3440},224,[281,3442,1032],{"emptyLinePlaceholder":1031},[281,3444,3446,3448,3450,3453,3456,3458,3460,3462,3465,3467,3470,3472,3474,3477,3479,3482,3485,3487,3489,3492,3494,3496,3499,3502,3505,3507,3509],{"class":283,"line":3445},225,[281,3447,1849],{"class":291},[281,3449,342],{"class":295},[281,3451,3452],{"class":287},"$PSCmdlet",[281,3454,3455],{"class":295},".ShouldProcess(",[281,3457,566],{"class":299},[281,3459,569],{"class":291},[281,3461,970],{"class":299},[281,3463,3464],{"class":295},"$match.name",[281,3466,2387],{"class":299},[281,3468,3469],{"class":299}," (config ",[281,3471,569],{"class":291},[281,3473,970],{"class":299},[281,3475,3476],{"class":295},"$match.id",[281,3478,2387],{"class":299},[281,3480,3481],{"class":299},", matched on ",[281,3483,3484],{"class":295},"$matchedOn",[281,3486,3385],{"class":299},[281,3488,1549],{"class":291},[281,3490,3491],{"class":299}," \"PATCH ",[281,3493,569],{"class":291},[281,3495,970],{"class":299},[281,3497,3498],{"class":295},"$changes",[281,3500,3501],{"class":291}," -join",[281,3503,3504],{"class":299}," ', '",[281,3506,2387],{"class":299},[281,3508,566],{"class":299},[281,3510,2485],{"class":295},[281,3512,3514,3517,3519,3522,3524,3526,3529,3531,3533,3535,3537,3539,3541,3544,3546],{"class":283,"line":3513},226,[281,3515,3516],{"class":287},"            Invoke-CWApi",[281,3518,292],{"class":291},[281,3520,3521],{"class":295},"Method Patch ",[281,3523,659],{"class":291},[281,3525,296],{"class":295},[281,3527,3528],{"class":299},"\"company\u002Fconfigurations\u002F",[281,3530,569],{"class":291},[281,3532,970],{"class":299},[281,3534,3476],{"class":295},[281,3536,2387],{"class":299},[281,3538,566],{"class":299},[281,3540,292],{"class":291},[281,3542,3543],{"class":295},"Body $operations.ToArray() ",[281,3545,518],{"class":291},[281,3547,3548],{"class":287}," Out-Null\n",[281,3550,3552,3555,3558,3560,3562,3564,3566,3569,3571,3573,3575,3577,3579,3581],{"class":283,"line":3551},227,[281,3553,3554],{"class":287},"            Write-Host",[281,3556,3557],{"class":299}," \"Updated ",[281,3559,569],{"class":291},[281,3561,970],{"class":299},[281,3563,3464],{"class":295},[281,3565,2387],{"class":299},[281,3567,3568],{"class":299},": ",[281,3570,569],{"class":291},[281,3572,970],{"class":299},[281,3574,3498],{"class":295},[281,3576,3501],{"class":291},[281,3578,3504],{"class":299},[281,3580,2387],{"class":299},[281,3582,1505],{"class":299},[281,3584,3586,3589,3591],{"class":283,"line":3585},228,[281,3587,3588],{"class":287},"            Start-Sleep",[281,3590,292],{"class":291},[281,3592,3593],{"class":295},"Milliseconds $DelayMilliseconds\n",[281,3595,3597],{"class":283,"line":3596},229,[281,3598,1568],{"class":295},[281,3600,3602,3605],{"class":283,"line":3601},230,[281,3603,3604],{"class":295},"        $updated",[281,3606,1932],{"class":291},[281,3608,3610],{"class":283,"line":3609},231,[281,3611,2910],{"class":291},[281,3613,3615],{"class":283,"line":3614},232,[281,3616,509],{"class":295},[281,3618,3620],{"class":283,"line":3619},233,[281,3621,1032],{"emptyLinePlaceholder":1031},[281,3623,3625,3627,3629,3631],{"class":283,"line":3624},234,[281,3626,1511],{"class":291},[281,3628,342],{"class":295},[281,3630,2868],{"class":291},[281,3632,3633],{"class":295}," $hostname) {\n",[281,3635,3637,3639,3642,3645,3648,3651],{"class":283,"line":3636},235,[281,3638,2893],{"class":287},[281,3640,3641],{"class":299}," \"No match for serial '",[281,3643,3644],{"class":295},"$serial",[281,3646,3647],{"class":299},"' \u002F MAC '",[281,3649,3650],{"class":295},"$mac",[281,3652,3653],{"class":299},"' and no hostname to create it with - skipped.\"\n",[281,3655,3657,3659],{"class":283,"line":3656},236,[281,3658,2902],{"class":295},[281,3660,1932],{"class":291},[281,3662,3664],{"class":283,"line":3663},237,[281,3665,2910],{"class":291},[281,3667,3669],{"class":283,"line":3668},238,[281,3670,509],{"class":295},[281,3672,3674],{"class":283,"line":3673},239,[281,3675,1032],{"emptyLinePlaceholder":1031},[281,3677,3679,3682,3684,3686,3688],{"class":283,"line":3678},240,[281,3680,3681],{"class":295},"    $typeName ",[281,3683,336],{"class":291},[281,3685,2057],{"class":287},[281,3687,292],{"class":291},[281,3689,3690],{"class":295},"DeviceType $device.DeviceType\n",[281,3692,3694,3696,3698,3700],{"class":283,"line":3693},241,[281,3695,1511],{"class":291},[281,3697,342],{"class":295},[281,3699,2868],{"class":291},[281,3701,3702],{"class":295}," $types.ContainsKey($typeName)) {\n",[281,3704,3706,3708,3711,3714,3717,3720],{"class":283,"line":3705},242,[281,3707,2893],{"class":287},[281,3709,3710],{"class":299}," \"Configuration type '",[281,3712,3713],{"class":295},"$typeName",[281,3715,3716],{"class":299},"' doesn't exist in PSA - skipped ",[281,3718,3719],{"class":295},"$hostname",[281,3721,2390],{"class":299},[281,3723,3725,3727],{"class":283,"line":3724},243,[281,3726,2902],{"class":295},[281,3728,1932],{"class":291},[281,3730,3732],{"class":283,"line":3731},244,[281,3733,2910],{"class":291},[281,3735,3737],{"class":283,"line":3736},245,[281,3738,509],{"class":295},[281,3740,3742],{"class":283,"line":3741},246,[281,3743,1032],{"emptyLinePlaceholder":1031},[281,3745,3747,3749,3751,3753,3756,3758,3761,3763,3765],{"class":283,"line":3746},247,[281,3748,1511],{"class":291},[281,3750,342],{"class":295},[281,3752,3452],{"class":287},[281,3754,3755],{"class":295},".ShouldProcess($hostname",[281,3757,1549],{"class":291},[281,3759,3760],{"class":299}," \"Create configuration (type ",[281,3762,3713],{"class":295},[281,3764,3385],{"class":299},[281,3766,2485],{"class":295},[281,3768,3770,3773,3775,3777,3779,3781,3783],{"class":283,"line":3769},248,[281,3771,3772],{"class":295},"        $newConfig ",[281,3774,336],{"class":291},[281,3776,1303],{"class":295},[281,3778,3119],{"class":291},[281,3780,321],{"class":295},[281,3782,324],{"class":291},[281,3784,327],{"class":295},[281,3786,3788,3791,3793],{"class":283,"line":3787},249,[281,3789,3790],{"class":295},"            name         ",[281,3792,336],{"class":291},[281,3794,3795],{"class":295}," $hostname\n",[281,3797,3799,3802,3804,3806,3809,3811],{"class":283,"line":3798},250,[281,3800,3801],{"class":295},"            type         ",[281,3803,336],{"class":291},[281,3805,1341],{"class":291},[281,3807,3808],{"class":295},"{ id ",[281,3810,336],{"class":291},[281,3812,3813],{"class":295}," $types[$typeName] }\n",[281,3815,3817,3820,3822,3824,3826,3828],{"class":283,"line":3816},251,[281,3818,3819],{"class":295},"            company      ",[281,3821,336],{"class":291},[281,3823,1341],{"class":291},[281,3825,3808],{"class":295},[281,3827,336],{"class":291},[281,3829,3830],{"class":295}," $companyId }\n",[281,3832,3834,3836,3838,3840,3842,3844,3846,3848,3850],{"class":283,"line":3833},252,[281,3835,3131],{"class":295},[281,3837,336],{"class":291},[281,3839,1489],{"class":299},[281,3841,569],{"class":291},[281,3843,970],{"class":299},[281,3845,3142],{"class":295},[281,3847,2387],{"class":299},[281,3849,566],{"class":299},[281,3851,2816],{"class":295},[281,3853,3855,3857,3859,3861,3863,3865,3867,3869,3871],{"class":283,"line":3854},253,[281,3856,3154],{"class":295},[281,3858,336],{"class":291},[281,3860,1489],{"class":299},[281,3862,569],{"class":291},[281,3864,970],{"class":299},[281,3866,3165],{"class":295},[281,3868,2387],{"class":299},[281,3870,566],{"class":299},[281,3872,2816],{"class":295},[281,3874,3876,3878,3880],{"class":283,"line":3875},254,[281,3877,3177],{"class":295},[281,3879,336],{"class":291},[281,3881,3182],{"class":295},[281,3883,3885,3887,3889,3891,3893,3895,3897,3899,3901],{"class":283,"line":3884},255,[281,3886,3188],{"class":295},[281,3888,336],{"class":291},[281,3890,1489],{"class":299},[281,3892,569],{"class":291},[281,3894,970],{"class":299},[281,3896,3199],{"class":295},[281,3898,2387],{"class":299},[281,3900,566],{"class":299},[281,3902,2816],{"class":295},[281,3904,3906],{"class":283,"line":3905},256,[281,3907,1568],{"class":295},[281,3909,3911,3913,3916,3918],{"class":283,"line":3910},257,[281,3912,1849],{"class":291},[281,3914,3915],{"class":295}," ($device.Manufacturer ",[281,3917,2874],{"class":291},[281,3919,3920],{"class":295}," $manufacturers.ContainsKey($device.Manufacturer.Trim())) {\n",[281,3922,3924,3927,3930,3932,3934,3936,3938,3940],{"class":283,"line":3923},258,[281,3925,3926],{"class":295},"            $newConfig[",[281,3928,3929],{"class":299},"'manufacturer'",[281,3931,1665],{"class":295},[281,3933,336],{"class":291},[281,3935,1341],{"class":291},[281,3937,3808],{"class":295},[281,3939,336],{"class":291},[281,3941,3942],{"class":295}," $manufacturers[$device.Manufacturer.Trim()] }\n",[281,3944,3946],{"class":283,"line":3945},259,[281,3947,1568],{"class":295},[281,3949,3951,3954,3956,3958,3960,3963,3965,3967,3969,3971],{"class":283,"line":3950},260,[281,3952,3953],{"class":295},"        $result ",[281,3955,336],{"class":291},[281,3957,1408],{"class":287},[281,3959,292],{"class":291},[281,3961,3962],{"class":295},"Method Post ",[281,3964,659],{"class":291},[281,3966,296],{"class":295},[281,3968,2433],{"class":299},[281,3970,292],{"class":291},[281,3972,3973],{"class":295},"Body $newConfig\n",[281,3975,3977,3980,3983,3985,3987,3989,3991,3994,3996,3999,4001],{"class":283,"line":3976},261,[281,3978,3979],{"class":287},"        Write-Host",[281,3981,3982],{"class":299}," \"Created ",[281,3984,3719],{"class":295},[281,3986,3469],{"class":299},[281,3988,569],{"class":291},[281,3990,970],{"class":299},[281,3992,3993],{"class":295},"$result.id",[281,3995,2387],{"class":299},[281,3997,3998],{"class":299},", type ",[281,4000,3713],{"class":295},[281,4002,4003],{"class":299},")\"\n",[281,4005,4007,4010,4012],{"class":283,"line":4006},262,[281,4008,4009],{"class":287},"        Start-Sleep",[281,4011,292],{"class":291},[281,4013,3593],{"class":295},[281,4015,4017],{"class":283,"line":4016},263,[281,4018,509],{"class":295},[281,4020,4022,4025],{"class":283,"line":4021},264,[281,4023,4024],{"class":295},"    $created",[281,4026,1932],{"class":291},[281,4028,4030],{"class":283,"line":4029},265,[281,4031,1393],{"class":295},[281,4033,4035],{"class":283,"line":4034},266,[281,4036,1032],{"emptyLinePlaceholder":1031},[281,4038,4040,4042,4044,4046,4048,4051,4053,4056,4059,4062,4065,4068,4071,4074,4077],{"class":283,"line":4039},267,[281,4041,2563],{"class":287},[281,4043,1489],{"class":299},[281,4045,569],{"class":291},[281,4047,970],{"class":299},[281,4049,4050],{"class":295},"$devices.Count",[281,4052,2387],{"class":299},[281,4054,4055],{"class":299}," discovered device(s): ",[281,4057,4058],{"class":295},"$updated",[281,4060,4061],{"class":299}," updated, ",[281,4063,4064],{"class":295},"$created",[281,4066,4067],{"class":299}," created, ",[281,4069,4070],{"class":295},"$unchanged",[281,4072,4073],{"class":299}," unchanged, ",[281,4075,4076],{"class":295},"$skipped",[281,4078,4079],{"class":299}," skipped.\"\n",[15,4081,4083],{"id":4082},"notes","Notes",[20,4085,4086,4124,4142,4148,4169,4182,4206,4212],{},[23,4087,4088,4091,4092,4095,4096,4098,4099,4101,4102,4105,4106,4108,4109,4112,4113,4116,4117,4120,4121,66],{},[30,4089,4090],{},"The original draft had two real bugs."," It built the auth string as ",[53,4093,4094],{},"\"$CWCompanyId+$CWPublicKey:$CWPrivateKey\"",". Microsoft's quoting rules spell out why that fails: PowerShell treats everything between the ",[53,4097,569],{}," and a following ",[53,4100,1323],{}," as a scope specifier, so the string throws instead of expanding. The fix is braces around each name, as in ",[53,4103,4104],{},"\"${CWPublicKey}:${CWPrivateKey}\"",". And it wrapped ",[53,4107,1677],{}," output in ",[53,4110,4111],{},"[...]",", which produced a nested array whenever more than one field changed. The script now builds the patch as an array and serialises it once. It also sets the content type with ",[53,4114,4115],{},"-ContentType"," rather than a ",[53,4118,4119],{},"Content-Type"," entry in ",[53,4122,4123],{},"-Headers",[23,4125,4126,4129,4130,4133,4134,4137,4138,4141],{},[30,4127,4128],{},"Codebase."," The ",[53,4131,4132],{},"v4_6_release"," path segment is the codebase, and it's published per company at ",[53,4135,4136],{},"https:\u002F\u002F\u003Cserver>\u002Flogin\u002Fcompanyinfo\u002F\u003CcompanyId>"," in the ",[53,4139,4140],{},"Codebase"," field. Reading it at runtime is how the maintained client libraries do it, and it saves editing the script when your instance moves.",[23,4143,4144,4147],{},[30,4145,4146],{},"Matching order matters."," Name-only matching (what the first draft did) creates duplicates when a device is renamed and silently merges two devices that reuse a name. Serial number is the most stable key, MAC next; name is the fallback. Blank values in the scan never overwrite populated fields in PSA.",[23,4149,4150,4153,4154,4157,4158,4161,4162,4165,4166,4168],{},[30,4151,4152],{},"Conditions syntax."," String values in ",[53,4155,4156],{},"conditions"," are wrapped in double quotes (",[53,4159,4160],{},"identifier=\"ACMECORP\"",") and numbers are not (",[53,4163,4164],{},"company\u002Fid=250","). ",[53,4167,1888],{}," URL-encodes the whole value.",[23,4170,4171,4174,4175,4178,4179,4181],{},[30,4172,4173],{},"Paging."," List endpoints return one page at a time; ",[53,4176,4177],{},"pageSize"," is capped at 1,000. ",[53,4180,2475],{}," pages until it gets a short page. Loading the company's configurations once, instead of one lookup per device, is the biggest single saving on API calls.",[23,4183,4184,4187,4188,105,4191,4194,4195,4198,4199,105,4202,4205],{},[30,4185,4186],{},"Reference data."," ",[53,4189,4190],{},"type",[53,4192,4193],{},"manufacturer"," are references, sent as ",[53,4196,4197],{},"@{ id = ... }"," after the script resolves names to IDs from ",[53,4200,4201],{},"company\u002Fconfigurations\u002Ftypes",[53,4203,4204],{},"procurement\u002Fmanufacturers",". Create those records in PSA once, up front; devices whose type doesn't exist are skipped with a warning.",[23,4207,4208,4211],{},[30,4209,4210],{},"Decommissioning is out of scope."," The script doesn't retire configurations for devices that disappeared from a scan. An offline laptop isn't the same as a device that's gone; pair this with a report of configurations not seen in the last few scans and retire those by hand.",[23,4213,4214,4187,4217,4220,4221,4224],{},[30,4215,4216],{},"Secrets.",[53,4218,4219],{},"Export-Clixml"," protects the credential with Windows DPAPI for the current user and machine. For an unattended run under a service account, export the credential while logged on as that account, or use a vault through the ",[53,4222,4223],{},"Microsoft.PowerShell.SecretManagement"," module. Keep the clientId out of public repositories too; it identifies your integration to ConnectWise.",[15,4226,4228],{"id":4227},"source","Source",[20,4230,4231,4239,4246,4253,4260],{},[23,4232,4233],{},[263,4234,4238],{"href":4235,"rel":4236},"https:\u002F\u002Fdeveloper.connectwise.com\u002F",[4237],"nofollow","ConnectWise Developer Network: PSA REST API and clientId registration (sign-in required)",[23,4240,4241],{},[263,4242,4245],{"href":4243,"rel":4244},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fconnectors\u002Fconnectwisepsa\u002F",[4237],"ConnectWise PSA connector reference: credentials, clientId header, conditions and paging parameters (Microsoft Learn)",[23,4247,4248],{},[263,4249,4252],{"href":4250,"rel":4251},"https:\u002F\u002Fgithub.com\u002FHealthITAU\u002Fpyconnectwise",[4237],"pyconnectwise: open-source PSA client, source for the codebase lookup, auth header format and the 1,000 pageSize cap",[23,4254,4255],{},[263,4256,4259],{"href":4257,"rel":4258},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fpowershell\u002Fmodule\u002Fmicrosoft.powershell.core\u002Fabout\u002Fabout_quoting_rules",[4237],"about_Quoting_Rules: a variable followed by a colon",[23,4261,4262],{},[263,4263,4266],{"href":4264,"rel":4265},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fpowershell\u002Fmodule\u002Fmicrosoft.powershell.utility\u002Fexport-clixml",[4237],"Export-Clixml (DPAPI-protected credentials)",[4268,4269,4270],"style",{},"html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}",{"title":277,"searchDepth":312,"depth":312,"links":4272},[4273,4274,4275,4276,4277,4278],{"id":17,"depth":312,"text":18},{"id":112,"depth":312,"text":113},{"id":257,"depth":312,"text":258},{"id":733,"depth":312,"text":734},{"id":4082,"depth":312,"text":4083},{"id":4227,"depth":312,"text":4228},"techcolumnist",[4281,4282],"ps","scripts","2025-08-20T14:00:00Z","Reconcile a network discovery CSV against ConnectWise PSA configurations over the REST API: match by serial, MAC or name, patch what changed, create the rest.","md",false,null,{},"\u002Fblog\u002F2025\u002F08\u002F20\u002Fpowershell-connectwise-sync-configuration-items-from-discovery-scans",{"title":6,"description":4284},[4279],"blog\u002F2025\u002F08\u002F20\u002Fpowershell-connectwise-sync-configuration-items-from-discovery-scans",[276,4294,4295],"connectwise","discovery","\u002F2025\u002F08\u002F20\u002Fpowershell-connectwise-sync-configuration-items-from-discovery-scans\u002F","jWi8TZNMxCX2ZQ3E5wJ3aiziFeMuQ-9xoJOHOxR5_MU",{"title":4299,"description":4300,"date":4301,"url":4302,"categories":4303,"tags":4304,"image":4287,"readingTime":330,"canonical":4279,"sites":4307,"series":4287,"seriesOrder":4287},"PowerShell: Windows – Inventory Installed Software Across a Domain","A script that reads the Uninstall registry keys on many Windows computers in parallel over PowerShell remoting and writes one CSV, without touching Win32_Product.","2025-08-27T14:00:00Z","\u002F2025\u002F08\u002F27\u002Fpowershell-windows-inventory-installed-software-across-a-domain\u002F",[4281,4282],[276,4305,4295,4306],"windows","active-directory",[4279],{"title":4309,"description":4310,"date":4311,"url":4312,"categories":4313,"tags":4315,"image":4287,"readingTime":383,"canonical":4279,"sites":4318,"series":4287,"seriesOrder":4287},"PowerShell: NetApp – Discover Every Volume Over 80 Percent Capacity","Sweep every ONTAP cluster you manage through the ONTAP REST API from PowerShell and report volumes above a capacity threshold, with a read-only login.","2025-08-13T14:00:00Z","\u002F2025\u002F08\u002F13\u002Fpowershell-netapp-discover-every-volume-over-80-percent-capacity\u002F",[4281,4282,4314],"dotps",[276,4316,4317,4295],"netapp","ontap",[4279],[4320,4328,4298],{"title":4321,"description":4322,"date":4323,"url":4324,"categories":4325,"tags":4326,"image":4287,"readingTime":397,"canonical":4279,"sites":4327,"series":4287,"seriesOrder":4287},"PowerShell: Windows – Discover Local Admins Across Every Workstation","A script that reads the local Administrators group on every workstation by SID, survives orphaned-SID errors, and flags members outside an approved allowlist.","2025-10-08T14:00:00Z","\u002F2025\u002F10\u002F08\u002Fpowershell-windows-discover-local-admins-across-every-workstation\u002F",[4281,4282],[276,4305,4295,4306],[4279],{"title":4329,"description":4330,"date":4331,"url":4332,"categories":4333,"tags":4334,"image":4287,"readingTime":383,"canonical":4279,"sites":4336,"series":4287,"seriesOrder":4287},"PowerShell: Azure – Tag Every Untagged Resource in a Subscription","A PowerShell sweep that finds untagged Azure resources and adds only the missing resource group tags, plus the built-in Azure Policy that does it going forward.","2025-09-24T14:00:00Z","\u002F2025\u002F09\u002F24\u002Fpowershell-azure-tag-every-untagged-resource-in-a-subscription\u002F",[4281,4282],[276,4335,4295],"azure",[4279],{"doc":4287,"posts":4338},[],1790052513131]