Deploy Monthly Windows Updates

Leave a commentPDQ Deploy, PDQ Inventory

Need to deploy monthly Windows updates to PCs on your network? Good news, we are now offering the Monthly Windows updates for Windows 7, 8.1 and 10 in the PDQ Deploy Package Library!

Take a knee, team. Microsoft recently modified the way that OS updates are delivered. Windows 7 and Windows 8.1 updates now behave a little more like their Windows 10 cousins. Basically, there are two sets of patches that are offered each month for the OS. (We aren’t talking about .NET or IE updates, just the OS). Anyway, Microsoft is no longer offering individual patches for security and bug fixes. Rather they are offering all patches in two different patch sets for Windows 7 and 8.1. They still only offer one OS patch set for Windows 10.

Windows Updates for Windows 7 and 8.1

Security Monthly Quality Rollup

These packages will be called Win 7 – Monthly Rollup and Win 8.1 – Monthly Rollup. These KB updates will, according to Microsoft, contain “all the new security fixes for that month…as well as fixes from all previous monthly rollups”. If you deploy this patch you do not need to deploy the Security-only update listed below.

Security Only Quality Update

These packages are called Win 7 – Security-only Update and Win 8.1 Security-only Update. This patch set isn’t cumulative. It only contains the security fixes for that month. If you deploy the Monthly Rollup package you do NOT need to deploy the security-only packages.

Windows 10 Cumulative Updates

These packages are broken up based on the Release ID of Windows 10. At this writing there are three different releases. There is the initial release, 1511 and 1607.

deploy monthly Windows updates-PackageLibrary-WindowsUpdates

All the packages will have the version listed as [Month][Year]. In the event that more than one patch set comes out in a month the subsequent package versions will be called [Month][Day][Year].

Track Updates using PDQ Inventory

You can use the Collection Library to see up-to-date status of machines and their compliance with the Windows Updates. You can deploy monthly Windows updates to, for example, the Win 7 Monthly Rollup (Old) collection in PDQ Inventory from PDQ Deploy.

Keep an eye out for videos where we demonstrate Auto Deployments of your Windows updates.

At this point we are only making packages for workstations. We are not including Servers in the packages.


Disabling Web Bluetooth API in Google Chrome

Leave a commentPowerShell

Disabling Web Bluetooth API in Google Chrome seems to be on the mind of many administrators in recent days. Google Chrome 56 recently came out (update notes here), it included the fancy new Web Bluetooth API. This allows developers to easily create web applications that can communicate with Bluetooth devices.

While there are many fun and creative things that could be done with this, you may have some privacy red flags popping up in your brain. Because, security.

Assuming that you stumbled upon this blog because you wish to disable it, here is how you would do just that.

Disabling Web Bluetooth API in Google Chrome

Disabling Web Bluetooth API in Google Chrome is pretty straightforward. In fact, Google Chrome policies can be enabled and disabled very easily. They are documented in the Chromium Administrators policy list. Here’s a link directly to the policy we’re going to use when disabling Web Bluetooth API. By default, this setting is not disabled.

There are couple of different ways to change Google Chrome policy settings:

  • Group Policy and Active Directory administrative templates (get them here)
  • Registry modification

Ideally, you’ve downloaded the Google Chrome Active Directory policy templates. With these, you should easily be able to set up a Group Policy Object (GPO) to get this setting deployed throughout your domain.

Seriously, folks. Use Group Policy to apply these settings and live the dream.

That being said, however, I also ♥ PowerShell and want to show you how you could tackle this with PowerShell.

Setting up via GPO

After grabbing those Google Chrome administrative templates, you’ll need to create a Group Policy Object that enables the following:

  • Location – Computer Configuration > Administrative Templates > Google > Google Chrome > Content Settings
  • Setting – Control use of the Web Bluetooth API
  • Value – “Do not allow any site to request access to Bluetooth devices via the Web Bluetooth API”

In addition to the instructions above, here are some pretty screenshots to show the process.

Disabling Web Bluetooth API - Web Bluetooth API - GPO Editor

Web Bluetooth API - GPO Setting

Setting up via Registry Key

In order to disable the Web Bluetooth API manually, you’ll want to create the following in your registry:

  • Location –  HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome\
  • Setting –  DefaultWebBluetoothGuardSetting (DWORD)
  • Value –  2

Web Bluetooth API - Registry Example

While you could easily add this to the registry manually like an animal, you could also choose to flex your PowerShell muscles and whip this problem out like a proper champ:

$Path = "HKLM:\\SOFTWARE\Policies\Google\Chrome"
$Type = "DWORD"
$Name = "DefaultWebBluetoothGuardSetting"
$Value = "2" # 2 = Disabled; 3 = Allow requests

