Help optimize, please

Hi all, from Halle (Saale), Germany,

i realized solution i want to share with you and hope for new impressions, code optimisations or/and maybe impressions for new functions for psadt maybe.(i like free for good :))

I did it with a planned schedule as User-GPO (executed as S-1-5-18), trigger: user logon and user delock screen, action: run some %network%\deploymentshare\maincheck.ps1. (users aren’t admin)
This code will check and if needed, first install or update the local “main-pack” (no app installer data) (especially: Is the local copy of deploy-application.ps1 older than actual productive one in %network%\deploymentshare\Main\ ? Copy !)
And at finish it starts the local copy of “main pack”
(deploy-application.exe with ServiceUI.exe from actual MDT)

Then i tooked time to play with deploy-application.ps1
I first now started to make some tests with the “install part”.
In actual architecture, ( i am no programmer, no function made actual for that (help- thanks!))
i work with, i call it “app_install_block”.
Each “app_install_block” consist the following:

  1. (if not alluser-software) checks AD security group membership (maybe also computer account to double secure, and/or also useful to report %app%- %user and %computer%,
  2. (actual easy standard to check if app is “installed” in wished version)
    check if C:\Deploymentcache\%app%%version%.txt exists
  3. check if local deployment cache “C:\Deploymentcache\%app%\%version%”\* exists (if not do copy it)
  4. start local copy of new or/refresh install routine or go to next “app_install_block”
    “C:\Deploymentcache\%app%\%version%\…" (execute-msi/execute-process)
  5. write C:\Deploymentcache\%app%%version%.txt

So if some app need an update (%version%), or some new app (%app%\%version%), i only have to make some changes to the associated “app_install_block” in deploy-application.ps1 on the productive networkshare.

Thats easy free patch management with good trigger options and informing or/and interacting, if wanted or sometimes needed.


…thanks for impressions, contacts and helps :slight_smile:

I suspect that you do not have an SCCM server? These script will probably work, but the guy that needs to take over your job role (if anything should happen to you), needs to invest a lot of time to get to know this custom system. This is why an SCCM is always a good choise because Engineers with SCCM knowledge are often easier found on the job market.

I hope you provided a good documentation with this “C:\deploymentcache” system so that it will be understandable to the next guy who takes over …

Hey Sven.

Yes no SCCM or it’s not free :sweat_smile:
You will see you dont need me for that.

I will post scripts soon, so you can see its really easy.
(for example the local “C:\deploymentcache” / “main kit” in it, is only a nearly empty local copy of PASDT)


ok, with a changed deploy-application.ps1 (but no main changes in it , only use)


Looking forward to that

Always happy to see what lives in the community

1 Like

The secret was (also is), to brought all things i wanted (idea’s) to do, together. Then i only builded the architecture for it.
(Yes, maybe some call it a little virtual invention. :innocent: )
Maybe same hard or easy like it “should be” in real life.

  1. User-GPO: Scheduled Task as S-1-5-18 (important not write “SYSTEM” write “S-1-5-18”)
  2. Trigger: “Any” user unlocks screen and “any” user login on machine. (for “full machine health control” - if you want)
  3. Action: run application: \\%your network share%\productive\MAINrun.exe:
    (Background: I tried some hours to start a “Mainrun.ps1” with local powershell.exe directly and couldn’t got it worked. I also didn’t wanted to work with some cmd/bat. i wanted to do it only with powershell. So i sayed f*ck off and compiled it with a “PS1toEXE-Tool” because it works really fine with an “EXE”)
  4. Mainrun.ps1 code:
    (Background: Normally no changes needed here, but if needed, you only have to change the “productive EXE”, filled with some other action, maybe you want delete the complete local deployment cache folder and delete the whole schedule, and all action will stop.)
Try { Set-ExecutionPolicy -ExecutionPolicy 'ByPass' -Scope 'Process' -Force -ErrorAction 'Stop' } Catch {}


$CachePATHMainKit = "C:\deployment_cache\MainKit"
$targetfile = "$CachePATHMainKit\Deploy-Application.ps1"
$file = "\\%your network share%\productive\MainKit\Deploy-Application.ps1"
$PSNuGet = "C:\Program Files\PackageManagement\ProviderAssemblies"

check if local Deploy-Application.ps1, is not newer than the Deploy-Application.ps1 from the productive system. If so, she will be actualized. Else, do nothing. (This is for: “Client software change management”)

if ( test-path $targetfile ) {
  if (!( (get-item $targetfile).LastWriteTime -gt (get-item $file).LastWriteTime ))
    Copy-Item $file $targetfile -Recurse -force
  else {}  

check if the folder: “C:\deployment_cache\MainKit” not exists. If so , create folder and copy the whole “MainKit” from productive system to local cache. Else, do nothing. (This is for: “Client go first time under management”)

if (!(Test-Path $CachePATHMainKit))
    New-Item -Path $CachePATHMainKit -ItemType Directory
    Copy-Item -Path "\\%your network share%\productive\MainKit\*" -Destination $CachePATHMainKit -Recurse -force

check if the local folder: “$PSNuGet\NuGet\” not exists. If so, create folder and copy the needed “Powershell 6 commandlet” from productive system to local system and install it in the local system. Else, do nothing. (Background: I like and need to use these newer powershell 6/7 functions later in the “Deploy-Application.ps1” to easier (don’t want use old WMI in Powershell and so on) get an client under management, especially if some older versions of apps needed to detect and uninstall, before install newest versions.)

if (!(Test-Path "'$PSNUGET\NuGet\'"))
    Copy-Item -Path "\\%your network share%\productive\nuget\*" -Destination $PSNUGET -Recurse -force
    Import-PackageProvider -Name NuGet -RequiredVersion

now its time to change to local cache path and start the “Deploy-Application.exe” with “ServiceUI.exe” for use your function “Execute-Process” from here also (Also here was the best functionality for me, with your original EXE that also starts the PS1, instead of try some time to start PS1 directly)

cd "$CachePATHMainKit"
. .\AppDeployToolkit\AppDeployToolkitMain.ps1
Execute-Process -Path "$CachePATHMainKit\ServiceUI.exe" -Parameters "Deploy-Application.exe" -WindowStyle Hidden

end code

  1. file/folder content of “\\%your network share%\productive\MainKit”:
  • A copy from clean “Toolkit”-Folder from PSADT 3.8.3.

  • A copy from ServiceUI.exe in it. (From actual version of MDT,which i also use for base Operating System-Deployment, but thats another chapter).

  • The user modified “Deploy-Application.ps1” in it. (Explained in Part II)

  1. file/folder content of “\\%your network share%\productive\NuGet\”:
  • A copy of Microsoft.PackageManagement.NuGetProvider.dll
    (Background: Got it from Import-Package on Internet connected client)

So now i am nearly done with part 1 for today.
You all know now, how i prepared the “Main-Kit” for install and also upgrade, with a little implemented “intelligence” and ready for use.

  1. Part II with the content of Deploy-Application.PS1 will follow soon.
    I would like to reveal two things.
  • All entries are only done in the “App_block” in the installation part of Deploy-Application.PS1. Install / patch to newer version / re-install / de-install

  • Each App (or what ever you want to do) has his “App_block” so you can easily use a template from copied “App_block”, paste it and fill it with your modified variable app data, to easily handle several apps and also to etablish an effective procedure for operating. If one App need a “change”, i only have to change the associated block, save the Deploy-Application.PS1 in productive path, and instantly every “schedule trigger” will go and get the actualized PS1 and do the changed steps from the associated App_block, without have influences to the other application blocks.