GPO Startup Script – Practical PowerShell Download Command

Like most sysadmins that manage a lot of computers, I have a need for startup scripts.
Also, I deploy those startup scripts to the computer via GPO.
However, I prefer to download those scripts to the machine and run them locally.
This allows them to run even if the computer isn’t currently connected to the network, like a laptop that’s off-site.

Additionally, I like logs of things I’m doing, so a simple log for something like this is to use PowerShell’s Start-Transcript function.
It should be the first command that you run.
We’ll also need to send stuff to the log; Write-Host or Write-Output will do the job well.
Here’s the download command that we use, including a legit $path:

Now, we just have to make that a one liner and pass it to the powershell.exe via -Command:

Too easy, right?

Issue

The problem with deploying this via a GPO Startup Script with PowerShell’s -Command parameter is that GPO’s Script Parameter has a limit: 520 characters.
This command/script is currently 972 characters, just counting the parameters.

Resolution

There are two ways, that I know of, to reduce the size of this command:

  1. Use/Create PowerShell Aliases.
  2. Use just enough of a function’s parameter name to be unique.
    • i.e.: The Invoke-WebRequest function’s UseBasicParsing parameter can be shortened to -UseB (case-insensitive of course); not -U because there’s also a UserAgent parameter and the first three letters of both parameters are the same.

Let’s start trimming things down …

PowerShell Command Line parameters

PowerShell’s command line parameters follow the same rule shortening as as functions.
So here’s what we want to shorten; 82 characters not including the ellipsis:

Here’s the shortest we can make it; 24 characters not including the ellipsis:

Note: The -Command parameter is assumed.
Parameter values that have a set list of possible values are auto-completed, just like the parameter name.

Adjust Code Using Aliases and Shortened Parameters

If we’re going to create an alias:

  • Be sure it’s not already in use.
  • Be sure we’re using the function enough times to make a difference.

Take advantage of positional parameters when code shortening.

Here’s the adjusted code block from the top of this article:

Turns out I didn’t need to make any aliases.
If I needed to, I would have done so something like this: nal w echo.
Explained:

  • nal is an alias for New-Alias
  • w is my alias name
  • echo is an alias for Write-Output
    • Yes, it passes through.

I could have shortened the strings even more, but I can only use single quotes inside of the command because the whole command needs to be passed inside of double quotes. There’s a few options for a putting a variable in a string; the first option can’t be done and the third is the shortest, in this case, so we used it:

  • "$bLogsDownload-$a.ps1.log"
  • ('{0}LogsDownload-{1}.ps1.log' -f $b,$a)
  • $b'LogsDownload-'$a'.ps1.log'
    • Can only use this one when passing to a parameter.
  • $b+'LogsDownload-'+$a+'.ps1.log'

I switch to using the ellipsis ascii character (>; …) instead of three dots (...). Super handy to know that exists.

Note: Consider shortening the URL with your favorite URL shortening service; such as Google URL Shortener.
If you make the URL within an account, you can usually see click/download counts.

Note: I kept the empty lines in there for keeping a readabile comparison, but I will remove them before proceeding to the next section.

Final Command

So, let’s use our command, from the previous section, but reduced down even more; 492 characters:

You probably want to test it to make sure it’s working.
Here’s how I do it:

If that runs as expected, we can run $command via a powershell.exe command line parameter:

Yah!!
That’s 516 characters of arguments!!
We can even put the URL in a shortener, as previously suggested, to get it down to 479 characters:

Now, just put it in GPO’s Script Parameters field; as shown:

"GPO

Notes

Of course, the command is totally unreadable to most people, but it sure is short! :smirk:
Be sure to write some documentation and/or create a description on the GPO with some details.
Maybe I should write an updated blog post about this.

I have this implemented in production to make HiddenPowershell and HiddenRun available on all of the systems that I manage.
This allows me to execute PowerShell and other process completely hidden.
Check out those if your interested.

If you don’t have room for it, remove the Stop-Transcript from the end.

  • It just gives a nice log footer with an end time>; thus you can calculate total run time, if you so desire.
  • Additionally, you don’t have to do logging at all.

If you have a longer PowerShell script that you want run on mobile devices, implement something like this:

  • Drop the script in a repo.
    • Public: github.com, gist.github.com, gitlab.com, gitlab.com/snippets, or pastebin.com work great.
    • Private: gitlab.com or gitlab.com/snippets works great. Just make a Personal Access Token and tack it on the end of the URL for the raw download, like this:
      • https://gitlab.com/UNT-CAS/StartupScripts/raw/master/deploy.ps1?private_token=9koXpg98eAheJpvBs5tK
  • Download the script with the first Startup Script.
    • Be sure to download the raw version of the script.
  • Execute it with a second Startup Script.
    • GPO Startup Scripts are run in order; hence the ability to order them.

Leave a Reply

Your email address will not be published. Required fields are marked *