Blog Posts tagged with Systems Management

Ask a question

Applying Windows 10 Feature Updates with KACE

Here is how I did it. I am sure there are 1000 ways to skin this cat. Hopefully this helps somebody.

Environment Details

WAN devices on approx 20 different remote sites with links from 1MB to 100mb connection speed.

Requirements for my project

  1. Update all windows 10 from x to Windows Version 1703 (OS Build 15063.729). We had multiple versions of Windows 10 ranging from 1511 to 1607.

  2. Upload the 4GB install files to WAN locations only once.

Important info/lingo/links for Windows 10 upgrading.

Windows 10 Version Info - https://goo.gl/6YczDW

Pay attention to difference in Version and Build.

Step 1 - Download ISO and copy to WAN Locations

  1. Download the ISO for 1703 (or version you are trying to update to). You can use the Windows Media Creation Tool or if you want to download directly you can do this trick. Extract the contents of ISO to a folder of your choice.

  2. Copy the entire contents of the folder above to each replication share. If you don't use replication shares this can be just a shared drive on a device in the same location as the device you want to upgrade. This is strickly for bandwidth reasons. If you are not concerned with bandwidth (and time to transfer 4gb) to each location then skip this step. Just make sure that whatever you setup your script in the “Windows Run As” has read Share and NTFS permissions.

Step 2 - Apply Labels to target Devices

Apply a Manual Label to each device you want to upgrade. I used Win10Upgrade-Nov1, Win10Upgrade-Nov7 etc so that you could easily go back and tell by the label when the upgrade was applied. Then after all was good and no issues removed all the manual labels.


Step 3 - Create the Script that does the work

Create Script that will do the actual upgrade. I will not give every script options here but here are the key ones.

  1. Under Deploy Section select Microsoft Windows and choose your labels or devices to target. Again I used manual Labels created in Step 2 above.

  2. Under Tasks Add a task and choose “Run a batch file…” with this as the bat file text. This is straight from this TechNet article. I used a bat file because I store the %kacelocalrepo% as a system variable that is set via GPO for other upgrades that are to large in size for Managed Installs.

    1. %kacelocalrepo%\Win10Build15063\setup.exe /auto upgrade /installfrom %kacelocalrepo%\Win10Build15063\sources\install.wim /dynamicupdate disable

Step 4 - Run the Script

Either use the “Run Now” feature or schedule the script to run once at a specific time. Just personal preference here. There is probably some way to silently do this but I choose to allow the users to cancel because I would rather them cancel the install (its graceful) rather than power off the machine and corrupt the upgrade.

Step 5 - Go fishing! Most Important Step!

Go fishing in your favorite watering hole and come back to upgraded Windows 10 devices. Use KACE GO app to make your boss think you're doing this from land.

Side Notes

I did not use the Windows 10 media creation tool. I used the trick to download the ISO manually. The disadvantages (I think) of this are it installed 1703.0 during this process. Then after that I had to install Cumulative Update for November which is another 932 MB install. Granted at this point “Patch Management” does all my Cumulative Updates and the files are already on the replications shares, but you could have done this all in one task via Using the “Add updates to customized Windows images”. Is installing the Version upgrade separately than the Cumulative upgrade easier to troubleshoot? Sure it is… just throwing that out there as this minimizes downtime for your end users by doing Upgrade instead of doing an Upgrade and then an Update.

View comments (4)

KACE UserKon 2018

KACE UserKon, the only conference dedicated exclusively to KACE users like you, is returning in May 2018! That’s why we’re seeking your input to influence the agenda. For example, do you want sessions on topics like:


  • Integrating and automating with LDAP integration?

  • Maximizing reporting?

  • Managing Windows 10 updates?

  • Managing your mobile devices?

  • Enhanced security and compliance?


Let us know in this 5-minute survey

We look forward to seeing you at KACE UserKon 2018!


View comments (10)

Announcing KACE Systems Management Appliance 8.0 General Availability

We are excited to announce a new version of KACE Systems Management Appliance is now available for download.

Look what's new:

  • Role Based Access Control – Establish control over who has access to which devices. Improve security and oversight.
  • Wake on LAN Improvements – Designate one agent to wake endpoints in a remote subnet. Increase productivity by performing off hour tasks in remote locations.
  • IPv6 Appliance Support - Agent can provide inventory to the Systems Management Appliance via IPv6. Mixed IPv4/IPv6 is supported to meet compliance requirements for government and other organizations.
  • Contract Management - Create & import hardware & software license contracts. Control and reduce non-compliance risk and fines.
  • Knowledge Base editor enhancements – Embedded HTML editor to create rich Knowledge Base articles.

