The Microsoft Deployment Toolkit, or MDT, is an incredibly flexible, extensible, and powerful utility in the hands of any sysadmin. As times change and best practices mature, we’ve seen a shift from traditional “golden” images (with applications, settings, etc. all baked in) to thin images, easily updated and dynamically provisioned during the imaging process itself. However, outside of PDQ, with great power often comes great complexity. Using MDT Imaging in PDQ Deploy can streamline the process of installing applications during the imaging process. You can simply queue a PDQ deployment from inside MDT!
Get started using MDT Imaging in PDQ Deploy
There are a few schools of thought on how you should deploy applications to a newly-imaged computer. The simplest way, which requires no MDT changes, is from within PDQ Inventory and Deploy.
Create new or use existing, dynamic collections that contain machines missing the applications you want to be installed. PDQ Inventory’s Collection Library has many dynamic collections for workstations missing applications. For example:
You can use a heartbeat trigger to create a schedule in PDQ Deploy linked to the appropriate collection and Auto-Download package.
That’s it. When PDQ Inventory sees those machines come online, it’ll queue the deployments as necessary.
This is a totally acceptable and very common way to deploy applications in an environment (especially things like Java and Adobe Reader updates), but there are also many cases where you want a freshly-imaged machine to be ready to go as soon as the task sequence completes. With applications like the Microsoft Office suit, you’ll also want to ensure all the latest Windows Updates are applied.
Better Living Through PowerShell
You can use a PowerShell script in conjunction with MDT to trigger a PDQ deployment targeting the machine MDT is imaging for those cases where you want to have newly-imaged machines ready to distribute to your users.
As an example: When I set this up, I put a custom task between the Pre- and Post-Application Install Windows Update steps of my task sequence. This allows the first run of updates (cumulative updates, framework patches, etc.) to process before installing your desired suite of applications. A second update run catches anything that is missed on the first go or that is newly required as a result of those installations.
There are two main methods of kicking off the deployment inside MDT. One uses the utility PsExec, and the other uses PowerShell’s Invoke-Command cmdlet. Both options accomplish the same end result, however, depending on your environment, one may be preferred over the other.
Option 1 – PSExec
PsExec is an extremely powerful and handy utility for any sysadmin.
From Microsoft’s documentation: “PsExec is a light-weight telnet-replacement that lets you execute processes on other systems, complete with full interactivity for console applications, without having to manually install client software.”
Things to note:
PsExec is not included with Windows by default. You can use a command step in MDT to copy PsExec onto the machine being imaged from your MDT share like so:
xcopy "%SCRIPTROOT%\PsExec.exe" "C:\WINDOWS" /Q /H /E /I /Y
MDT runs commands in the context of whatever credentials you feed it (either in CustomSettings.ini or manually at the beginning of the task sequence). You can also change the setting for the PowerShell step to “Run this step as the following account.”
Whatever account you use will need to be a Console User in PDQ Deploy. Your deployment will fail without this.
Learn more about the test-path and start-sleep commands
The script:
netsh advfirewall set allprofiles state off
ipconfig /registerdns
psexec.exe \\pdq.host.fqdn -h -accepteula ipconfig /flushdns
psexec.exe \\pdq.host.fqdn -h -accepteula pdqdeploy.exe Deploy -Package "New PC Setup" -Targets $env:COMPUTERNAME
Start-Sleep 30
while (Test-Path "C:\Windows\AdminArsenal\PDQDeployRunner\service-1.lock") {
Start-Sleep 30
}
How this works:
Temporarily disables the firewall on the machine. Reset the group policy settings after a reboot.
Re-registers the machine in DNS (See more about ipconfig /registerdns). PDQ software is highly dependent on a healthy, up-to-date DNS.
Flushes the DNS cache on the PDQ server to ensure it reflects the correct IP > Hostname mapping for the machine being imaged.
Initiates a CLI deployment of “New PC Setup” targeting the hostname of the machine being imaged. Replace the package name with whatever package you want to deploy. Nested packages are great here.
Wait. We want PDQ Deploy to have time to actually start the deployment, especially if you do a lot of deployments and it might end up in the queue.
Wait more. Now we’re watching service-n.lock, which is a file generated by the PDQ Deploy runner service. As long as that file exists, the PDQ deployment is ongoing and MDT will not progress to the next step in your task sequence. PDQ Deploy is done once it’s gone. We can move onto the next step in the MDT task sequence!
Option 2 – Invoke-Command
Invoke-Command is a stock cmdlet starting with PowerShell 3.0 and onward. From Microsoft: “The Invoke-Command cmdlet runs commands on a local or remote computer and returns all output from the commands, including errors.”
Things to note:
PDQ Deploy must be running in Central Server mode.
Create a registry key on your PDQ Deploy server to make the background service use TCP instead of Named Pipes:
Location: HKEY_LOCAL_MACHINE\SOFTWARE\Admin Arsenal\PDQ Deploy
Value: ServicePort (DWORD value)
Set the ServicePort value to a port number you’d like to use (outside of the well-known port range, and not 6336 or 7337), then restart the background service.
Depending on your environment: Configure the firewall on your PDQ Deploy server to allow connections on that port.
As with PsExec, this will run in the context of your MDT user, ensure that the user is set up as a Console User in PDQ Deploy.
Because the cmdlet returns all command output, including errors, you’ll need to add some redirection so that MDT doesn’t think something is wrong.
The script:
netsh advfirewall set allprofiles state off
ipconfig /registerdns
Invoke-Command -ComputerName pdq.host.fqdn -ScriptBlock {
ipconfig /flushdns
pdqdeploy.exe Deploy -Package "New PC Setup" -Targets $args[0]
} -Args $env:COMPUTERNAME 2>&1
Start-Sleep 30
while (Test-Path "C:\Windows\AdminArsenal\PDQDeployRunner\service-1.lock") {
Start-Sleep 30
}
This one works in a similar fashion to the PsExec version. By passing $env:COMPUTERNAME as an argument, we refer to it inline as $args[0], as it’s the first object in that array. We redirect the output using 2>&1 because MDT assumes that no news is good news, and also assumes the inverse.
Wrapping It Up
MDT is an extremely versatile tool that can be made even better with the power of PDQ Deploy. By using this functionality, you can increase the efficiency of your imaging process, leaving you with more time for the fun things in life, like fixing your mangled DNS servers and drinking! If you’re looking for more information on the subject, you can also refer to the PDQ YouTube channel.