Mit leg tidligere på måneden med psappdeploytoolkit har fået startet et lille projekt, nemlig Poor mans software deployment system, hvilket egentligt er en meget simple executer af software som er wrapped med psappdeploytoolkit.

Version 0.01

Features:

Input en txt file med pc navne som skal have skudt en opdatering ud.
test om maskinen er tændt.
test om en bruger er logget på maskinen og præsentere den på logget bruger unatteded installations UI (psappdeploy)
auto rerun af install script såfremt at en bruger defer installationen ( error 5000 )
psappdeploy installation køre i maskinens system konto.


Prereqs:

Sysinternals suite
GPO, som laver c:\windows\logs\software til en \\computername\logs share  ( test om maskinen er tændt )
GPO, som enabler remote powershell.
GPO, som enabler remote eventlog ( eller port 445 til psexec )

Workflow:

A) Powershell script danner en psexec job file pr maskine som står i input txt filen.
A1) er der bruger på maskinen, skal serviceui benyttes, ellers skal installtion blot køres.
A2)er maskinen offline / ude af huset skal den direkte i rerun køen.
B) Powershell scriptet starter et powershell job pr psexec job file
C) Powershell script adventer alle jobs er færdig og danner nye pc liste såfremt installtionen er defered som køres efter X tid igen som step A)

Eksemple som kan deploy JRE 7u71 f.eks. ( udvikling kode så det er "grimt" )

 

---------------- kode start --------------------------------

Param(
  [string]$filePath
)
$defaltHostlist = "c:\pmsds\pc.txt"
if ($filepath.length -eq "0" )
{
$defaltHostlist = "c:\pmsds\pc.txt"
    Write-Host "Default input file with computernames :" $defaltHostlist
}
else
{
if (test-path $filePath )
{
$defaltHostlist = $filePath
Write-Host "custom input file with computernames : " $defaltHostlist
}
}
# --------------- følgende 3 linjer skal tilpases pr pakke som skal sendes ud
$ApptoInstall = "jre"
$AppDeployVersion = "7u71"
$ToInstall = "
\\pmsds\PMSDS\Software\ToInstall\jre7\Toolkit\Deploy-Application.exe"
# --------------- 
$Sleepsecuntes = "14400"
$pcs = Get-Content $defaltHostlist
"`nLoaded total pc from file $($pcs.count)`n"
$datestamp = Get-DAte  -format "dd-mm-yyyy-HH-mm"
$pmsdsRoot = "c:\pmsds"
$pmsdsJobs = "\jobs"
$pmsdslogs = "\logs"
$slash = "\"
$Filety = ".bat"
$filelog = ".log"
$filererun = ".rerun"
$filebad = ".BAD"
$Jcount = 0
$ServiceUI = "
\\pmsds\PMSDS\Tools\ServiceUIx64.exe "
$cmd = " C:\Windows\System32\cmd.exe /C "
$PSExec = "C:\SysinternalsSuite\psexec.exe \\"
$PSExecSystem = " -s "
$SUI = "_serviceUi"
$loganalyseLine = "C:\Windows\System32\cmd.exe exited on "
$joblog = $pmsdsRoot + $pmsdsJobs + $slash + $jobname
$jobname = $ApptoInstall + $AppDeployVersion
$jobdir = $pmsdsRoot + $pmsdsJobs +$slash +$ApptoInstall + $AppDeployVersion +$slash + $datestamp
$joblogdir = $pmsdsRoot + $pmsdslogs
$joblog = $pmsdsRoot + $pmsdslogs + $slash + $jobname + $filelog
$jobRerun = $jobdir + $slash + $slash + $jobname + $datestamp + $filererun
$jobBAD = $jobdir + $slash  + $slash + $jobname +$datestamp + $filebad

if(!(Test-Path -Path $jobdir)){
    New-Item -ItemType directory -Path $jobdir
}
if(!(Test-Path -Path $joblogdir)){
    New-Item -ItemType directory -Path $joblogdir
}
 foreach($pc in $pcs){
$softwarelogs = '\\'+ $pc + '\logs'
write-host "testing connection to : " $softwarelogs
if (Test-path $softwarelogs )
{
$scriptToRunWithUser =  $PSExec + $pc + $PSExecSystem + $cmd + $ServiceUI + $ToInstall
$scriptToRunNouser = $PSExec + $pc + $PSExecSystem + $cmd + $ToInstall
$runFileuser = $jobdir + $slash  + $pc+  $SUI + $Filety
$runFile = $jobdir + $slash  + $pc + $Filety
#write-host "to write:" $runFile
#write-host "to run: " $scriptToRun
# test om der er en bruger logget ind.
 $SB = {    Get-ChildItem Registry::\HKEY_USERS | Where-Object { Test-Path "$($_.pspath)\Volatile Environment" } | ForEach-Object { (Get-ItemProperty "$($_.pspath)\Volatile Environment").USERNAME }}
    $user = Invoke-Command -ComputerName $pc -ScriptBlock $SB
    write-host "User Loggedon: " $user
    if ($user.length -eq "0")
    {
        $scriptToRunNouser | Out-File $runFile  -Encoding ascii -Force
    }
    else
    {
        $scriptToRunWithUser | Out-File $runFileuser  -Encoding ascii -Force
        }
}
else
{
    $pc.tostring() | Out-File $jobRerun -Append -Encoding ascii
}
}
 get-job  -Name $jobname | remove-job
Foreach ($bat in get-childitem $jobdir){
 
    if ($bat.Extension -eq ".bat")
    {
    write-host "Running at background job : " $bat
    $scriptblock = $cmd + $bat.FullName
    $scriptBlock = [Scriptblock]::Create($scriptblock)
    start-job -Name $jobname -ScriptBlock $scriptblock
    }
}

write-host "All jobs are started sleeping 20 sec"
Start-Sleep -Seconds 20
get-job -Name $jobname | Wait-Job 
get-job -Name $jobname  | Receive-Job -Keep 2>&1 >  $joblog
$loganalyse = Get-Content $joblog
foreach ($line in $loganalyse )
{
    if ($line.ToLower().StartsWith( $loganalyseLine.ToLower()))
        {
         $analyse =  $line.Split(" ")
        $hostname = $analyse.Item(3)
        $psexit = $analyse.Item(7)
            if( $psexit -eq "0.")
             {
             Write-Host "job done"
             Write-Host "hostname: " $analyse.Item(3)
            Write-Host "Exitcode: " $analyse.Item(7)
            }
            elseif ($psexit -eq "5000.")
            {
             write-host "job defered, need to rerun"
            Write-Host "hostname: " $analyse.Item(3)
            Write-Host "Exitcode: " $analyse.Item(7)
            $analyse.Item(3).tostring() | Out-File $jobRerun -Append -Encoding ascii
            }
            else
            {
            write-host "job gone bad, look into it"
            Write-Host "hostname: " $analyse.Item(3)
            Write-Host "Exitcode: " $analyse.Item(7)
            $line.tostring() | Out-File $jobBad -Append -Encoding ascii
       }
    }
   }
   if (Test-Path ($jobRerun))
    {
    Write-Host "waiting this ammount of secondes before rerun: " $Sleepsecuntes
     Start-Sleep -Seconds $Sleepsecuntes
     Invoke-Expression -Command ($PSCommandPath + ' -filePath ' + $jobRerun)
  
   }

---------------- kode slut--------------------------------