Tutorial: MDT Imaging in PDQ Deploy

Follow

Comments

10 comments

  • Phil Adler

    How would you do this with the invoke-command in powershell. Psexec is nice but I would rather not store credentials in plain text

    0
    Comment actions Permalink
  • Allison Maheu

    Hey Phil,

    There are a few extra steps to use Invoke-Command instead of PSExec. I do want to note that this tweak is explicitly not supported, may break or change functionality in future versions, etc.

    First, you'll need to create a registry key to tell the Deploy background service to listen for TCP requests.

    Location: HKEY_LOCAL_MACHINE\SOFTWARE\Admin Arsenal\PDQ Deploy
    Key Type: REG_DWORD
    Key Name: ServicePort
    Value: Choose a port that is not currently in use. This will vary depending on your environment.

    Once you've created it, restart the PDQ Deploy service.

    Second, you'll need to change the script to reflect Invoke-Command instead of PSExec.
    The block should end up looking something like this (I'll be cleaning up my script as well in the near future):

    netsh advfirewall set allprofiles state off
    ipconfig /registerdns

    $package = "PACKAGE NAME HERE"
    $target = $env:COMPUTERNAME
    $pdqserver = "PDQ SERVER FQDN HERE"

    Invoke-Command -ComputerName $pdqserver -ScriptBlock { ipconfig /flushdns; pdqdeploy.exe Deploy -Package "$($Using:package)" -Targets "$($Using:target)" }
    while(test-path "C:\Windows\AdminArsenal\PDQDeployRunner\service-1.lock"){
    start-sleep 30
    }

    Lastly, you'll need to ensure that PS Remoting is enabled and configured properly on your PDQ Deploy server. This is going to vary based on your environment, so I'll just refer you to Microsoft's documentation for reference:
    https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/enable-psremoting?view=powershell-5.1

    Good luck and happy deploying!
    -Jake

    0
    Comment actions Permalink
  • Phil Adler

    Thanks, where do I need to reference the port number in the script? I am using a central server so I should create the registry key on the central server or add a step in the deployment 

    0
    Comment actions Permalink
  • Allison Maheu

    Hey Phil,

    You shouldn't need to reference the port number in the script. You'll configure it on the central server so that the Deploy service will be able to listen for the input coming from Invoke-Command.

    -Jake

    0
    Comment actions Permalink
  • Jason Lester

    Jake,

    I've been testing it out today with our MDT sequence.  It works and pulls down all the packages fine other than the IE Flash packages, Those return an error, I suppose because they are MSUs?  However, the output lines from the psexec commands are interpreted by MDT as errors, so you get the yellow screen at the end of the task with 12 errors (one for each output line from psexec.)  Any ideas how to get that suppressed?

    0
    Comment actions Permalink
  • Allison Maheu

    Hey Jason!

    I agree that it's probably because they're MSUs. MDT gets cranky when you do things outside of when it thinks they should be done, like using wusa.exe when it's not Windows Update time.

    What I would recommend as a workaround is to set up a scheduled deployment linked to the IE Flash package, targeting the "Flash IE (Not Installed)" dynamic collection in PDQ Inventory, using a heartbeat trigger. Once the machine comes back online the first time, Inventory should see that new machine and deploy Flash accordingly.

    In theory, you could also import a copy of the MSU and add it into MDT proper, though this is a bit more work and would require targeting for each version of the MSU you might need to install. For more info on this approach: https://systemcenterguru.wordpress.com/2013/12/18/install-windows-hotfixes-msu-during-os-deployment-using-mdtsccm2012/ 

    I hope this gets you on the right track.

    -Jake

    0
    Comment actions Permalink
  • Jason Lester

    Thanks, we already have a heartbeat trigger setup to get what is missing later.  So, I think we're good there.

    What about the errors from the psexec output?  I'm trying again right now with those lines in the script having 2>&1 on the end.  I'm hoping that causes MDT to not see the output lines from psexec which it seems to interpret as errors.

    Jason

    0
    Comment actions Permalink
  • Allison Maheu

    Hey Jason,

    Could you paste the errors that you're seeing? If I remember correctly, psexec shouldn't return errors if it's managing to start the deployment at all (even if the package itself fails). 

    You can also open up a ticket if you'd like to take this to a more private venue. :)

    -Jake

    0
    Comment actions Permalink
  • Jason Lester

    It's not that it's returning errors, it's the output from psexec running the commands.  I guess it outputs what command it is running on the remote system to the console, then the exit code.  MDT seems to be picking those up as errors, even thought it was successful.

    Adding the 2>&1 fixed it.  Everything deployed successfully that time.  Thanks for the info, this will save me from having to update our standard apps in both MDT and PDQ now.

    0
    Comment actions Permalink
  • Erin

    Hi all, funnily enough i posted this in reddit just last week as my solution. I have changed it to use IP instead of DNS Name as in a WAN environment the DNS wasnt as reliable as i'd liked.

    I've added some waits and timeouts so the script will wait for the lockfile to appear, but also timeout after 60 minutes if it never starts.

    I deal with turning the firewall off/on in mdt so i could have multiple PDQ deployment steps between those. The 3 steps I use are:

    Turn off - c:\windows\system32\netsh.exe advfirewall set allprofiles state off

    Put PDQ Step in between and run as an account with PDQ access - powershell.exe -executionpolicy bypass \\Powershell path\PDQ-Deploy-MDT-WithIP.ps1 -package 'NameOfPDQPackageorBundle'

    Turn back on - c:\windows\system32\netsh.exe advfirewall set allprofiles state on

    Hope this can help someone refine their process. 

     

    I have the piece using the original computername also in there remmed out .

    Begin script below dotted line PDQ-Deploy-MDT-WithIP.ps1

    -----------------------------------------------------------------

     

    # Declare the parameter for package name so we can pass the package name on the command line
    param (
    [Parameter(Mandatory=$true)][string]$package
    )

    # Find the ip address from the computername
    $ipV4 = Test-Connection -Computername "$env:COMPUTERNAME" -count 1 |Select -ExpandProperty IPV4Address

    # Run the deployment command using ip address as the target
    Invoke-Command -ComputerName <PDQSERVERNAME> -ScriptBlock { param ($compname) & 'C:\Program Files (x86)\Admin Arsenal\PDQ Deploy\pdqdeploy.exe' Deploy -Package $Using:package -Targets $Using:ipV4.IPAddressToString} -ArgumentList "$env:COMPUTERNAME"

    # Run the deployment command using computername address as the target
    #Invoke-Command -ComputerName <PDQSERVERNAME> -ScriptBlock { param ($compname) & 'C:\Program Files (x86)\Admin Arsenal\PDQ Deploy\pdqdeploy.exe' Deploy -Package $Using:package -Targets $compname} #-ArgumentList "$env:COMPUTERNAME"


    #Add a timeout so if the deployment doesn't start it continues after 60 minutes
    $timeout= new-timespan -Minutes 60
    $StopWatch = [diagnostics.stopwatch]::StartNew()

    #wait for the package to start by waiting for the lock file to appear
    $LockfileExist=$false
    Do{
    If(Test-Path 'c:\windows\AdminArsenal\PDQDeployRunner\service-1.lock') {$LockfileExist = $true} Else {Write-Host 'Waiting PDQ install to start on ' $env:COMPUTERNAME - $ipV4.IPAddressToString ; Start-Sleep -s 10}
    }
    Until (($LockfileExist) -or ($StopWatch.elapsed -ge $timeout))

     

    #Check if the package is still running by looking for the lock file to disappear
    $fileDeleted=$false
    Do{

    If(Test-Path 'c:\windows\AdminArsenal\PDQDeployRunner\service-1.lock') {Write-Host 'PDQ install started: waiting to complete on ' $env:COMPUTERNAME - $ipV4.IPAddressToString; Start-Sleep -s 10} Else {$fileDeleted = $true}
    }
    Until ($fileDeleted)

    1
    Comment actions Permalink

Please sign in to leave a comment.