Check out this helpful knowledge article:

 Upgrading a KACE Systems Management Appliance that is Multiple Versions Behind

KACE SMA 6.4 is now in discontinued support. To determine the current support phase of your product, please refer to the KACE SMA life cycle table.

Be sure to check out the KACE SMA Product Support page to find solution articles, tips and tricks, tutorials, documentation, notifications, life cycle tables, training, and a product user forum.

Download Now
Be the first to comment

Agents not checking in! Best troubleshooting practices

Endpoint system management is a critical component of KACE SMA and its understanding play an important role for using side features that rely on device periodic inventory.

Let’s get started by reviewing the ports required for KACE Agent to communicate with KACE SMA:

·        Port 80 – Agent check-in

·        Port 443 – Agent check-in (Mandatory for KACE 8.0)

·        Port 139/445 – Agent/Client provisioning

·        Port 52230 – Agent AMP Persistent connection (6.4 and lower Only).

Note: For additional information please check the following article - Which network ports and URLs are required for the KACE?

KACE Agent performs a number of periodic activities based on communication settings schedules (Settings | Provisioning | Communication Settings); for this configuration, KACE Support recommends to keep the number of connections per hour under 500. The reason for this is to allow KACE SMA manage the different activities on schedule without major delays.

Note: For multi-org KACE SMA this value will apply to all the organizations in total. Example, if KACE SMA has 5 organizations, that would mean each organization should be under 100 connections per hour.

Another value that needs attention is “Load average Score” (Settings | Provisioning | Communication Settings); this particular value should not exceed 8 – 10 rate. In case that this number is high, it would be recommended check communication settings.

What would be the next step?

The next point to be considered is checked how are the services running. A service under failed status will create a direct impact on the agent proper communication; How do we check KACE SMA Services status?

Settings | Support | Run Diagnostic Utilities | Select “Services” Hit Run.

Important Note: If any of services are appearing as” Failed” Status contact KACE Support immediately for assistance.

Additional items to be checked:

A misconfiguration in communication settings, for example, if the schedules exceed 500 connections per hour or let’s say that multiple tasks (Patching, Scripting, etc.) were launch simultaneously these most likely may generate high congestion or a high agent task traffic; in those cases, it will be necessary to see the number of activities being handled by the agents.

How do we find these agent activities? And What specifically we are looking for?

·        Click on Settings | Support | Display Agent task status

·        Use “View By: In Progress”

·        Under “Timeout” column look times showing as negative

If that would be the case, proceed to remove all those showing negative numbers under “Timeout”. Wait for the next inventory cycle and wait for the results.

Let’s review troubleshooting steps and integrate some additional solutions.

What to do when the check-in issue is happening to all or most of the devices?

·        Check that all services are up and running

·        Check communication settings and make proper adjustments – KACE recommends no more than 500 connections per hour overall.

·        Check Agent Tasks – Look if there are activities showing negative numbers

·        Check Device Smart labels: Labels within labels, labels assigned to software and device metering may become corrupted and generate delays or prevent agents to check in.

Other KB articles to take in consideration for troubleshooting:

·        How fast can the KACE SMA appliance complete different tasks per machine? - https://support.quest.com/kace-systems-management-appliance/kb/116816   

·        Agent Communication Issues Checklist (190297) - https://support.quest.com/kace-systems-management-appliance/kb/190297

·        Troubleshooting Agents That Are Not Checking In Windows (112029) - https://support.quest.com/kace-systems-management-appliance/kb/112029


What to do if inventory issue is occurring with only one system or a particular system?

-        Check the number of license nodes and devices in used

-        Is inventory.xml file created, does it show 0 KB, is it updating? - Check C:\ProgramData\Quest\KACE

-        Are the agent services running?

-        Is “amp.conf” file containing the right KACE SMA hostname? – Check C:\ProgramData\Quest\KACE

-        Are PEM cert files correct or present? – Check C:\ProgramData\Quest\KACE – Folder should contain two *.pem files.

Note: In some cases, it will be required to apply a re-trust if PEM files are corrupted. How to apply re-trust command, check following article AMPTOOLS.EXE Command Switches (146458) - https://support.quest.com/kace-systems-management-appliance/kb/146458

