Managing Computers with GPO?

Our team computers are a nightmare to keep up to date. We have 8 different images for different models, which we haven’t been able to keep up to date with each other because we don’t have a student dedicated to IT. It tends to fall on the programming team to manage all computers, not just programming team ones. I would love a way to automate it to make life easier.

Here are the basics of our team computers:

  • We have about 8 different models of laptops, all of them running W10 Pro
  • Most of these are older laptops: T2 and W4 series ThinkPads or their equivalent Latitudes and Precisions
  • We have one new laptop: a T580, which is our Driver Station
  • There are three types of computer use cases: General (requires Chrome, Firefox, 7Zip, Inkscape), Programming (requires general and WPILib, NI, LibreOffice, etc.), CAD (requires general and SolidWorks)
  • We currently do not use Active Directory for management: all management is done in the images which is then mirrored to our laptops. Ninite is used for updating core apps, and students are responsible for keeping their use-case-specific apps up to date

This is a nightmare to maintain, and no two computers end up in the same state. I have been reading up on ways to manage Windows computers.

  • Ansible, which I have used with Linux, has the ability to run on Windows computers. However, it doesn’t seem designed to handle Windows as well as it handles Linux
  • Active Directory, which can have stuff deployed through GPO, but requires a physical Windows Server to run, and we aren’t interested in many of the other features that Active Directory has.
  • Configuration Designer, which can create a file that is run on computers and remotely configures them. It has the ability to install EXE and MSI files.

We need a system to be able to

  • Use Windows
  • Create one user account (we use the same account across all of our devices)
  • Specify connection to our school district’s internet without requiring students to manually enter a password
  • Set Windows personalization settings (background image, lock screen)
  • Install our commonly used applications

So I have a couple of questions for teams:

  • What system do you use for management?
  • How easy is it to install Solidworks through an MSI or silent EXE?
  • How easy is it to install the FRC Development Suite (NI, WPILib, CTRE Phoenix) through an MSI or silent EXE?

Thank you for your help! We are desperate for a better solution.


Lol, I just set up one computer with an image for programming and clone it to the rest (other than the one-off machines). General use is handled by personal systems, and CAD is handled by school-provided workstations. Unfortunately we can’t really run our own servers so this is how I have to do it

1 Like

We don’t use anything for our laptops, but I recently moved my church to Microsoft 365 Business. Non-profits can get 10 free accounts. M365 includes Intune and Azure AD for management, 1TB of OneDrive storage per account, and Office 365. Intune allows you to set almost setting GPO can (including security, personalization, and WiFi), and you can remotely deploy MSI installers.

1 Like

My Advise is to find and assign a mentor to do all the machine maintainence (whether he does it or over sees students that’s up to your team).

The numbers that you are looking at having to maintain, to me, doesn’t make any sense to image each use case as such. So instead of ‘image’, categorize usage.

Apps that should be universal across all machines (doesn’t hurt if it’s on): 7zip, Chrome/Firefox/Edge browsers, Adobe Acrobat Reader, and whatever else your team needs should just be deployed and be on every machines.

Programming/Drive Station - the full NI, VS Code, WPI + 3rd party libraries. For the most part, all programmers are responsible to check and update at the beginning of each meeting if there’s any updates.

CAD/CAM - be it Solidworks or Fusion or what have you. We standardized on Fusion and find its installation/maintenance is a lot easier to deal with plus the facts that all drawings are in the cloud is a plus since then students can install Fusion at home and they would have full access to everything. Fusion also prompts you to update if update is available (all are setup to receive update downloads automatically).

3d printer - setup as CAD/CAM but with additional drivers (depending on your 3d printer use).

CNC Router driver - also a CAD/CAM but with the CNC router’s drivers installed.

