Wednesday, March 13, 2013

Start MDT Litetouch Task Sequence remotely (psexec.exe revisited)

Recalling my blog of February 23 i used a PowerShell script to start a deployment of a MDT Litetouch task sequence remotely via the use of psexec.exe.

Addition sept13 2013: a GUI to wake machines is published here

image
This script pushes the litetouch.vbs script to the client using psexec.exe, as shown here.
Now after a few weeks i have had many tests with this script and i can tell you; it works! there are a few buts though!
Let’s look at the first version of the script:

$ErrorActionPreference = "SilentlyContinue"
Do {
Clear-Host
Do {
$trgMachine = Read-Host("Give the machinename that has to receive a LiteTouch deployment (Netbios or DNS name are equally good)")
      If($trgMachine -eq ""){Write-Host "Please give a name"}
}While($trgMachine -eq "")
      psexec.exe -i \\$trgMachine -h -u DOMAIN\User -p Userpassword cscript.exe //B "\\MDTServer\Deploymentshare$\Scripts\litetouch.vbs"
           if($LASTEXITCODE -eq 0){Write-Host "All went well"}else{Write-Host "Something went wrong: " + $LASTEXITCODE}
      $goOn= Read-Host("Another machine? (y)")

}while($goOn -eq "y")

this script will work quite well on older type of clients that are not to choosy about security (Windows clients older then Windows Vista) but on clients from Vista and above this script will only work when a user is logged on to the console; running it when no user is logged on will not result in very good deployments and running the script (started with a user account in the script) while an other user is logged on will also not do the trick. how do we solve this?
The trick is an option of psexec –i , this option calls an interactive process, when no SessionID is provided, psexec will run interactively in the console. when you enter a SessionID it will run in the provided session.
What i did is this: i took a function that checks for active sessions on the target machine, when no session is found mstsc is called to setup a session to the machine. In this session the deployment will run.


# thanks to http://adamstech.wordpress.com/2011/05/12/how-to-properly-pause-a-powershell-script/
Function Pause ($Message = "Press any key to continue . . . ") {
    If ($psISE) {
      
# The "ReadKey" functionality is not supported in Windows PowerShell ISE.
        $Shell = New-Object -ComObject "WScript.Shell"
        $Button = $Shell.Popup("Click OK to continue.", 0, "Script Paused", 0)

        Return
    }

    Write-Host -NoNewline $Message
    $Ignore =
        16,  # Shift (left or right)
        17,  # Ctrl (left or right)
        18,  # Alt (left or right)
        20,  # Caps lock
        91,  # Windows key (left)
        92,  # Windows key (right)
        93,  # Menu key
        144, # Num lock
        145, # Scroll lock
        166, # Back
        167, # Forward
        168, # Refresh
        169, # Stop
        170, # Search
        171, # Favorites
        172, # Start/Home
        173, # Mute
        174, # Volume Down
        175, # Volume Up
        176, # Next Track
        177, # Previous Track
        178, # Stop Media
        179, # Play
        180, # Mail
        181, # Select Media
        182, # Application 1
        183  # Application 2

    While ($KeyInfo.VirtualKeyCode -Eq $Null -Or $Ignore -Contains $KeyInfo.VirtualKeyCode) {
        $KeyInfo = $Host.UI.RawUI.ReadKey("NoEcho, IncludeKeyDown")
    }

    Write-Host
}


#Main procedureDO {Clear-Host
    # clear DNS to have the latest ip adresses   
Ipconfig /flushdns
        #enter a machine name
        Do  {$TargetMachine = Read-Host("Please enter the name of the Machine")
            If($TargetMachine -eq ""){Write-Host "That's no name, please try again"}
            }While($TargetMachine -eq "") 
    
  # Test for respons of machine
       
if(!(Test-Connection -Count 1 $TargetMachine)){ Write-Host "machine $TargetMachine is down"
             
               # Get the user session
               $loggedonuser = Get-WmiComputerSessions -computer $TargetMachine
                       if($loggedonuser.length -eq 0){write "No user is currently logged on `nChecking Operating System"
                            $OSType = (Get-WmiObject -ComputerName $TargetMachine Win32_OperatingSystem).Name
                            # checking the Operating System, if XP is found script version 1 can be used
                            # Else a RDP session will be started to be used by the litetouch.vbs script
                            if(!($OSType -like "*xp*")){
                                    $logonrdp = $TargetMachine + " /admin"
                                   # a session will be setup to the machine i use a rdp file here                                    mstsc /v:$logonrdp "D:\PSScripts\Logon scripts\Default.rdp"
                                  
# function pause is used to wait for the session to be fully running
                                    # thanks to
http://adamstech.wordpress.com/2011/05/12/how-to-properly-pause-a-powershell-script/
                                    Pause
                }}}

      # Now a sessionID will be fetched to be used by psexec       Write-Host "enumerating sessions"
       $SessionID = gwmi win32_process -computer $TargetMachine -Filter "Name = 'explorer.exe'"
       psexec.exe /accepteula  \\$TargetMachine -h -i $SessionID.SessionID -e -u DOMAIN\User -p password cscript.exe //Nologo //B "\\Deployserver\Deploymentshare$\Scripts\litetouch.vbs"
      # Depending on the exit codes the script will notify the user on success or failure       switch ($LASTEXITCODE)
       {
           0                   {Write-Host "All went well"}
           1                   {Write-Host "No user is logged on to the machine"}
           6                   {Write-Host "Machine $TargetMachine is not available"}
           53                  {Write-Host "The machine is restarted into WinPE to be deployed"}
           5206                {Write-Host "the deploy wizard could not finish"}
           -2147467259         {Write-Host "Litetouch generated arrors, check OSDLogs"}
            1073807364         {Write-Host "The machine is restarted into WinPE or the migratie went wrong"}
           -1073741510         {Write-Host "The machine is restarted into WinPE or the migratie went wrong"}
           default             {Write-Host "Something went wrong, the error is: " $LASTEXITCODE}
       } 
       Clear-Variable -Name OSType
$again= Read-Host("Do another machine (y)")
}while($again -eq "y")


i have tested the script on a lot of clients (XP and Windows 7 mixed), now you can service all these kind of Windows clients. till next time.



No comments:

Post a Comment