-        Check that required ports are opened and KACE folders are not affected by antivirus software (whitelist - C:\ProgramData\Quest\KACE and C:\Program Files (x86)\Quest\KACE)  - For additional details see - Which directories and executables do I need to whitelist for the SMA agent? (111785)

-        See if HDD space in the machine is not full, a full disk will make agent services to fail.

-        Look for WMI related errors. For additional information check the following resources.

·        How to repair or fully rebuild Windows WMI Repository (231983)


·        WMI Isn't Working!


·        WMI Diagnosis Utility



Several important features in KACE SMA make use of the agent inventory cycle and its correct functionality is essential for all the activities to properly run.

What features depend on Agent inventory?

·        Managed installations

·        File Synchronization

·        Replication Shares

·        Smart Labels

What should we know about KACE Agent 8.0?

·        KACE 8.0 exclusively communicate via port 443 - Using KONEA Technology.

·        IPv6 Appliance Support - Agent can provide inventory to the Systems Management Appliance via IPv6

Visit our Website KACE Support where you will be able to find additional documentation, videos, and tutorials.  Need additional assistance, contact KACE Tech Support.

View comments (2)

Powershell Function for Kace REST API

Since there isn't official support for the API from Quest and the documentation provided is, well...lacking. I thought I would post what I use to interface with the API with examples of the endpoints I've been able to use successfully.

One of the biggest hurdles is incorrect paths in the documentation. For instance, /api/mi/managed_installs/add_to_machines is in the documentation, but the actual endpoint is /api/managed_install/managed_installs/add_to_machines. Some endpoints don't return the data they say they do, like /api/managed_install/machines/{MachineID}. it says it returns the MIs that the machine ID is a part of, but it just returns the machine information...which is useless (you could just use /api/inventory/machines).

Anyway, all of that aside, the below code (Powershell function) has examples that use the correct paths, and are tested and working on my 8.0 appliance. I use Powershell 5, and can't guarantee functionality for any previous Powershell versions. Also, be careful, as the API does not prompt for confirmation before processing, it just does it. The examples are in the comment-based help (for use with the Get-Help cmdlet). The function supports both single and multiple ORG appliances. For single org appliances, either omit the organization parameter or use -Organization Default. For multiple orgs, just use the name of the org with the Organization parameter. You can also log into the system org using -Organization System.

Please add comments below for any other paths that you have been able to use. Especially ones that differ from the documentation or aren't explained well in the documentation.

Note: Sorry the formatting is so crazy - it's cleaner in ISE.
#Requires -Version 5