All of our computers (purchased+donated), we managed ourselves and are NOT part of the school’s internal network. Rather, we network (peer) them all within our own subnet and then just use a gateway to piggyback on the school’s network and out into the Internet. We’re also using Teamviewer to do all maintenance (once a month - all MS patches are pushed out from MS on Tuesday. All Win 10 Pro are set to have patches auto installed - except for the Drive Station - Drive Station we always locked down 2 weeks before our 1st competition. All machines also has Avast (Antivirus installed).

I’m a student in the role of your mentor suggestion, I do my best with what I know and have available. Imaging just makes it more convenient instead of installing the same software 9 times. The one-off computers (CAM/3D printing computer and the CNC driving computer) aren’t imaged, but our school CAD machines are running the school’s image and I image the programming machines (instead of installing the same thing everywhere repeatedly).

I recently thought of making a batch script that installs everything (this is mostly for programming laptops…) - WPILib, vendor, sparkmax client, etc. I plan on making it so you can specify with flags/switches what you (don’t) want to install. However, maintaining and updating the versions it installs won’t be fun. Is there a way to download the “latest” version of something instead of a specific version? Another option is just querying what the latest version is (then perhaps something like a build system can be implemented).
Any ideas, etc?

My co-lead for programming did something like this last season. It went alright, though we didn’t really use it this season. Mainly due to being busy with everything else so no time to set up for 2020.

Any chance you can share what you have?

I’m the co-lead, here’s the script:

@echo OFF
rem check for admin privileges, and then prompt for them if needed
net session >nul 2>&1
if %errorlevel%==2 powershell -noprofile -command "&{ start-process '%~f0' -verb RunAs}" && exit
cd %~dp0
rem Define what is copied
set installroot="%userprofile%\Programming"
set copy[0]="Phoenix-Documentation-master"
set copylength=1

rem Define programming installers
set programminginstaller[0,0]=
set programminginstaller[0,1]="FRCUpdateSuite_2018.1.0\setup.exe"
set programminginstaller[1,0]=
set programminginstaller[1,1]="Phoenix-diagnostics-Tuner-v1.5.2\CTRE_Phoenix_Tuner.exe"
set programminginstaller[2,0]=
set programminginstaller[2,1]="GRIP-install.exe"
set programminginstaller[3,0]=
set programminginstaller[3,1]="WPILibInstaller_Windows64-2020.3.2.exe"
set programminginstaller[4,0]=
set programminginstaller[4,1]="navx-mxp\setup.exe"
set programminginstaller[5,0]=
set programminginstaller[5,1]="FRC_Radio_Configuration_19_1_1.exe"
set programminginstaller[6,0]=
set programminginstaller[6,1]="FileZilla-install.exe"
set programminginstaller[7,0]=
set programminginstaller[7,1]="git-install.exe"
set programminginstaller[8,0]=
set programminginstaller[8,1]="git-desktop-install.exe"
set programminginstaller[9,0]="jdk-11.0.7_windows-x64_bin.exe"
set programminginstaller[9,1]=
set programminginstallerlength=10

rem Define programming installer parameters
set programminginstallerparams[0]=""
set programminginstallerparams[0]=%programminginstallerparams[0]:"=%
set programminginstallerparams[1]=""
set programminginstallerparams[1]=%programminginstallerparams[1]:"=%
set programminginstallerparams[2]=""
set programminginstallerparams[2]=%programminginstallerparams[2]:"=%
set programminginstallerparams[3]=""
set programminginstallerparams[3]=%programminginstallerparams[3]:"=%
set programminginstallerparams[4]=""
set programminginstallerparams[4]=%programminginstallerparams[4]:"=%
set programminginstallerparams[5]=""
set programminginstallerparams[5]=%programminginstallerparams[5]:"=%
set programminginstallerparams[6]="/S /user=all"
set programminginstallerparams[6]=%programminginstallerparams[6]:"=%
set programminginstallerparams[7]="/silent"
set programminginstallerparams[7]=%programminginstallerparams[7]:"=%
set programminginstallerparams[8]=""
set programminginstallerparams[8]=%programminginstallerparams[8]:"=%
set programminginstallerparams[9]=""
set programminginstallerparams[9]=%programminginstallerparams[8]:"=%

rem Define where programming installers install to
set programminginstallerdir[0]="C:\Program Files (x86)\National Instruments"
set programminginstallerdir[1]="C:\Users\Public\Documents\Cross The Road Electronics\LifeBoat"
set programminginstallerdir[2]="abcd"
set programminginstallerdir[3]="C:\Users\Public\frc2019"
set programminginstallerdir[4]="%programfiles(x86)%\Kauai Labs\navX-MXP"
set programminginstallerdir[5]="%programfiles(x86)%\FRC Radio Configuration Utility"
set programminginstallerdir[6]="%programfiles%\FileZilla FTP Client"
set programminginstallerdir[7]="%localappdata%\Programs\Git"
set programminginstallerdir[8]="%appdata%\GitHub Desktop"

rem Define cad installers
set cadinstaller[0,0]=""
set cadinstaller[0,1]="GrabCAD-Workbench-installer.exe"
set cadinstaller[1,0]=""
set cadinstaller[1,1]="SOLIDWORKS 2017 SP02\setup.exe"
set cadinstallerlength=2

rem Define cad installer parameters
set cadinstallerparams[0]=""
set cadinstallerparams[0]=%cadinstallerparams[0]"=%
set cadinstallerparams[1]=""
set cadinstallerparams[1]=%cadinstallerparams[1]"=%

rem Define where cad installers install to
set cadinstallerdir[0]="%localappdata%\Programs\GrabCAD\GrabCADDesktopClient"
set cadinstallerdir[1]="%programfiles%\SOLIDWORKS Corp\SOLIDWORKS"

SetLocal EnableDelayedExpansion

rem Check for system architecture type (32 or 64 bit)
reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL && set OS=32BIT || set OS=64BIT
ECHO This is a %OS% Machine

rem Prompt user for installation type
ECHO What would you like to install?
ECHO 1-programming
ECHO 2-cad
ECHO 3-both*
ECHO 4-cancel
choice /c:1234
IF %install%==4 GOTO:EOF
IF %install%==2 GOTO cad

rem Create %installroot% if it doesn't exist, then proceed to copy stuff into it and run programming installers
ECHO Installing Programming
ECHO Creating %installroot%
IF NOT EXIST "%installroot%" mkdir "%installroot%"
ECHO Starting programming copy loop
set i=0
IF NOT %i% lss !copylength! goto programmingcopyloopend
ECHO Copying !copy[%i%]!
IF EXIST "%installroot%\!copy[%i%]!" goto programmingcopyloopcontinue
mkdir "%installroot%\!copy[%i%]!"
rem xcopy /s /y /d
robocopy /s /xo /mt:128 /r:10 /m:1 "%~dp0\!copy[%i%]!" "%installroot%\!copy[%i%]!" > nul
set /A i=!i!+1
goto programmingcopylooproot
ECHO "C:\Programming\gradle-4.10.2" | FIND /I "%PATH%">NUL && SETX PATH %PATH%;"C:\Programming\gradle-4.10.2"

rem copy loose files
robocopy /s /xo /mt:128 /r:10 /m:1 "%~dp0\Copy" "%installroot%" > nul

ECHO Starting programming install loop
set i=0
IF NOT %i% lss !programminginstallerlength! goto programminginstallloopend
ECHO installing !programminginstaller[%i%,1]!
IF EXIST !programminginstallerdir[%i%]! goto programminginstallloopcontinue
IF %OS%==64BIT IF "!programminginstaller[%i%,0]!"=="" goto programming32 ELSE goto programming64 ELSE goto programming32
START /WAIT "" "%~dp0\!programminginstaller[%i%,0]!" !programminginstallerparams[%i%]!
rem set isjdk = echo !programminginstaller[%i%,0]! | find "jdk"
rem IF NOT [%isjdk%]==[] goto programming32
goto programminginstallloopcontinue
START /WAIT "" "%~dp0\!programminginstaller[%i%,1]!" !programminginstallerparams[%i%]!
goto programminginstallloopcontinue
set /A i=!i!+1
goto programminginstalllooproot
IF NOT EXIST "%JAVA_HOME%" ( IF EXIST "%programfiles%\Java\jdk-11.0.4" SETX JAVA_HOME "%programfiles%\Java\jdk-11.0.4" )

rem run cad installers
IF %install%==1 GOTO end
ECHO Starting CAD install loop
set i=0
IF NOT %i% lss !cadinstallerlength! goto cadloopend
ECHO installing !cadinstaller[%i%,1]!
IF EXIST "!cadinstallerdir[%i%]!" goto cadloopcontinue
IF %OS%==64BIT IF "!cadinstaller[%i%,0]!"=="" goto cad32 ELSE goto cad64 ELSE goto cad32
START /WAIT "" "%~dp0\!cadinstaller[%i%,0]!" !cadinstallerparams[%i%]!
goto cadloopcontinue
START /WAIT "" "%~dp0\!cadinstaller[%i%,1]!" !cadinstallerparams[%i%]!
goto cadloopcontinue
set /A i=!i!+1
goto cadlooproot
GOTO end
ECHO End of script
IF %install%==1 SHUTDOWN /r /t 0

If you’re familiar with batch, then understanding it shouldn’t be too problematic, it’s pretty well commented, anything strange it does is explained, there’s ajsut a few things like “installer” has a pair for each entry, 0 is for x64, 1 is x86. The second line to set the parameters is to remove the quotes because params don’t work with quotes, and there’s a list of directories that they install to so that it doesn’t install something it doesn’t have to, although I’m not sure where GRIP installs to. It has an auto-restart at the end, and prompts for whether you want the programming or CAD package, or both. There’s also some commented-out code to run both x86 and x64 for the jdk, if you want that.
I also noticed that you wanted an update script, and I made that too, although it’s not very smart.

@echo off
title Updating Installers...
echo git desktop
curl -L -o Git-desktop-install.exe
echo git
curl -sL | find /I "browser_download_url" | find /I "64-bit.exe" >tempurl
set /p url=<tempurl
set url=%url:~30%
curl -L %url% -o Git-install.exe
echo filezilla
curl -s | find /I "quickdownloadbuttonlink" >tempurl
set /p url=<tempurl
set url=%url:~48,-101%
curl -L %url% -o Filezilla-install.exe
echo frc radio config
curl -L -o
"%programfiles%\7-zip\7z.exe" x -y >nul
del /s /s "" >nul
echo navx
curl -L "" -o
rmdir /s /q navx-mxp
"%programfiles%\7-zip\7z.exe" x -y -onavx-mxp >nul
del /s /q "" >nul
echo wpilib
curl -sL | find /I "browser_download_url" | find /I "Windows64" >tempurl
set /p url=<tempurl
set url=%url:~30%
curl -L %url% -o
"%programfiles%\7-zip\7z.exe" x -y >nul
del /s /s "" >nul
echo grip
curl -sL | find /I "browser_download_url" | find /I "x64.exe" >tempurl
set /p url=<tempurl
set url=%url:~30%
curl -L %url% -o Grip-install.exe
echo phoenix tuner
curl -sL | find /I "browser_download_url" >tempurl
set /p url=<tempurl
set url=%url:~30%
curl -L %url% -o
"%programfiles%\7-zip\7z.exe" x -y >nul
del /s /q "" >nul
echo ---------------------------------------------------------
echo --!!FRC update suite will have to be updated manually!!--
echo ---------------------------------------------------------
del /s /q tempurl >nul
title Done Updating

uses cURL to retrieve everything, you could probably make something smarter with powershell or batch/powershell hybrid.
Also, for the original post, might I suggest Ninite? It is a single-download single-run program to install a bunch of the more common softwares.

1 Like

This looks awesome! Thank you so much!

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.