# Create $Path if it doesn't exist
IF ( -Not (Test-Path -Path $Path) ) {
    New-Item -Path $Path -Force | Out-Null

# Create new DWORD with $Name and $Value
New-ItemProperty -Path $Path -PropertyType $Type -Name $Name -Value $Value -Force | Out-Null

Voila! Disabling Web Bluetooth API in Google Chrome was no problem thanks to Group Policy and PowerShell!

As a result, you should go grab yourself a delicious cookie and enjoy it.

Seems like you earned it.

PS: While it is awesome to use PowerShell, please please please use Group Policy where you can!

Create a Hipster Playlist Using PowerShell

Leave a commentPowerShell

Hipster playlist in Powershell

Hipster cred! I have it, you want it. No way to build it up faster than to be into something before it becomes popular. You may have been wondering how you might be able to pull a random list of fifteen infrequently listened to bands and document the fact that you knew of them before it became all about the money. Well lucky for you we have what you need.

Note: if you see a band in this list and object to their placement, you are functioning at a higher hipster level than this blog accounts for and can add that feather to your fedora.

Setting Up the Spotify API

Before this script will be able to run at all we will need to set up an API(Application Program Interface) at This will give us the client ID and let us set a redirect URI(Uniform Resource Identifier) for after we authenticate. Seen below is what this screen looks like after I use cutting edge blurring technology to hide my actual IDs.

hipster playlist uri spotify

With this created, you can now generate an access request. The request has to contain the following:

  • Client ID – Identification number generated by Spotify
  • Redirect URI – URI that the browser will go to after you authenticate.
  • Response Type – How you want the Spotify servers to respond to the request
  • Scope – Permissions you are requesting

Opening Your Spotify Hipster Playlist

Here is how our URI request looks. $clientID should be replaced with your client ID after you register your application with Spotify

$clientid = <Your Client ID Here>
$AuthUri = "" +
           "client_id=$clientid" +                                                                                     #Put the client ID from your web application here here
           "&redirect_uri=" +         #Thanks to Jonathan Lindgren ( for use of that awesome gif
           "&scope=playlist-modify-public playlist-modify-private playlist-read-private playlist-read-collaborative" +

If you copy the above URL into a web browser it will respond with your access token inside the address bar. We could manually copy that over like we are animals, or we can use PowerShell to build our own browser on the fly that will have the token we need in an object. Let’s check in with Kris to see how he might perform such a task.

Add-Type -AssemblyName System.Windows.Forms
$FormProperties = @{
    Size = New-Object System.Drawing.Size(850, 675)
    StartPosition = "CenterScreen"
$Form = New-Object System.Windows.Forms.Form -Property $FormProperties
$BrowserProperties = @{
    Dock = "Fill"
$Browser = New-Object System.Windows.Forms.WebBrowser -Property $BrowserProperties

Compelling stuff Kris, thanks for stopping by.

Running this will bring you to a login screen for Spotify. Once your credentials are in it will take you to some fantastic artwork by Jonathan Lindgren.

Feel free to bask in its glory, but to move forward with the script you will eventually have to close this browser.

Once you close that browser, your access token will be in $Browser.Url.Fragment. It will take a little work to clean up that data to make it usable. First, you need to use regular expressions to strip everything but the token value. Then, you need to specify the token type and create a header variable.

If ($Browser.url.Fragment -match "access_token=(.*)&token") {$AccessToken = $Matches[1]}

$BearerToken = "Bearer $AccessToken"
$HeaderValue = @{Authorization = $BearerToken}

Now the we have the token the rest of the script is just the same command over and over. Invoke-RestMethod is the PowerShell cmdlet that lets you send HTTPS requests against a web service.

Each time you run the command you specify where you are making the request (URI), what you are doing (method), what you are sending over (body), and your access token (header).

That is it. Just use different variations of that command and it will let you grab your account, build a playlist, grab every genre, and get the three least listened to bands for each one.

Now that we have all the steps lets take a look at the completed script.

### Create uri for generating access request ###

$AuthUri = "" +
            "client_id=$clientid" +                                                                                     #Put the client ID from your web application here here
            "&redirect_uri=" +         #Thanks to Jonathan Lindgren ( for use of that awesome gif
            "&scope=playlist-modify-public playlist-modify-private playlist-read-private playlist-read-collaborative" +

### Build Browser and request authentication ###

Add-Type -AssemblyName System.Windows.Forms
$FormProperties = @{
    Size = New-Object System.Drawing.Size(850, 675)
    StartPosition = "CenterScreen"

$Form = New-Object System.Windows.Forms.Form -Property $FormProperties
$BrowserProperties = @{
    Dock = "Fill"

$Browser = New-Object System.Windows.Forms.WebBrowser -Property $BrowserProperties


### Create access token variable and grab your user account information ###

If ($Browser.url.Fragment -match "access_token=(.*)&token") {$AccessToken = $Matches[1]}

$UserUri = ""
$BearerToken = "Bearer $AccessToken"
$HeaderValue = @{Authorization = $BearerToken}
$UserAccount = (Invoke-RestMethod -Uri $UserUri -Method Get -ContentType application\json -Headers $HeaderValue).href

### Build Playlist and get ID ###

$PlaylistUri = $UserAccount + "/playlists"
$NewPlaylist = @{
    name = "Before they are Popular"
    public = "true"
} | ConvertTo-Json

$PlaylistID = Invoke-RestMethod -Uri $PlaylistUri -Method Post -ContentType application/json -Headers $HeaderValue -Body $NewplayList

### Grab all genres seeds and select 5 random ones that have more than 10 bands associated with it ####

$GenreSeedUri = ""
$Genres = Invoke-RestMethod -Uri $GenreSeedUri -Headers $HeaderValue | Select-Object -ExpandProperty genres
$GenreList = @()
foreach($Genre in $Genres){
    $GenreUri = "$Genre&type=artist&limit=5&market=us"
    $BandCount = (Invoke-RestMethod -Uri $GenreUri -ContentType Application/json -Headers $HeaderValue)
    if($BandCount -gt 10){
        $GenreList += $Genre
    Write-Output "Generating list for: $Genre"
    Start-Sleep -Milliseconds 100

$FinalList = Get-Random -InputObject $GenreList -Count 5

### Grab 3 least popular band per genre ###

$Bands = @()
foreach($Item in $FinalList){
    $BandUri = "$($Item)&type=artist&type=artist&limit=5&market=us"
    $BandCount = [System.Math]::Round(((Invoke-RestMethod -Uri $BandUri -ContentType Application/json) - 3), 0)
    $OffsetUri = "$($Item)&type=artist&offset=$($BandCount)&limit=3&market=us"
    $LastThreeBands = (Invoke-RestMethod -Uri $OffsetUri -ContentType Application/json).artists.items | Select-Object name, id
    $Bands += $LastThreeBands

### Add top track from bands to playlist ###

Foreach($Band in $Bands){
    $TopTrackUri = "$($"
    $TopTrack = (Invoke-RestMethod -Uri $TopTrackUri -ContentType Application/json).tracks | Select-Object uri
    if($TopTrack -ne $null){
         $CombinedTopTrack = $TopTrack.uri -join ','
         $AddTrackUri = $UserAccount + "/playlists/" + $ + "/tracks?position=0&uris=$CombinedTopTrack"
         Invoke-RestMethod -Uri $AddTrackUri -Method Post -ContentType application/json -Headers $HeaderValue

### List the 5 Genres used ###

Write-Host "You have created a playlist from the following genres: $FinalList"

Final note, should you want to do something useful with these commands the format would be the same. Just know that I used these commands before they were cool.

Managing Changes to PDQ Deploy or Inventory with Git

4 CommentsPDQ Deploy, PDQ Inventory

Write-Host “Hello world!”

Hi there. I’m Colby Bouma, a shiny new employee at Admin Arsenal on the QA team. I used PDQ extensively at my previous job and I did some crazy things with it. Today I would like to share one of those crazy things with you. It’s important to know I tend to go a little over the top occasionally 😀

Have you ever wanted a detailed history of the changes you’ve made to PDQ Deploy and Inventory? You can accomplish this with the built in Export feature and your own git repository. The Export feature creates XML files which are fairly readable and work very well with git. If you follow my workflow of exporting and committing after every change you get some handy benefits:

  • Quickly find when a change was made
  • See exactly what changed
  • Keep notes on why you made a change
  • Create a sort of undo button by importing a snippet of XML

Setting Up Gitlab and Preparing Your Workstation

  1. Install and configure Gitlab.
    1. Create a virtual machine with at least 2GB RAM, 20GB HDD, and 1 CPU core. You can use your favorite Linux distro, but I chose Ubuntu 16.04 for this demo. I followed these instructions to install Gitlab.
      sudo apt-get install curl openssh-server ca-certificates postfix
      curl -sS | sudo bash
      sudo apt-get install gitlab-ce
    2. Follow this guide to configure email. This is required for creating accounts in Gitlab. Once you are done, run:
      sudo gitlab-ctl reconfigure
    3. You should now be able to log into your Gitlab webpage and change the root password.
    4. Create a user account for yourself. It’s never a good idea to run as root.
      gitlab admin area
      gitlab new user
  2. Create a repository.
    gitlab new project
  3. Install Git on your workstation. The defaults are fine.
  4. Clone the repository to your workstation.
    git clone http://lnxDEMO/colby/PDQ_Settings.git

    clone git repository
    clone repository black

  5. Create the initial export. In PDQ Deploy, go to File > Preferences > Export All.
    preferences export all
    xml preferences export
  6. Commit the initial export with the comment “Initial commit”.
    git add .\Deploy_Settings.xml
    git commit -m “Initial commit”

    initial commit

  7. Push the initial commit to Gitlab.
    git push -u origin master

    git credentials
    git push black
    repository pdq settings git

Workflow for Managing Changes to PDQ Deploy or Inventory

Perform an export after making any change. If you need to make multiple changes, do them one at a time and export after each change. This makes it much easier to look through and encourages detailed notes instead of “Huh, looks like I changed some stuff”.

  1. Perform an export and save over the previous file.
    export deploy settings
    confirm replace file git
  2. Commit all changed files:
    git commit -a

    git commit
    git commit 2

  3. Press “i” to enter INSERT mode.
    git editor press i
  4. Write a comment such as “Increase ‘Backups to Keep’ to 200”. I also like to make a note of the path to the item I have changed, such as “Database –> Backups to Keep”. The first line is a brief note to summarize the commit; everything below that can be as detailed as you want. Make sure to put a blank line after the first line if you are going to write detailed notes.
    Keep 200
  5. To save and close the comment hit the ESC key, type “:x”, and hit ENTER.
    Keep 200 x
  6. Synchronize with Gitlab:
    git push origin master

    (If you make multiple changes you can wait to do this step until you’re done.)
    git push origin
    backups to keep changes to pdq deploy

Undo Button

  1. Find the snippet of code you want to restore.
    restore code pdq deploy
  2. Copy and paste it into a text editor. In this example I had to rearrange it a little bit due to how the diff was formatted. For packages you want everything between <Package> and </Package>.
    Package code snip
  3. Save it as an XML file.
    activation status save
  4. Import it.
    import to pdq deploy
    import rebuilt package
    rebuilt package was successfully imported

PDQ Inventory 12 is Now Available

Leave a commentPDQ Inventory

PDQ Inventory 12 is now available to download. To upgrade the version, click the notice A new version is available in the status bar of the console. Here are all the new and exciting features that await you.

Custom Fields Import Wizard*

Are you currently using Inventory but have to maintain a separate spreadsheet to track those little items that Inventory does not gather? Perhaps you have to keep track of Asset Tag numbers, Employee numbers, or even the colors used on that one guy’s cool mechanical keyboard. Whatever the data, your days of separate tracking are about to come to an end. We bring to you the Custom Fields Import Wizard. This very handy tool allows you to import a large amount of custom data all at once from a CSV (comma-separated values) file.

To launch the Import Wizard, click File > Preferences > Custom Fields, then click Import Wizard (or on the Custom Fields page of the Computer window, click Import Wizard).

Select your CSV file and map the fields in the CSV file to any existing Custom Fields in PDQ Inventory or create brand new fields within the wizard. You can also import and overwrite data whenever you update the CSV file.

Tool Details in the Tools Library

The Tools Library now includes a Tool Details sidebar that displays the description, any applicable keyboard shortcuts, required software, and category. This is available to all license types; however, Enterprise mode is required to import tools.

Heartbeat Trigger for Scan Profiles*

We’ve added the ability for PDQ Inventory to start a scan whenever a computer goes from offline to online status so you can always have the most recent data. If the computer registers as offline and online within the Heartbeat interval (default 300 seconds), the computer will not register as offline by the Heartbeat and a scan will not be initiated. This is set up on the Triggers tab of the Scan Profile window found in File > Preferences > Scan Profiles. Open an existing Scan Profile or click New to create a new profile.

New actions available for Files and Registry pages*

The Files and Registry pages of the Computer window have more flexibility than before. Have you ever scanned for file or registry entries and had the results return far too many line items? Or have you changed a scan profile, but the results are still showing? You can now delete individual entries without having to repeat the process of editing your scan profile and scanning the computer again.

Additionally, opening File Explorer to the exact location of a file is now just a right-click away using the context menu.

More data collected during a scan

  • Current User (User UPN Name), Display Name (AD User Display Names), and Deep Freeze Status* have all been added to the Computer page of the Computer window as well as Collections and Reports.
  • Added From, Deep Freeze Product Code*, and Deep Freeze Version* have all been added to Collections and Reports.
  • SMART Status* has been added to the Disk Drives page of the Computer window as well as Collections and Reports.

Other smaller (but no less important) additions

  • The Computer window of a selected computer can be opened directly from within the Remote Command window using the context menu.
  • The Main Console Toolbar is now arranged more conveniently by task.

*Requires Pro or Enterprise mode

How to Disable Flash on Your Network

Leave a commentDeployment Examples, PDQ Deploy

In this post, we’ll go over how to disable Flash on IE, Firefox, and Chrome. The video below is the complete recorded webcast in which we cover each browser. In each section, a link is provided that will go to that portion of the webcast or you can watch the webcast in its entirety below.

Is Flash all that bad? Maybe, maybe not. Adobe Flash is a necessary evil for some organizations…a lot of schools often need Flash to run certain educational programs. The objective is to minimize your possible security risks (AKA minimizing your attack surface). If you don’t need Adobe Flash in your environment, disable it. If you need it, get it and make sure you keep it up to date. For your consideration, what would happen in a month without Adobe Flash?

How to Uninstall Flash in Firefox

In the Package Library, there is a deployment package available that will uninstall Adobe Flash (requires an Enterprise license). It will only uninstall the Flash as made available by Adobe. It will not uninstall or disable Flash built into IE (for Windows 8 and higher) or the embedded PPAPI Flash in Chrome. Watch how to uninstall Adobe Flash for Firefox.

Disable Flash in Google Chrome

There are two steps to disabling Flash in Chrome. First there is the embedded Pepper Flash (PPAPI). Straight up, the best and surefire way to make sure the embedded Flash is disabled in Chrome is through a GPO. In order to use this method you need to import the Google ADMX files into your Group Policy environment. You can download the latest ADMX files here. In a new or existing GPO you can configure the new policy. With the example below we have a dedicated GPO called Component Update Disabled.

GPO how to disable flash in chrome

In Settings > Administrative Templates > Google/Google Chrome you’ll be able to see what policies you have enabled or disabled. Right-click on your GPO (on the left pane) and select Edit. With the ADMX template loaded, you’ll have the option to go to Computer Configurations > Policies > Administrative Templates > Google > Google Chrome. From there you can find the setting called Enables component updates in Google Chrome. Which you can then set to disabled. If you do not explicitly set this policy to Disabled then any computers that can access the internet will automatically have the latest embedded Pepper Flash installed.

If you are using Chrome make sure you don’t have the Adobe Flash Player PPAPI installed. This is important because even if you disable the Enables Component Updates in Google Chrome setting Chrome will use the installed Adobe Flash Player PPAPI if it is installed. You can deploy the Uninstall Adobe Flash Player package from PDQ Deploy’s Package Library to uninstall this application.
edit gpo flash google chrome

If you would prefer to not use a GPO to disable the embedded Flash for Chrome you can use PDQ Deploy to push out a specific registry value to your target computers. Below is a download for a package you can use in PDQ Deploy to deploy this policy’s registry changes. Also below is an accompanying Collection you can import into PDQ Inventory to help you track computers with Flash disabled.

Package – Disable Flash in Chrome

Collections – Flash Disabled

Watch the video on how to disable Flash in Chrome here.

Disable Flash in IE

Every KB that comes out from Microsoft for Flash has a workaround for disabling Flash. Again, GPO is probably the best way to accomplish this, check out this blog post on how to disable Flash in IE using GPO.

We also have a deployment package you can push out here. Make things easy on yourself and deploy to the right computers and use the Collections provided here to track computers that have Flash disabled.

Why disable Flash? Shouldn’t uninstalling it do the same thing?

In some cases you will want to uninstall it. Other situations, however, uninstalling really isn’t an option so you are left with disabling it. Below is a chart showing which OS/browser combinations you can uninstall vs. disable. If uninstalling is an option, you can use the deployment package available that will uninstall Adobe Flash available in PDQ Deploy.

OS Browser Disable/Uninstall
Windows XP to Windows 7 IE Uninstall
Windows 8.1-10 IE Disable
All Firefox Uninstall
All Chrome Disable AND Uninstall
All Opera Uninstall

Deploy Adobe Creative Cloud Using Setup.exe

Leave a commentDeployment Examples, PDQ Deploy

You’re looking to deploy Adobe Creative Cloud using setup.exe, rather than the MSI. For instructions on using the MSI, check out this blog post. This post will show you how to configure the Creative Cloud Packager and then successfully install the selected Adobe CC products. Be sure to check out the tips for troubleshooting silent installations of Creative Cloud at the bottom of this post.

Configuring the Creative Cloud Packager

1. Download the Creative Cloud Packager by logging in to and selecting the appropriate management link. In the management window, select Deployment Tools then select the Download Win > package.

2. This will download the CCPLauncher.exe. Launch the executable.
3. Click on Create Package.

4. Give the package a name, a location where the package should be saved, the architecture (32 or 64-bit) of the applications, the license type, and any special configuration options (mostly update preferences).


5. Click Next.
6. Select the applications and/or updates you wish to build into your installer.

NOTE: As indicated in the image above, for multilingual offices you can also select the Match OS Language, which will install the applications based on OS locale. This negates needing to create multiple packages in specific languages.adobe creative cloud packages

7. Once you’ve made the appropriate application and/or update selections, click Build. And wait. And wait some more. Go to lunch. Wait. Deploy some other things. Wait. Inventory the satellite office in Boca Raton with their 3,478 USB printers. Wait.

You should now have a directory containing an MSI installer and a setup.exe for the Creative Cloud products in the ..\DownloadDirectory\Build\.

setup.exe for adobe creative cloud
Deploy Adobe Creative Cloud Using Setup.exe

In the following example, we are only deploying the 64-bit version, but it is possible to create a 32 and a 64-bit installation. For information on how to do this, see the original KB.

1. In PDQ Deploy, click New Package or Ctrl+N from the toolbar or click on File > New Package or right-click the Packages folder in the navigation tree and select New Package.
2. Name the package something reasonable, and choose the appropriate Copy Mode (see Considerations below) if not already set globally (Pull Copy Mode should be default in your global settings if you have followed the recommendations at the bottom of this article).

Deploy Adobe Creative Cloud Using Setup
3. Click on New Step > Install, and give the step a title. For the Install File, navigate to the directory containing the setup.exe you created above.


  • The setup.exe has a silent parameter, –silent. This must be used when deploying the setup.exe. The full usage statement for setup executable is:
setup [--silent] [--ADOBEINSTALLDIR=<TargetInstallDirPath>] [--INSTALLLANGUAGE=<ProductInstallLanguage>] [{-h, -help, --help}]
  • Make sure to check Include Entire Directory. If this is not checked, the deployment will fail.

silent install parameter for adobe creative cloud
4. Click on the Conditions tab and select the O/S Version. Since Adobe Creative Cloud products will only run on Windows 7 and above, exclude XP and Vista. Exclude servers unless required. Since this package is installing the 64-bit Creative Cloud applications, select 64-bit from Architecture.

architecture type for adobe cc
5. Save the package.
6. Deploy and enjoy.

IMPORTANT: While we make every effort to test on multiple platforms and architectures, it is highly recommended you test the deployment before a general release into production. Given the possibility of the package being substantially sized, testing will provide important information on bandwidth limitations and deployment times. In our tests, an install consisting of Adobe Acrobat, Photoshop, and Dreamweaver took anywhere from 6 – 20 minutes to deploy.


  • In order to download the Creative Cloud Packager from Adobe, you will need to be an administrator of an Adobe Creative Cloud account.
  • You cannot deploy using Creative Cloud for Individuals (requires Team, Enterprise, or Education Creative Cloud plans).
  • While the deployment method outlined in this article can be accomplished using PDQ Deploy in free mode, changes will need to be made to create separate deployments based, for example, on OS architecture


  • The guidance in this article is focused on Creative Cloud for Teams. The steps for Creative Cloud for Enterprise and Education vary, but should be intuitive enough to allow successful deployment given the general instruction expressed in this article.
  • Since the size of a Creative Cloud package can be significant, it is recommended you use the Pull copy mode instead of the default Push copy mode (File > Preferences > Performance). This will also require placing the Repository on an accessible file share. For more information, see: PDQ Deploy: Understanding Push and Pull Deployments
  • For the greatest level of performance where multiple file servers exist and the deployment audience is greater than 30 machines, the use of Distributed File System Replication (DFSR) is highly recommended. For more information, see: PDQ Deploy and Microsoft DFS.
  • If users do not have local admin access on their respective machines and therefore do not have access to the Creative Cloud App Panel, the Creative Cloud Package can also be used to push out updates to machines with installed Creative Cloud products.

Troubleshooting Your Deployment

If the package deployment fails and/or you receive a 1603 error, please try the following.

  • Machines should be fully patched and not in need of a reboot.
  • Check to ensure sufficient space is available on the drive where Adobe CC will be installed. Some Creative Cloud deployments can be several gigabytes in size, which includes the files copied to the target and the installed size.
  • Clear out %WINDIR%\Temp directory.
  • Review the troubleshooting steps in This Article.

Error: “Setup.exe returned error code N”:
Adobe has a great Creative Cloud Troubleshooting Guide. There should be a log file on the target machine called PDApp.log, usually in C:\Windows\Temp. At the end of the log or near the end, there should be an error code. That error code can then be used to diagnose the particular issue. For example, PDQ Deploy reports, “setup.exe returned error code 4”. Reviewing the log file shows, “The Bootstrapper Process return code is (82).Stopping the installation process.” Reviewing the Troubleshooting Guide, error 82 is caused by AAM running and can be solved by closing all Adobe processes and/or renaming the PDApp folder.

Error: “Setup.exe returned error code 6”:
Usually the programs will have installed, but the error will still be thrown and the deployment will show as failed. There can be a few causes for the error code 6, which are outlined here as well as in the Troubleshooting Guide. This can also be caused by insufficient disk space or any number of other environmental conditions.

How to Remove AppX Packages

5 CommentsPDQ Deploy, PowerShell

A common request we have is how to remove AppX packages, or in other words, remove Windows 10 default applications. First, you’ll see how to write and deploy a script to remove the applications, then we’ll look at an option for removing the application for all users on a workstation.

Building the Script to Remove Appx Packages

To successfully remove AppX packages you’ll need two separate PowerShell scripts: one to remove the application(s) and one to prevent it from installing when a new user logs onto the desktop.

Remove Windows 10 Default Applications

To remove the existing software you need to decide which apps you would like to remove first. You can remove a single package with a one line script.

Get-AppxPackage |where {$_packagefullname -like "*zune*"} | Remove-AppxPackage

If, however, there is an entire list you would like it becomes a little more involved, you will need to create an array for each application you want to remove. For example:

$appname = @(

ForEach($app in $appname){
Get-AppxPackage -Name $app | Remove-AppxPackage -ErrorAction SilentlyContinue

You can add however many apps you like to the array and this script will cycle through and remove them. To get a full list of software you can remove you can run the following script on a Windows 10 machine:

Get-AppxPackage -AllUsers | select PackageFullName

Preventing Applications from Installing for New Users

The process for preventing the software from installing in the future is very similar. The only difference in the command is “provisioned” is added to the command name (Get-AppxProvisionedPackage). Here is how you get the list:

Get-AppxProvisionedPackage -online | select PackageName

And then to remove them from the preinstall list use the following script:

$appname = @(

ForEach($app in $appname){
Get-AppxProvisionedPackage -Online | where {$_.PackageName -like $app} | Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue


Running the PowerShell Script Remotely

Now that we have the script we want we need to deploy it to the machines that you want to remove AppX packages from. This is where it starts to get tricky, if you create a package and run it with the default settings it will look like it did not do anything. The reason is the remove command does not have any ability to specify a specific user, so if you run it as the deploy user it will try and uninstall that software for the deploy user on that machine.

If you are in a work environment has one computer per user you can run this as the logged on user and it will work as you are hoping as long as the users are logged in at that time.


For the AppxProvisionedPackage you can create the package with the defaults and it will still work as it is machine based and not user based.

Why These Scripts Do Not Remove Apps For Every User

If you have reached this point, you have been looking at this for awhile and you have found a lot of examples that say (incorrectly) if you run this command, then it will remove for every user:

Get-AppxPackage -AllUsers | Remove-AppxPackage

If you run it you’ll see nothing actually is removed. The reason has to do with the information that pipes over between the two commands. The first command (Get-AppxPackage) has an attribute (-AllUsers) that will look at each user on the computer, while the second command (Remove-AppxPackage) does not. That command while it does find packages for every user, it only passes over the name of the package, therefore it will only attempt to remove the package for the user running the script.

Alternative Solution

The challenge everyone runs into it is how do we remove AppX packages from all users that have logged into the machine previously without having to catch them while they are logged in. If all of your end users are local admins the very quick answer is add the PowerShell script as a logon script in Group Policy. If they are not local admins it takes a little work, but you can do it with PDQ Deploy.

Step 1: Build the PowerShell script. At the bottom I added two lines that will delete the script and batch file once the process is complete.

$appname = @(

ForEach($app in $appname){
    Get-AppxPackage -Name $app | Remove-AppxPackage -ErrorAction SilentlyContinue

Remove-Item -Path "$env:USERPROFILE\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\startup\test.bat"  -Force
Remove-Item -Path "$env:USERPROFILE\AppData\local\removeappxpackages.ps1"  -Force

Step 2: Create batch file to start the new script and run it all silently

@echo off
start Powershell.exe -executionpolicy remotesigned -windowstyle hidden -File  %userprofile%\AppData\Local\removeappxpackages.ps1 /min

Step 3: Create a new package in PDQ Deploy with a PowerShell step (get a free Enterprise trial here) that will copy the PowerShell script and batch file into each user profile that has had an interactive login.

$users = Get-ChildItem -Path "C:\Users"

foreach($user in $users){
  $path = "C:\Users\$($\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"
    if(test-path $path){
        Copy-Item -Path test.bat -Destination "$path\test.bat" -Force -ErrorAction Silentlycontinue
        Copy-Item -Path removeappxpackages.ps1 -Destination "C:\Users\$($\AppData\Local\" -Force -ErrorAction Silentlycontinue

Step 4: Add the files you created into the package.

addfiles Remove AppX Packages

Running this will make it so any user that has logged into a machine will have these applications removed the next time that they logon. They will not see anything and it removes them in under a minute. Running the remove-appxprovisionedpackage script from earlier will prevent it from installing these applications for all new users so you don’t have to run this script again.

Track Anti-Virus Software Versions with PDQ Inventory

Leave a commentPDQ Inventory, Scanning

PDQ Inventory is especially useful for keeping tabs on application information. Building dynamic collections in PDQ Inventory can answer questions like: “Are all of our devices up to date?” and “Which devices are most vulnerable right now?”. For some examples, we will use PDQ Inventory to find computers that have multiple anti-spyware applications installed and, of course, which computers have our preferred anti-spyware installed. In this example, we will use WebRoot SecureAnywhere as the preferred application.

Start by making two basic dynamic collections:

  1. A collection for your organization’s preferred anti-virus software
  2. A collection for devices with potentially unwanted anti-virus software.

The latter is important to track because no user is perfect—a hasty “whatever, just click install” mindset usually results in unwanted applications getting installed somewhere along the line. Having multiple anti-spyware applications on a single device can cause conflicts that can even result in BSODs and disabled anti-virus protection—something no admin, or even end user, wants to see.

Finding Unwanted Anti-Virus Installations

Set up an unwanted anti-virus collection to catch big-name applications that your organization does not use—just use the Any filter as shown below. It will help to add a few basic keywords to catch lesser-known or junk applications that might slip through. Experiment with application name/publisher values until you’ve covered all the bases, then uninstall unwanted applications at will!

Track Anti-Virus Software Versions

Having good anti-virus software only goes so far in keeping your organization’s devices safe. Mismanaged or undermanaged anti-virus software is a security risk. PDQ Inventory makes it easy to track anti-virus software versions and to identify devices with out-of-date protection or other software problems.

Handling Mismatched Anti-Virus Version Counts

Sometimes, the numbers of out-of-date and up-to-date versions will not match up to the number of devices in the parent collection. For example, you might have 200 devices in the parent collection, but 175 show up with the current software version and 50 show up with older versions. Mismatched version counts could result from an updated version failing to uninstall previous versions. This would cause two or more versions show up on one device. Multiple installed versions might be something to handle on a case-by-case basis via remote uninstall commands in PDQ Inventory or with a custom uninstall package in PDQ Deploy.
There are a lot of old versions reported in the group of collections below, due in part to mismatched version counts. Old versions are especially likely to show up in larger numbers for cloud-based anti-virus applications. If the version number from cloud-based software looks like it’s severely out of date, it may just be the version number of the agent installed, not the actual update protecting the device.


In this case, the endpoint device can be checked to verify that it is receiving updates from the cloud. Below is how the agent version from PDQ Inventory/Programs List could differ from the cloud-based update protecting a device.

AA-WRSAEndpoint (1)

Collections for different versions are simple to make, though, especially when you put variables to use.

Maintaining Software Versions in Collections

Variables help you easily change up-to-date and out-of-date version numbers. The benefit of variables is you can change them all in one place, rather than have to edit multiple collections. I set several variables to separate the previous version from all other older versions to separate devices that failed to update once from devices that failed to update several times. Name your variables and set appropriate values, then use them in dynamic collections.



Once your collections are built and you’re confident that they’re accurate, it’s time to put them to good use. Use PDQ Deploy to build a package with the most recent version of the anti-virus software your organization uses, then deploy it to the most vulnerable (out-of-date) targets. When new versions of anti-virus software are released, all you need to do is update the variables you set in Preferences. Your dynamic collections will then reflect the changes.

Once your out-of-date anti-virus pile is down to zero, treat yourself to a little dance and then make sure other applications and plugins that affect security are up to date!


Disclaimer: For demonstration purposes, cloud-based software was treated as hosted/on-premise software. Keep in mind that the nature of your anti-virus software (cloud-based or hosted/on-premise) can affect how the software’s version information shows up in PDQ Inventory.

See What’s New in PDQ Deploy 12

3 CommentsPDQ Deploy

PDQ Deploy 12 is now available. To update your console, click the “A new version is available” notice in the status bar of your console. If the update link is not visible, go to File > Preferences > Alerts to enable update notices.

New in the PDQ Deploy 12 Release

Use PDQ Inventory Scan User Credentials in PDQ Deploy

Use the scan user credentials from PDQ Inventory (in Enterprise mode) for your deployment credentials in PDQ Deploy. In previous versions of PDQ Deploy you were limited to using one set of credentials for all target computers per deployment. This meant that computers that required different Deploy User credentials had to be broken down into different deployments. That all changes in PDQ Deploy 12. This new feature requires you to have PDQ Inventory 11.2 or higher and PDQ Deploy 12 both in Enterprise mode. When you create or schedule a deployment, under the options tab you can select to use the PDQ Inventory scan user credentials first, if available. If the target does not exist in PDQ Inventory, the default PDQ Deploy credentials will be used instead.

Wake-on-LAN/Ping Settings Are More Versatile

The Offline Settings have, historically, been global. We have now made it so you can modify your Offline Settings at the Package and Deployment / Schedule levels. In addition to your current global settings (found in File > Preferences > Deployments), you can now ping targets or send Wake-on-LAN (WOL) per package, Auto Deployment package, schedule, or deployment. For example you could have your global settings to only deploy to computers that are online (PDQ Deploy pings the targets and only deploys to the computers that respond) but change a particular deployment to override that setting and attempt to use WOL (Wake-ON-LAN) for the offline computers.

To ping a target or send a WOL per package (including Auto Deployment package):

Package > Properties > Offline Settings


To ping a target or send a WOL for a schedule:

Schedule > Offline Settings



Some Improvements…

Post Schedule Notifications

If you are already a fan of using Post Deployment Notifications, you will enjoy this addition. You can now set Post Schedule Notifications to send only one email upon deployment completion of the entire schedule rather than multiple emails when using a Post Deployment Notification. You also have more options for customizing your emails and can now use variables in the subject line and email body. Set up a Post Schedule Notification very similarly to a Post Deployment Notification in File > Preferences > Mail Server.

You can add additional custom variables to use in notification emails (and other areas in PDQ Deploy) in File > Preferences > Variables.


Nested Package Run As Options

When adding a nested package, you can now select to use the Run As option of the nested package. You can change this setting by selecting the nested step and going to the Options tab.