#Initialize the WebSession hash table
if (!$Script:KaceREST) {

    $Script:KaceREST = @{}


#Force TLS 1.2 (required for K1000 8.0)
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

function Send-KaceAPIRequest {
    This function provides an easy(ish) method to interface with the K1000 REST API. 
    THe function will automatically log in to the appliance and establish a web session for the specified organiztion.
    Multiple organizations can be used at once, and the function will maintain a separate web session for each org.
    Data is returned from the function as the content from the full HtmlWebResponseObject that has been converted from JSON into a PSObject using ConvertFrom-Json.
    The -FullContent parameter can be used to return the original HtmlWebResponseObject in its entirety.
      The Kace REST API documentation is rife with incorrect paths. If the paths in the below examples differ from the documentations, then (at least at this point), the documentation is wrong.
      I use Powershell 5. I have done no testing with any previous version of Powershell, nor do I plan to.
      My K1000 is on version 8.0. This function has only been tested with this version.
      Use at your own risk.

    The Url of the K1000. Must begin with either http:// or https://

    HTTP verb to be used in the request. Must be one of the following: GET, POST, PUT, DELETE, OPTIONS, PATCH

    The path to the API endpoint. Must begin with either /api or /ams. Ex. -URI /api/inventory/machines

    Query to be added the request. Must begin with a ?. If there are spaces, then the parameter must be enclosed in double or single quotes. Ex. -Query '?filtering=name eq MACHINE1'

.PARAMETER Organization
    The organization to send the request. Defaults to "Default"

    Only available if the Method is PUT, POST, or PATCH. Accepts a hash table @{Property1=Value1;Property2=Value2}.

.PARAMETER FullContent
    Switch that tells the function to return the full HtmlWebResponseObject instead of the default PsObject. Use for extra troubleshooting information.

Get all machines (limited to 50 devices by default)
    Send-KaceAPIRequest -K1000Url https://K1000 -Method GET -URI /api/inventory/machines

Get all machines (no limit) Note: ALL is case sensitive, but 0 can also be used
    Send-KaceAPIRequest -K1000Url https://K1000 -Method GET -URI /api/inventory/machines -Query '?paging=limit ALL'
    Send-KaceAPIRequest -K1000Url https://K1000 -Method GET -URI /api/inventory/machines -Query '?paging=limit 0'

Get machines based on filters

    Machines with Win 7 enterprise x64 - full machine data -uses Organization called Test
        Send-KaceAPIRequest -K1000Url https://K1000 -Method GET -URI /api/inventory/machines -Query '?shaping=machine all&paging=limit all&filtering=os_name eq Microsoft Windows 7 Enterprise x64' -Organization Test

    Machines with softwre that contains "Chrome" installed - limited machine and software data
        Send-KaceAPIRequest -K1000Url https://K1000 -Method GET -URI /api/inventory/machines -Query '?shaping=machine limited,software limited&paging=limit all&filtering=software.display_name co Chrome'

    Machines in a label named Test - Note: if using label ID (label.id) to filter for devices in a SMART label, know that the ID is based on the manual label that the smart label is associated with, not the ID of the smart label
        Send-KaceAPIRequest -K1000Url https://K1000 -Method GET -URI /api/inventory/machines -Query '?shaping=machine all&paging=limit ALL&filtering=label.name eq Test'

Add machine to Managed Install

    Get machines in set of names
        $Machines = Send-KaceAPIRequest -K1000Url https://K1000 -Method GET -URI /api/inventory/machines -Query '?shaping=machine limited&paging=limit ALL&filtering=name in MACHINE1;MACHINE2'

    Add machines from previous query to managed install with ID 111 in Org Test
    Note: defining the machine IDs as an array is necessary in case only one machine is being added
        Send-KaceAPIRequest -K1000Url https://K1000 -Method PUT -URI /api/managed_install/managed_installs/111/add_to_machines -Organization Test -Body @{Machines=[array]$Machines.Machines.Id}

Remove machines from Managed Install
    Remove same machines from above add request
        Send-KaceAPIRequest -K1000Url https://K1000 -Method PUT -URI /api/managed_install/managed_installs/111/remove_from_machines -Organization Test -Body @{Machines=[array]$Machines.Machines.Id}

Run a script with ID 15 on machines in a label named Test and check the status after 5 seconds

    Get machines and format a string for the below post request (IDs must be separated by commas)
    $Machines = Send-KaceAPIRequest -K1000Url https://K1000 -Method GET -URI /api/inventory/machines -Query '?paging=limit 0&shaping=machine limited&filtering=label.name eq Test'
    [string]$MachineIDs = $null

    foreach ($MachineID in $Machines.Machines.Id) {

        $MachineIDs += ',' + $MachineID


    $MachineIDs = $MachineIDs.Substring(1)
    Note: Returns 0 if failed
    $ScriptRun = Send-KaceAPIRequest -K1000Url https://K1000 -Method POST -URI /api/script/15/actions/run?machineIDs=$MachineIDs

    if ($ScriptRun[0] -ne 0) {

        Start-Sleep -Seconds 5

        #Check Status of request
        Send-KaceAPIRequest -K1000Url $K1Url -Method GET -URI /api/script/runStatus/$ScriptRun


    else {





    Param (

        [Parameter(Position=0,Mandatory=$true,HelpMessage='Must begin with ''http://'' or ''https://''')]
        [ValidateScript({$_ -like "http://*" -or $_ -like "https://*"})]
        [Parameter(Position=1,Mandatory=$true,HelpMessage='Insert a valid HTTP verb: GET, OPTIONS, POST, PUT, DELETE, or PATCH')]

        [Parameter(Position=2,Mandatory=$true,HelpMessage='Must begin with ''/api'' or ''/ams''')]
        [ValidateScript({$_ -like "/api*" -or $_ -like "/ams*"})]

        [ValidateScript({$_ -like "?*"})]


        [ValidateScript({$Script:KaceREST.Keys -contains $Organization})]



    DynamicParam {

        #Define Body paramter if method is PUT, POST, or PATCH
        if ($Method -in ('POST','PUT','PATCH')) {

            #Create parameter attributes
            $BodyParamAttributes = New-Object -Type System.Management.Automation.ParameterAttribute -Property @{

                HelpMessage='Accepts a hastable with the required properties that will be converted to JSON'


            #Add parameter attributes to collection
            $BodyParamAttributeCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]

            #Create parameter
            $BodyParam = New-Object -Type System.Management.Automation.RuntimeDefinedParameter("Body", [Hashtable],$BodyParamAttributeCollection)

            #Define and return parameter
            $BodyParamDictionary = New-Object -Type System.Management.Automation.RuntimeDefinedParameterDictionary
            Return $BodyParamDictionary



    Begin {

        if ($ResetCookies) {



        if (!$Script:KaceREST."$Organization") {

            #Get credentials for login and create login JSON request
            #HTTPS is recommended since credentials are sent in plain text
            #If the password needs to be stored to be able to run API requests for automation, then please read the following articles for doing this as securely as possible.
            #https://www.powershellgallery.com/packages/CredentialManager/2.0 (requires Powershell 5)
            try {
                $RestCredentials = Get-Credential -Message "Type in the K1000 REST Username/Password for Org $Organization"

                $RESTUserName = $RestCredentials.UserName

                if (!$RestCredentials -or $RestCredentials.Password.Length -eq 0) {
                    Throw "Operation cancelled by user or invalid credential object"

                $RESTPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR(($RestCredentials.Password)))

                $LoginBody = ConvertTo-Json -InputObject ([ordered]@{'password'=$RESTPassword;'userName'=$RESTUserName;'organizationName'=$Organization})


            catch {

                if ($_.Exception -eq 'Operation cancelled by user or invalid credential object') {

                    Write-Error -Message "Unable to create login request for $K1000Url`: Invalid credential object or operation cancelled by user."


                Write-Error -Message "$_`nUnable to create login request for $K1000Url.`nPlease check that the credentials are correct."



            #Log in to the API

            try {

                #Create key in the hash table for specified ORG to store Web session
                $script:KaceREST.Add($Organization,(New-Object Microsoft.PowerShell.Commands.WebRequestSession))
                #Post login request
                $LoginRequest = Invoke-WebRequest -Uri ("$K1000Url" + "/ams/shared/api/security/login") -Method Post -ContentType 'application/json' -Headers @{'Accept'='application/json';'x-dell-api-version'=1} -Body $LoginBody -WebSession $script:KaceREST.$Organization -ErrorAction Stop

                #Add CSRF token to web session


            catch {
                #If login failed, clear the web session from the table

                Write-Error -Message "$_`nUnable to log in to REST API at $K1000Url.`nPlease check that the Url and credentials are correct, and that mobile access is enabled for the specified user."




    Process {

        try {
            #Build the request URL
            $RequestUri = "$K1000Url" + "$Uri" + "$Query"

            #Convert the body hash table to JSON
            if ($PSBoundParameters.Body) {

                $Body = ConvertTo-Json -InputObject $PSBoundParameters.Body

            #Send the request. -ContentType and Body parameters are required for PUT/POST requests. They are here for all requests because it simplifies coding and are ignored for the GET method anyway.
            $Response = Invoke-WebRequest -Uri $RequestUri -Method $Method -WebSession $Script:KaceREST.$Organization -ContentType 'application/json' -Body $Body -ErrorAction Stop


        catch {

            Write-Error -Message "$_`n$Method request to `'$RequestUri`' for the $Organization org failed.`nPlease check that the API path is correct and mobile access is enabled for the specified user.`nUse -ResetCookies if you think that the token has expired."



    End {

        #Return the response in friendly format, which is the content from the original HtmlWebResponseObject, converted from JSON to a PSObject (ConvertFrom-JSON). 
        #Use -FullContent to return the original HtmlWebResponseObject
        if ($Response.GetType().Name -eq 'HtmlWebResponseObject') {

            if ($FullContent) {



            else {

                ConvertFrom-JSON -InputObject $Response.Content



        else {

            Write-Error -Message "Unable to return HTML response"




#Define K1 URL amd Organization name
$K1Url = "https://K1000"
$OrgName = "Default"

#Get all machines (limited to 50 devices by default)
$Machines = Send-KaceAPIRequest -K1000Url $K1Url -Method GET -URI /api/inventory/machines -Organization $OrgName
View comments (3)
Showing 331 - 335 of 369 results

Top Contributors

Talk About appdeploy-tips