[{"data":1,"prerenderedAt":1730},["ShallowReactive",2],{"post:\u002F2022\u002F10\u002F12\u002Fautotask-powershell-enable-client-portal-for-all-users\u002F":3},{"post":4,"newer":1680,"older":1689,"related":1699,"series":1728},{"id":5,"title":6,"body":7,"canonical":1659,"categories":1660,"date":1663,"description":1664,"extension":1665,"featured":1666,"hero":1667,"image":1667,"meta":1668,"navigation":244,"path":1669,"readingTime":174,"seo":1670,"series":1667,"seriesOrder":1667,"sites":1671,"source":1673,"stem":1674,"tags":1675,"updated":1677,"url":1678,"__hash__":1679},"blog\u002Fblog\u002F2022\u002F10\u002F12\u002Fautotask-powershell-enable-client-portal-for-all-users.md","PowerShell: Autotask – Enable Client Portal for All Users",{"type":8,"value":9,"toc":1652},"minimark",[10,14,19,40,44,51,143,154,158,161,254,258,1579,1583,1648],[11,12,13],"p",{},"This is a quick one, it’s been forever since I’ve posted here. After moving back to Autotask, there’s still a ton of things to automate. One of the things that was bugging me was the fact you can’t set the client portal to default. Well, here’s a script you can run periodically to enable all the users to have the simple version of the client portal.",[15,16,18],"h2",{"id":17},"requirements","Requirements",[20,21,22,31,34,37],"ul",{},[23,24,25,26,30],"li",{},"PowerShell 3.0 or later (the script uses ",[27,28,29],"code",{},"Invoke-RestMethod",").",[23,32,33],{},"An Autotask REST API user with permission to read companies and contacts and to create client portal users.",[23,35,36],{},"The Autotask REST API base URL for your zone, the API integration code, and the API username and secret, supplied as environment variables (see Parameters).",[23,38,39],{},"Network access to the Autotask REST API.",[15,41,43],{"id":42},"parameters","Parameters",[11,45,46,47,50],{},"The script has no ",[27,48,49],{},"param"," block. It reads its settings from these environment variables, which must be set in the session before it runs.",[52,53,54,73],"table",{},[55,56,57],"thead",{},[58,59,60,64,67,70],"tr",{},[61,62,63],"th",{},"Name",[61,65,66],{},"Type",[61,68,69],{},"Required",[61,71,72],{},"Description",[74,75,76,97,115,129],"tbody",{},[58,77,78,84,87,90],{},[79,80,81],"td",{},[27,82,83],{},"at_uri",[79,85,86],{},"Environment variable (string)",[79,88,89],{},"Yes",[79,91,92,93,96],{},"Base URL of your Autotask REST API zone, without ",[27,94,95],{},"\u002Fv1.0",".",[58,98,99,104,106,108],{},[79,100,101],{},[27,102,103],{},"at_integrationcode",[79,105,86],{},[79,107,89],{},[79,109,110,111,114],{},"API integration code (sent as the ",[27,112,113],{},"ApiIntegrationcode"," header).",[58,116,117,122,124,126],{},[79,118,119],{},[27,120,121],{},"at_username",[79,123,86],{},[79,125,89],{},[79,127,128],{},"Autotask API user name.",[58,130,131,136,138,140],{},[79,132,133],{},[27,134,135],{},"at_secret",[79,137,86],{},[79,139,89],{},[79,141,142],{},"Secret for the Autotask API user.",[11,144,145,146,149,150,153],{},"Two values in the script are specific to the author's Autotask instance and must be adjusted before you run it: the ",[27,147,148],{},"companyCategoryID"," filter and ",[27,151,152],{},"Select-Object -Skip 3",". See Notes.",[15,155,157],{"id":156},"usage","Usage",[11,159,160],{},"Set the environment variables for the current session, then run the script. It lists the contacts it enables as it goes.",[162,163,168],"pre",{"className":164,"code":165,"language":166,"meta":167,"style":167},"language-powershell shiki shiki-themes github-dark","$env:at_uri = \"\u003Cautotask-rest-url>\"\n$env:at_integrationcode = \"\u003Cintegration-code>\"\n$env:at_username = \"\u003Capi-username>\"\n$env:at_secret = \"\u003Capi-secret>\"\n\n.\\Enable-AutotaskClientPortal.ps1\n","powershell","",[27,169,170,194,209,224,239,246],{"__ignoreMap":167},[171,172,175,179,183,186,190],"span",{"class":173,"line":174},"line",1,[171,176,178],{"class":177},"s95oV","$",[171,180,182],{"class":181},"sDLfK","env:",[171,184,185],{"class":177},"at_uri ",[171,187,189],{"class":188},"snl16","=",[171,191,193],{"class":192},"sU2Wk"," \"\u003Cautotask-rest-url>\"\n",[171,195,197,199,201,204,206],{"class":173,"line":196},2,[171,198,178],{"class":177},[171,200,182],{"class":181},[171,202,203],{"class":177},"at_integrationcode ",[171,205,189],{"class":188},[171,207,208],{"class":192}," \"\u003Cintegration-code>\"\n",[171,210,212,214,216,219,221],{"class":173,"line":211},3,[171,213,178],{"class":177},[171,215,182],{"class":181},[171,217,218],{"class":177},"at_username ",[171,220,189],{"class":188},[171,222,223],{"class":192}," \"\u003Capi-username>\"\n",[171,225,227,229,231,234,236],{"class":173,"line":226},4,[171,228,178],{"class":177},[171,230,182],{"class":181},[171,232,233],{"class":177},"at_secret ",[171,235,189],{"class":188},[171,237,238],{"class":192}," \"\u003Capi-secret>\"\n",[171,240,242],{"class":173,"line":241},5,[171,243,245],{"emptyLinePlaceholder":244},true,"\n",[171,247,249,251],{"class":173,"line":248},6,[171,250,96],{"class":177},[171,252,253],{"class":181},"\\Enable-AutotaskClientPortal.ps1\n",[15,255,257],{"id":256},"script","Script",[162,259,261],{"className":164,"code":260,"language":166,"meta":167,"style":167},"\u003C#\n.SYNOPSIS\n    Enables the simple client portal for every active Autotask contact that does not have it yet.\n.DESCRIPTION\n    Queries Autotask companies (filtered by company category), then the active\n    contacts of each company, and compares them with the existing client portal\n    users. For every contact without a client portal user it creates one, with\n    the contact's e-mail address as the user name and a random 10-character\n    password. Settings are read from environment variables, not parameters.\n.PARAMETER at_uri\n    Environment variable. Base URL of your Autotask REST API zone, without \u002Fv1.0.\n.PARAMETER at_integrationcode\n    Environment variable. API integration code (sent as the ApiIntegrationcode header).\n.PARAMETER at_username\n    Environment variable. Autotask API user name.\n.PARAMETER at_secret\n    Environment variable. Secret for the Autotask API user.\n.EXAMPLE\n    $env:at_uri = \"\u003Cautotask-rest-url>\"\n    $env:at_integrationcode = \"\u003Cintegration-code>\"\n    $env:at_username = \"\u003Capi-username>\"\n    $env:at_secret = \"\u003Capi-secret>\"\n    .\\Enable-AutotaskClientPortal.ps1\n.NOTES\n    Author  : Thomas Lasswell (https:\u002F\u002Fwww.techcolumnist.com)\n    Version : 1.0 (2022-10-12)\n    Requires: PowerShell 3.0 or later, Autotask REST API user\n    Adjust  : Select-Object -Skip 3 skips the first three companies returned and\n              companyCategoryID 101 is a category ID from the author's Autotask\n              instance. Change or remove both before running.\n    Limit   : Only companies with 500 or fewer contacts are handled.\n#>\nfunction New-SecurePassword {\n    $Password = \"!?@#$%^&*0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz\".ToCharArray()\n    ($Password | Get-Random -Count 10) -join ''\n}\n\n$at_uri = $($env:at_uri)\n$at_integrationcode = $($env:at_integrationcode)\n$at_username = $($env:at_username)\n$at_secret = $($env:at_secret)\n\n# Autotask headers.\n$headers = New-Object \"System.Collections.Generic.Dictionary[[String],[String]]\"\n$headers.Add(\"ApiIntegrationcode\", \"$at_integrationcode\")\n$headers.Add(\"Content-Type\", 'application\u002Fjson')\n$headers.Add(\"UserName\", \"$at_username\")\n$headers.Add(\"Secret\", \"$at_secret\")\n\n# Get the companies to process.\n$companies = $(Invoke-RestMethod -Uri $($at_uri + '\u002Fv1.0\u002FCompanies\u002Fquery?search={\"IncludeFields\": [\"id\", \"companyName\",\"companyNumber\",\"isActive\"],\"filter\":[{\"op\":\"eq\",\"field\":\"companyCategoryID\",\"value\":\"101\"}]}') -Headers $headers -Method Get).items\n\nforeach ($company in $companies | Select-Object -Skip 3) {\n    # Get the active contacts of the company.\n    $contacts = $(Invoke-RestMethod -Uri $($at_uri + '\u002Fv1.0\u002FContacts\u002Fquery?search={\"IncludeFields\": [\"id\", \"firstName\",\"lastName\",\"isActive\",\"emailAddress\"],\"filter\":[{\"op\":\"and\",\"items\":[{\"op\":\"eq\",\"field\":\"companyID\",\"value\":\"' + $($company.id) + '\"},{\"op\":\"eq\",\"field\":\"isActive\",\"value\":\"true\"}]}]}') -Headers $headers -Method Get).items\n    $query = $null\n    $x = 0\n    $y = 0\n    $clientportal = @()\n\n    # Get the existing client portal users, 100 contacts per query.\n    do {\n        foreach ($contact in $contacts) {\n            if ($query) {\n                $query += ',{\"op\":\"eq\",\"field\":\"contactID\",\"value\":\"' + $($contact.id) + '\"}'\n            }\n            if (!$query) {\n                $query = '{\"op\":\"eq\",\"field\":\"contactID\",\"value\":\"' + $($contact.id) + '\"}'\n            }\n            $y++\n            $x++\n            if ($x -eq $contacts.Count) {\n                $y = 100\n            }\n            if ($y -eq 100) {\n                $postbody = '{\"filter\":[{\"op\":\"or\",\"items\":[' + $query + ']}]}'\n                $clientportal += $(Invoke-RestMethod -Uri $($at_uri + '\u002Fv1.0\u002FClientPortalUsers\u002Fquery') -Body $postbody -Headers $headers -Method Post).items\n                $query = $null\n                $y = 0\n            }\n        }\n    }\n    while ($x -lt $contacts.Count)\n\n    # Create client portal users for the contacts that are missing one.\n    if ($clientportal.Count -ne $contacts.Count) {\n        Write-Host \"Contacts: $($contacts.Count)\"\n        Write-Host \"Enabled: $($clientportal.Count)\"\n        $missing = $null\n        $missing = $contacts.id | Where-Object { $_ -notin $clientportal.contactId }\n        foreach ($miss in $missing) {\n            $contact = $null\n            $contact = $contacts | Where-Object { $miss -eq $_.id }\n            Write-Host \"$($contact.emailAddress)\"\n            $json = [PSObject]@{\n                contactID            = $($contact.id)\n                userName             = \"$($contact.emailAddress)\"\n                securityLevel        = 1\n                password             = \"$(New-SecurePassword)\"\n                numberFormat         = 22\n                dateFormat           = 1\n                timeFormat           = 1\n                isClientPortalActive = $true\n            }\n            $json = $json | ConvertTo-Json\n            Start-Sleep -Milliseconds 10\n            Invoke-RestMethod -Uri $($at_uri + '\u002Fv1.0\u002FClientPortalUsers') -Method POST -Body $json -Headers $headers\n        }\n    }\n}\n",[27,262,263,269,276,281,288,293,298,304,310,316,327,333,343,349,359,365,375,381,389,395,401,407,413,419,427,433,439,445,451,457,463,469,475,488,502,532,538,543,562,579,596,613,618,624,638,662,677,696,715,720,726,770,775,806,812,862,873,884,894,908,913,919,927,941,950,974,980,994,1014,1019,1028,1036,1050,1061,1066,1081,1102,1145,1154,1163,1168,1174,1180,1194,1199,1205,1219,1241,1260,1270,1297,1310,1320,1345,1364,1387,1400,1420,1431,1452,1463,1473,1483,1494,1499,1514,1528,1564,1569,1574],{"__ignoreMap":167},[171,264,265],{"class":173,"line":174},[171,266,268],{"class":267},"sAwPA","\u003C#\n",[171,270,271,273],{"class":173,"line":196},[171,272,96],{"class":181},[171,274,275],{"class":188},"SYNOPSIS\n",[171,277,278],{"class":173,"line":211},[171,279,280],{"class":267},"    Enables the simple client portal for every active Autotask contact that does not have it yet.\n",[171,282,283,285],{"class":173,"line":226},[171,284,96],{"class":181},[171,286,287],{"class":188},"DESCRIPTION\n",[171,289,290],{"class":173,"line":241},[171,291,292],{"class":267},"    Queries Autotask companies (filtered by company category), then the active\n",[171,294,295],{"class":173,"line":248},[171,296,297],{"class":267},"    contacts of each company, and compares them with the existing client portal\n",[171,299,301],{"class":173,"line":300},7,[171,302,303],{"class":267},"    users. For every contact without a client portal user it creates one, with\n",[171,305,307],{"class":173,"line":306},8,[171,308,309],{"class":267},"    the contact's e-mail address as the user name and a random 10-character\n",[171,311,313],{"class":173,"line":312},9,[171,314,315],{"class":267},"    password. Settings are read from environment variables, not parameters.\n",[171,317,319,321,324],{"class":173,"line":318},10,[171,320,96],{"class":181},[171,322,323],{"class":188},"PARAMETER",[171,325,326],{"class":188}," at_uri\n",[171,328,330],{"class":173,"line":329},11,[171,331,332],{"class":267},"    Environment variable. Base URL of your Autotask REST API zone, without \u002Fv1.0.\n",[171,334,336,338,340],{"class":173,"line":335},12,[171,337,96],{"class":181},[171,339,323],{"class":188},[171,341,342],{"class":188}," at_integrationcode\n",[171,344,346],{"class":173,"line":345},13,[171,347,348],{"class":267},"    Environment variable. API integration code (sent as the ApiIntegrationcode header).\n",[171,350,352,354,356],{"class":173,"line":351},14,[171,353,96],{"class":181},[171,355,323],{"class":188},[171,357,358],{"class":188}," at_username\n",[171,360,362],{"class":173,"line":361},15,[171,363,364],{"class":267},"    Environment variable. Autotask API user name.\n",[171,366,368,370,372],{"class":173,"line":367},16,[171,369,96],{"class":181},[171,371,323],{"class":188},[171,373,374],{"class":188}," at_secret\n",[171,376,378],{"class":173,"line":377},17,[171,379,380],{"class":267},"    Environment variable. Secret for the Autotask API user.\n",[171,382,384,386],{"class":173,"line":383},18,[171,385,96],{"class":181},[171,387,388],{"class":188},"EXAMPLE\n",[171,390,392],{"class":173,"line":391},19,[171,393,394],{"class":267},"    $env:at_uri = \"\u003Cautotask-rest-url>\"\n",[171,396,398],{"class":173,"line":397},20,[171,399,400],{"class":267},"    $env:at_integrationcode = \"\u003Cintegration-code>\"\n",[171,402,404],{"class":173,"line":403},21,[171,405,406],{"class":267},"    $env:at_username = \"\u003Capi-username>\"\n",[171,408,410],{"class":173,"line":409},22,[171,411,412],{"class":267},"    $env:at_secret = \"\u003Capi-secret>\"\n",[171,414,416],{"class":173,"line":415},23,[171,417,418],{"class":267},"    .\\Enable-AutotaskClientPortal.ps1\n",[171,420,422,424],{"class":173,"line":421},24,[171,423,96],{"class":181},[171,425,426],{"class":188},"NOTES\n",[171,428,430],{"class":173,"line":429},25,[171,431,432],{"class":267},"    Author  : Thomas Lasswell (https:\u002F\u002Fwww.techcolumnist.com)\n",[171,434,436],{"class":173,"line":435},26,[171,437,438],{"class":267},"    Version : 1.0 (2022-10-12)\n",[171,440,442],{"class":173,"line":441},27,[171,443,444],{"class":267},"    Requires: PowerShell 3.0 or later, Autotask REST API user\n",[171,446,448],{"class":173,"line":447},28,[171,449,450],{"class":267},"    Adjust  : Select-Object -Skip 3 skips the first three companies returned and\n",[171,452,454],{"class":173,"line":453},29,[171,455,456],{"class":267},"              companyCategoryID 101 is a category ID from the author's Autotask\n",[171,458,460],{"class":173,"line":459},30,[171,461,462],{"class":267},"              instance. Change or remove both before running.\n",[171,464,466],{"class":173,"line":465},31,[171,467,468],{"class":267},"    Limit   : Only companies with 500 or fewer contacts are handled.\n",[171,470,472],{"class":173,"line":471},32,[171,473,474],{"class":267},"#>\n",[171,476,478,481,485],{"class":173,"line":477},33,[171,479,480],{"class":188},"function",[171,482,484],{"class":483},"svObZ"," New-SecurePassword",[171,486,487],{"class":177}," {\n",[171,489,491,494,496,499],{"class":173,"line":490},34,[171,492,493],{"class":177},"    $Password ",[171,495,189],{"class":188},[171,497,498],{"class":192}," \"!?@#$%^&*0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz\"",[171,500,501],{"class":177},".ToCharArray()\n",[171,503,505,508,511,514,517,520,523,526,529],{"class":173,"line":504},35,[171,506,507],{"class":177},"    ($Password ",[171,509,510],{"class":188},"|",[171,512,513],{"class":181}," Get-Random",[171,515,516],{"class":188}," -",[171,518,519],{"class":177},"Count ",[171,521,522],{"class":181},"10",[171,524,525],{"class":177},") ",[171,527,528],{"class":188},"-join",[171,530,531],{"class":192}," ''\n",[171,533,535],{"class":173,"line":534},36,[171,536,537],{"class":177},"}\n",[171,539,541],{"class":173,"line":540},37,[171,542,245],{"emptyLinePlaceholder":244},[171,544,546,549,551,554,557,559],{"class":173,"line":545},38,[171,547,548],{"class":177},"$at_uri ",[171,550,189],{"class":188},[171,552,553],{"class":188}," $",[171,555,556],{"class":177},"($",[171,558,182],{"class":181},[171,560,561],{"class":177},"at_uri)\n",[171,563,565,568,570,572,574,576],{"class":173,"line":564},39,[171,566,567],{"class":177},"$at_integrationcode ",[171,569,189],{"class":188},[171,571,553],{"class":188},[171,573,556],{"class":177},[171,575,182],{"class":181},[171,577,578],{"class":177},"at_integrationcode)\n",[171,580,582,585,587,589,591,593],{"class":173,"line":581},40,[171,583,584],{"class":177},"$at_username ",[171,586,189],{"class":188},[171,588,553],{"class":188},[171,590,556],{"class":177},[171,592,182],{"class":181},[171,594,595],{"class":177},"at_username)\n",[171,597,599,602,604,606,608,610],{"class":173,"line":598},41,[171,600,601],{"class":177},"$at_secret ",[171,603,189],{"class":188},[171,605,553],{"class":188},[171,607,556],{"class":177},[171,609,182],{"class":181},[171,611,612],{"class":177},"at_secret)\n",[171,614,616],{"class":173,"line":615},42,[171,617,245],{"emptyLinePlaceholder":244},[171,619,621],{"class":173,"line":620},43,[171,622,623],{"class":267},"# Autotask headers.\n",[171,625,627,630,632,635],{"class":173,"line":626},44,[171,628,629],{"class":177},"$headers ",[171,631,189],{"class":188},[171,633,634],{"class":181}," New-Object",[171,636,637],{"class":192}," \"System.Collections.Generic.Dictionary[[String],[String]]\"\n",[171,639,641,644,647,650,653,656,659],{"class":173,"line":640},45,[171,642,643],{"class":177},"$headers.Add(",[171,645,646],{"class":192},"\"ApiIntegrationcode\"",[171,648,649],{"class":188},",",[171,651,652],{"class":192}," \"",[171,654,655],{"class":177},"$at_integrationcode",[171,657,658],{"class":192},"\"",[171,660,661],{"class":177},")\n",[171,663,665,667,670,672,675],{"class":173,"line":664},46,[171,666,643],{"class":177},[171,668,669],{"class":192},"\"Content-Type\"",[171,671,649],{"class":188},[171,673,674],{"class":192}," 'application\u002Fjson'",[171,676,661],{"class":177},[171,678,680,682,685,687,689,692,694],{"class":173,"line":679},47,[171,681,643],{"class":177},[171,683,684],{"class":192},"\"UserName\"",[171,686,649],{"class":188},[171,688,652],{"class":192},[171,690,691],{"class":177},"$at_username",[171,693,658],{"class":192},[171,695,661],{"class":177},[171,697,699,701,704,706,708,711,713],{"class":173,"line":698},48,[171,700,643],{"class":177},[171,702,703],{"class":192},"\"Secret\"",[171,705,649],{"class":188},[171,707,652],{"class":192},[171,709,710],{"class":177},"$at_secret",[171,712,658],{"class":192},[171,714,661],{"class":177},[171,716,718],{"class":173,"line":717},49,[171,719,245],{"emptyLinePlaceholder":244},[171,721,723],{"class":173,"line":722},50,[171,724,725],{"class":267},"# Get the companies to process.\n",[171,727,729,732,734,736,739,741,743,746,748,751,754,757,759,762,765,767],{"class":173,"line":728},51,[171,730,731],{"class":177},"$companies ",[171,733,189],{"class":188},[171,735,553],{"class":188},[171,737,738],{"class":177},"(",[171,740,29],{"class":181},[171,742,516],{"class":188},[171,744,745],{"class":177},"Uri ",[171,747,178],{"class":188},[171,749,750],{"class":177},"($at_uri ",[171,752,753],{"class":188},"+",[171,755,756],{"class":192}," '\u002Fv1.0\u002FCompanies\u002Fquery?search={\"IncludeFields\": [\"id\", \"companyName\",\"companyNumber\",\"isActive\"],\"filter\":[{\"op\":\"eq\",\"field\":\"companyCategoryID\",\"value\":\"101\"}]}'",[171,758,525],{"class":177},[171,760,761],{"class":188},"-",[171,763,764],{"class":177},"Headers $headers ",[171,766,761],{"class":188},[171,768,769],{"class":177},"Method Get).items\n",[171,771,773],{"class":173,"line":772},52,[171,774,245],{"emptyLinePlaceholder":244},[171,776,778,781,784,787,790,792,795,797,800,803],{"class":173,"line":777},53,[171,779,780],{"class":188},"foreach",[171,782,783],{"class":177}," ($company ",[171,785,786],{"class":188},"in",[171,788,789],{"class":177}," $companies ",[171,791,510],{"class":188},[171,793,794],{"class":181}," Select-Object",[171,796,516],{"class":188},[171,798,799],{"class":177},"Skip ",[171,801,802],{"class":181},"3",[171,804,805],{"class":177},") {\n",[171,807,809],{"class":173,"line":808},54,[171,810,811],{"class":267},"    # Get the active contacts of the company.\n",[171,813,815,818,820,822,824,826,828,830,832,834,836,839,842,844,847,849,852,854,856,858,860],{"class":173,"line":814},55,[171,816,817],{"class":177},"    $contacts ",[171,819,189],{"class":188},[171,821,553],{"class":188},[171,823,738],{"class":177},[171,825,29],{"class":181},[171,827,516],{"class":188},[171,829,745],{"class":177},[171,831,178],{"class":188},[171,833,750],{"class":177},[171,835,753],{"class":188},[171,837,838],{"class":192}," '\u002Fv1.0\u002FContacts\u002Fquery?search={\"IncludeFields\": [\"id\", \"firstName\",\"lastName\",\"isActive\",\"emailAddress\"],\"filter\":[{\"op\":\"and\",\"items\":[{\"op\":\"eq\",\"field\":\"companyID\",\"value\":\"'",[171,840,841],{"class":188}," +",[171,843,553],{"class":188},[171,845,846],{"class":177},"($company.id) ",[171,848,753],{"class":188},[171,850,851],{"class":192}," '\"},{\"op\":\"eq\",\"field\":\"isActive\",\"value\":\"true\"}]}]}'",[171,853,525],{"class":177},[171,855,761],{"class":188},[171,857,764],{"class":177},[171,859,761],{"class":188},[171,861,769],{"class":177},[171,863,865,868,870],{"class":173,"line":864},56,[171,866,867],{"class":177},"    $query ",[171,869,189],{"class":188},[171,871,872],{"class":181}," $null\n",[171,874,876,879,881],{"class":173,"line":875},57,[171,877,878],{"class":177},"    $x ",[171,880,189],{"class":188},[171,882,883],{"class":181}," 0\n",[171,885,887,890,892],{"class":173,"line":886},58,[171,888,889],{"class":177},"    $y ",[171,891,189],{"class":188},[171,893,883],{"class":181},[171,895,897,900,902,905],{"class":173,"line":896},59,[171,898,899],{"class":177},"    $clientportal ",[171,901,189],{"class":188},[171,903,904],{"class":188}," @",[171,906,907],{"class":177},"()\n",[171,909,911],{"class":173,"line":910},60,[171,912,245],{"emptyLinePlaceholder":244},[171,914,916],{"class":173,"line":915},61,[171,917,918],{"class":267},"    # Get the existing client portal users, 100 contacts per query.\n",[171,920,922,925],{"class":173,"line":921},62,[171,923,924],{"class":188},"    do",[171,926,487],{"class":177},[171,928,930,933,936,938],{"class":173,"line":929},63,[171,931,932],{"class":188},"        foreach",[171,934,935],{"class":177}," ($contact ",[171,937,786],{"class":188},[171,939,940],{"class":177}," $contacts) {\n",[171,942,944,947],{"class":173,"line":943},64,[171,945,946],{"class":188},"            if",[171,948,949],{"class":177}," ($query) {\n",[171,951,953,956,959,962,964,966,969,971],{"class":173,"line":952},65,[171,954,955],{"class":177},"                $query ",[171,957,958],{"class":188},"+=",[171,960,961],{"class":192}," ',{\"op\":\"eq\",\"field\":\"contactID\",\"value\":\"'",[171,963,841],{"class":188},[171,965,553],{"class":188},[171,967,968],{"class":177},"($contact.id) ",[171,970,753],{"class":188},[171,972,973],{"class":192}," '\"}'\n",[171,975,977],{"class":173,"line":976},66,[171,978,979],{"class":177},"            }\n",[171,981,983,985,988,991],{"class":173,"line":982},67,[171,984,946],{"class":188},[171,986,987],{"class":177}," (",[171,989,990],{"class":188},"!",[171,992,993],{"class":177},"$query) {\n",[171,995,997,999,1001,1004,1006,1008,1010,1012],{"class":173,"line":996},68,[171,998,955],{"class":177},[171,1000,189],{"class":188},[171,1002,1003],{"class":192}," '{\"op\":\"eq\",\"field\":\"contactID\",\"value\":\"'",[171,1005,841],{"class":188},[171,1007,553],{"class":188},[171,1009,968],{"class":177},[171,1011,753],{"class":188},[171,1013,973],{"class":192},[171,1015,1017],{"class":173,"line":1016},69,[171,1018,979],{"class":177},[171,1020,1022,1025],{"class":173,"line":1021},70,[171,1023,1024],{"class":177},"            $y",[171,1026,1027],{"class":188},"++\n",[171,1029,1031,1034],{"class":173,"line":1030},71,[171,1032,1033],{"class":177},"            $x",[171,1035,1027],{"class":188},[171,1037,1039,1041,1044,1047],{"class":173,"line":1038},72,[171,1040,946],{"class":188},[171,1042,1043],{"class":177}," ($x ",[171,1045,1046],{"class":188},"-eq",[171,1048,1049],{"class":177}," $contacts.Count) {\n",[171,1051,1053,1056,1058],{"class":173,"line":1052},73,[171,1054,1055],{"class":177},"                $y ",[171,1057,189],{"class":188},[171,1059,1060],{"class":181}," 100\n",[171,1062,1064],{"class":173,"line":1063},74,[171,1065,979],{"class":177},[171,1067,1069,1071,1074,1076,1079],{"class":173,"line":1068},75,[171,1070,946],{"class":188},[171,1072,1073],{"class":177}," ($y ",[171,1075,1046],{"class":188},[171,1077,1078],{"class":181}," 100",[171,1080,805],{"class":177},[171,1082,1084,1087,1089,1092,1094,1097,1099],{"class":173,"line":1083},76,[171,1085,1086],{"class":177},"                $postbody ",[171,1088,189],{"class":188},[171,1090,1091],{"class":192}," '{\"filter\":[{\"op\":\"or\",\"items\":['",[171,1093,841],{"class":188},[171,1095,1096],{"class":177}," $query ",[171,1098,753],{"class":188},[171,1100,1101],{"class":192}," ']}]}'\n",[171,1103,1105,1108,1110,1112,1114,1116,1118,1120,1122,1124,1126,1129,1131,1133,1136,1138,1140,1142],{"class":173,"line":1104},77,[171,1106,1107],{"class":177},"                $clientportal ",[171,1109,958],{"class":188},[171,1111,553],{"class":188},[171,1113,738],{"class":177},[171,1115,29],{"class":181},[171,1117,516],{"class":188},[171,1119,745],{"class":177},[171,1121,178],{"class":188},[171,1123,750],{"class":177},[171,1125,753],{"class":188},[171,1127,1128],{"class":192}," '\u002Fv1.0\u002FClientPortalUsers\u002Fquery'",[171,1130,525],{"class":177},[171,1132,761],{"class":188},[171,1134,1135],{"class":177},"Body $postbody ",[171,1137,761],{"class":188},[171,1139,764],{"class":177},[171,1141,761],{"class":188},[171,1143,1144],{"class":177},"Method Post).items\n",[171,1146,1148,1150,1152],{"class":173,"line":1147},78,[171,1149,955],{"class":177},[171,1151,189],{"class":188},[171,1153,872],{"class":181},[171,1155,1157,1159,1161],{"class":173,"line":1156},79,[171,1158,1055],{"class":177},[171,1160,189],{"class":188},[171,1162,883],{"class":181},[171,1164,1166],{"class":173,"line":1165},80,[171,1167,979],{"class":177},[171,1169,1171],{"class":173,"line":1170},81,[171,1172,1173],{"class":177},"        }\n",[171,1175,1177],{"class":173,"line":1176},82,[171,1178,1179],{"class":177},"    }\n",[171,1181,1183,1186,1188,1191],{"class":173,"line":1182},83,[171,1184,1185],{"class":188},"    while",[171,1187,1043],{"class":177},[171,1189,1190],{"class":188},"-lt",[171,1192,1193],{"class":177}," $contacts.Count)\n",[171,1195,1197],{"class":173,"line":1196},84,[171,1198,245],{"emptyLinePlaceholder":244},[171,1200,1202],{"class":173,"line":1201},85,[171,1203,1204],{"class":267},"    # Create client portal users for the contacts that are missing one.\n",[171,1206,1208,1211,1214,1217],{"class":173,"line":1207},86,[171,1209,1210],{"class":188},"    if",[171,1212,1213],{"class":177}," ($clientportal.Count ",[171,1215,1216],{"class":188},"-ne",[171,1218,1049],{"class":177},[171,1220,1222,1225,1228,1230,1232,1235,1238],{"class":173,"line":1221},87,[171,1223,1224],{"class":181},"        Write-Host",[171,1226,1227],{"class":192}," \"Contacts: ",[171,1229,178],{"class":188},[171,1231,738],{"class":192},[171,1233,1234],{"class":177},"$contacts.Count",[171,1236,1237],{"class":192},")",[171,1239,1240],{"class":192},"\"\n",[171,1242,1244,1246,1249,1251,1253,1256,1258],{"class":173,"line":1243},88,[171,1245,1224],{"class":181},[171,1247,1248],{"class":192}," \"Enabled: ",[171,1250,178],{"class":188},[171,1252,738],{"class":192},[171,1254,1255],{"class":177},"$clientportal.Count",[171,1257,1237],{"class":192},[171,1259,1240],{"class":192},[171,1261,1263,1266,1268],{"class":173,"line":1262},89,[171,1264,1265],{"class":177},"        $missing ",[171,1267,189],{"class":188},[171,1269,872],{"class":181},[171,1271,1273,1275,1277,1280,1282,1285,1288,1291,1294],{"class":173,"line":1272},90,[171,1274,1265],{"class":177},[171,1276,189],{"class":188},[171,1278,1279],{"class":177}," $contacts.id ",[171,1281,510],{"class":188},[171,1283,1284],{"class":181}," Where-Object",[171,1286,1287],{"class":177}," { ",[171,1289,1290],{"class":181},"$_",[171,1292,1293],{"class":188}," -notin",[171,1295,1296],{"class":177}," $clientportal.contactId }\n",[171,1298,1300,1302,1305,1307],{"class":173,"line":1299},91,[171,1301,932],{"class":188},[171,1303,1304],{"class":177}," ($miss ",[171,1306,786],{"class":188},[171,1308,1309],{"class":177}," $missing) {\n",[171,1311,1313,1316,1318],{"class":173,"line":1312},92,[171,1314,1315],{"class":177},"            $contact ",[171,1317,189],{"class":188},[171,1319,872],{"class":181},[171,1321,1323,1325,1327,1330,1332,1334,1337,1339,1342],{"class":173,"line":1322},93,[171,1324,1315],{"class":177},[171,1326,189],{"class":188},[171,1328,1329],{"class":177}," $contacts ",[171,1331,510],{"class":188},[171,1333,1284],{"class":181},[171,1335,1336],{"class":177}," { $miss ",[171,1338,1046],{"class":188},[171,1340,1341],{"class":181}," $_",[171,1343,1344],{"class":177},".id }\n",[171,1346,1348,1351,1353,1355,1357,1360,1362],{"class":173,"line":1347},94,[171,1349,1350],{"class":181},"            Write-Host",[171,1352,652],{"class":192},[171,1354,178],{"class":188},[171,1356,738],{"class":192},[171,1358,1359],{"class":177},"$contact.emailAddress",[171,1361,1237],{"class":192},[171,1363,1240],{"class":192},[171,1365,1367,1370,1372,1375,1378,1381,1384],{"class":173,"line":1366},95,[171,1368,1369],{"class":177},"            $json ",[171,1371,189],{"class":188},[171,1373,1374],{"class":177}," [",[171,1376,1377],{"class":188},"PSObject",[171,1379,1380],{"class":177},"]",[171,1382,1383],{"class":188},"@",[171,1385,1386],{"class":177},"{\n",[171,1388,1390,1393,1395,1397],{"class":173,"line":1389},96,[171,1391,1392],{"class":177},"                contactID            ",[171,1394,189],{"class":188},[171,1396,553],{"class":188},[171,1398,1399],{"class":177},"($contact.id)\n",[171,1401,1403,1406,1408,1410,1412,1414,1416,1418],{"class":173,"line":1402},97,[171,1404,1405],{"class":177},"                userName             ",[171,1407,189],{"class":188},[171,1409,652],{"class":192},[171,1411,178],{"class":188},[171,1413,738],{"class":192},[171,1415,1359],{"class":177},[171,1417,1237],{"class":192},[171,1419,1240],{"class":192},[171,1421,1423,1426,1428],{"class":173,"line":1422},98,[171,1424,1425],{"class":177},"                securityLevel        ",[171,1427,189],{"class":188},[171,1429,1430],{"class":181}," 1\n",[171,1432,1434,1437,1439,1441,1443,1445,1448,1450],{"class":173,"line":1433},99,[171,1435,1436],{"class":177},"                password             ",[171,1438,189],{"class":188},[171,1440,652],{"class":192},[171,1442,178],{"class":188},[171,1444,738],{"class":192},[171,1446,1447],{"class":181},"New-SecurePassword",[171,1449,1237],{"class":192},[171,1451,1240],{"class":192},[171,1453,1455,1458,1460],{"class":173,"line":1454},100,[171,1456,1457],{"class":177},"                numberFormat         ",[171,1459,189],{"class":188},[171,1461,1462],{"class":181}," 22\n",[171,1464,1466,1469,1471],{"class":173,"line":1465},101,[171,1467,1468],{"class":177},"                dateFormat           ",[171,1470,189],{"class":188},[171,1472,1430],{"class":181},[171,1474,1476,1479,1481],{"class":173,"line":1475},102,[171,1477,1478],{"class":177},"                timeFormat           ",[171,1480,189],{"class":188},[171,1482,1430],{"class":181},[171,1484,1486,1489,1491],{"class":173,"line":1485},103,[171,1487,1488],{"class":177},"                isClientPortalActive ",[171,1490,189],{"class":188},[171,1492,1493],{"class":181}," $true\n",[171,1495,1497],{"class":173,"line":1496},104,[171,1498,979],{"class":177},[171,1500,1502,1504,1506,1509,1511],{"class":173,"line":1501},105,[171,1503,1369],{"class":177},[171,1505,189],{"class":188},[171,1507,1508],{"class":177}," $json ",[171,1510,510],{"class":188},[171,1512,1513],{"class":181}," ConvertTo-Json\n",[171,1515,1517,1520,1522,1525],{"class":173,"line":1516},106,[171,1518,1519],{"class":181},"            Start-Sleep",[171,1521,516],{"class":188},[171,1523,1524],{"class":177},"Milliseconds ",[171,1526,1527],{"class":181},"10\n",[171,1529,1531,1534,1536,1538,1540,1542,1544,1547,1549,1551,1554,1556,1559,1561],{"class":173,"line":1530},107,[171,1532,1533],{"class":181},"            Invoke-RestMethod",[171,1535,516],{"class":188},[171,1537,745],{"class":177},[171,1539,178],{"class":188},[171,1541,750],{"class":177},[171,1543,753],{"class":188},[171,1545,1546],{"class":192}," '\u002Fv1.0\u002FClientPortalUsers'",[171,1548,525],{"class":177},[171,1550,761],{"class":188},[171,1552,1553],{"class":177},"Method POST ",[171,1555,761],{"class":188},[171,1557,1558],{"class":177},"Body $json ",[171,1560,761],{"class":188},[171,1562,1563],{"class":177},"Headers $headers\n",[171,1565,1567],{"class":173,"line":1566},108,[171,1568,1173],{"class":177},[171,1570,1572],{"class":173,"line":1571},109,[171,1573,1179],{"class":177},[171,1575,1577],{"class":173,"line":1576},110,[171,1578,537],{"class":177},[15,1580,1582],{"id":1581},"notes","Notes",[20,1584,1585,1635,1645],{},[23,1586,1587,1588,1591,1592],{},"There are a few places you might want to update. I use a filter for a specific customer category, so where your ",[27,1589,1590],{},"$companies"," variable is, you may want to change or remove this part of the query:",[162,1593,1597],{"className":1594,"code":1595,"language":1596,"meta":167,"style":167},"language-json shiki shiki-themes github-dark","{\"op\":\"eq\",\"field\":\"companyCategoryID\",\"value\":\"101\"}\n","json",[27,1598,1599],{"__ignoreMap":167},[171,1600,1601,1604,1607,1610,1613,1615,1618,1620,1623,1625,1628,1630,1633],{"class":173,"line":174},[171,1602,1603],{"class":177},"{",[171,1605,1606],{"class":181},"\"op\"",[171,1608,1609],{"class":177},":",[171,1611,1612],{"class":192},"\"eq\"",[171,1614,649],{"class":177},[171,1616,1617],{"class":181},"\"field\"",[171,1619,1609],{"class":177},[171,1621,1622],{"class":192},"\"companyCategoryID\"",[171,1624,649],{"class":177},[171,1626,1627],{"class":181},"\"value\"",[171,1629,1609],{"class":177},[171,1631,1632],{"class":192},"\"101\"",[171,1634,537],{"class":177},[23,1636,1637,1638,1641,1642,1644],{},"Category ",[27,1639,1640],{},"101"," and the ",[27,1643,152],{}," (which skips the first three companies returned) are specific to my Autotask instance. Adjust or remove both for yours.",[23,1646,1647],{},"The script currently only handles companies with 500 or fewer contacts. I’ll update it with a loop to get all the contacts as well.",[1649,1650,1651],"style",{},"html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}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 .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 .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}",{"title":167,"searchDepth":196,"depth":196,"links":1653},[1654,1655,1656,1657,1658],{"id":17,"depth":196,"text":18},{"id":42,"depth":196,"text":43},{"id":156,"depth":196,"text":157},{"id":256,"depth":196,"text":257},{"id":1581,"depth":196,"text":1582},"techcolumnist",[1661,1662],"ps","scripts","2022-10-12T14:13:37Z","This is a quick one, it’s been forever since I’ve posted here. After moving back to Autotask, there’s still a ton of things to automate.","md",false,null,{},"\u002Fblog\u002F2022\u002F10\u002F12\u002Fautotask-powershell-enable-client-portal-for-all-users",{"title":6,"description":1664},[1672,1659],"lasswell","both","blog\u002F2022\u002F10\u002F12\u002Fautotask-powershell-enable-client-portal-for-all-users",[1676,166],"autotask","2026-09-20T00:00:00Z","\u002F2022\u002F10\u002F12\u002Fautotask-powershell-enable-client-portal-for-all-users\u002F","wFqBByf0AdRKA1b4fLUk8kNdbuhbG1QdtvdBu4jsk8A",{"title":1681,"description":1682,"date":1683,"url":1684,"categories":1685,"tags":1687,"image":1667,"readingTime":196,"canonical":1672,"sites":1688,"series":1667,"seriesOrder":1667},"The Remote Work Revolution: Adapting to the New Norm","The shift to remote work, catalyzed by the global pandemic, has ushered in a new era of business operations.","2023-10-12T23:59:44Z","\u002F2023\u002F10\u002F12\u002Fthe-remote-work-revolution-adapting-to-the-new-norm\u002F",[1686],"trends",[],[1672,1659],{"title":1690,"description":1691,"date":1692,"url":1693,"categories":1694,"tags":1695,"image":1667,"readingTime":174,"canonical":1659,"sites":1698,"series":1667,"seriesOrder":1667},"PowerShell: Get Exchange Mailboxes Over XXGB","Simple command turned crazy. I ended up coming up with this due to the fact we have duplicate display names and needed to update for Exchange Online to get mailbox sizes.","2021-02-18T14:46:29Z","\u002F2021\u002F02\u002F18\u002Fpowershell-get-exchange-mailboxes-over-xxgb\u002F",[1661,1662],[166,1696,1697],"exchange","exchange-online",[1672,1659],[1700,1709,1719],{"title":1701,"description":1702,"date":1703,"url":1704,"categories":1705,"tags":1706,"image":1667,"readingTime":174,"canonical":1659,"sites":1708,"series":1667,"seriesOrder":1667},"PowerShell: Autotask – Get Picklist Values","When using AutoTask’s API it’s required to lookup a various amount of picklist values that are used in updating you’re web request.","2015-02-06T18:11:32Z","\u002F2015\u002F02\u002F06\u002Fpowershell-autotask-get-picklist-values\u002F",[1661,1662],[1676,166,1707],"soap",[1672,1659],{"title":1710,"description":1711,"date":1712,"url":1713,"categories":1714,"tags":1715,"image":1667,"readingTime":241,"canonical":1659,"sites":1718,"series":1667,"seriesOrder":1667},"PowerShell: Active Directory – Report Group Membership Sprawl","Rank AD security groups by nesting depth, transitive member count, ownership and staleness for an access review, plus a per-user Kerberos token size estimate.","2025-12-03T14:00:00Z","\u002F2025\u002F12\u002F03\u002Fpowershell-active-directory-report-group-membership-sprawl\u002F",[1661,1662],[166,1716,1717],"active-directory","reporting",[1659],{"title":1720,"description":1721,"date":1722,"url":1723,"categories":1724,"tags":1725,"image":1667,"readingTime":226,"canonical":1659,"sites":1727,"series":1667,"seriesOrder":1667},"PowerShell: Windows Server – Disable SMBv1 Fleet-Wide and Verify","A script that audits SMBv1 access (event 3000), disables the SMBv1 server and optional feature across Windows servers, and reports which ones still need a restart.","2025-11-26T14:00:00Z","\u002F2025\u002F11\u002F26\u002Fpowershell-windows-server-disable-smbv1-fleet-wide-and-verify-it-stuck\u002F",[1661,1662],[166,1726],"windows",[1659],{"doc":1667,"posts":1729},[],1790223957652]