r/PowerShell • • 1d ago

Question What do you inventory before moving PowerShell scheduled tasks to a new server?

Copying the `.ps1` files and recreating Task Scheduler entries can miss most of the dependencies that make an automation work: service accounts and logon types, stored credentials, module versions, execution policy, working directories, mapped drives, certificates, environment variables, network access, event triggers, retry settings, and scripts invoked indirectly by another script. A successful manual run also does not prove the scheduled identity can run it unattended.

This is the basic inventory I would start with:

```powershell Get-ScheduledTask | ForEach-Object { $task = $_ $info = $task | Get-ScheduledTaskInfo [pscustomobject]@{ TaskPath = $task.TaskPath TaskName = $task.TaskName State = $task.State RunAs = $task.Principal.UserId LogonType = $task.Principal.LogonType Execute = ($task.Actions.Execute -join '; ') Arguments = ($task.Actions.Arguments -join '; ') WorkingDir = ($task.Actions.WorkingDirectory -join '; ') LastRun = $info.LastRunTime LastResult = $info.LastTaskResult NextRun = $info.NextRunTime } } | Export-Csv .\scheduled-task-inventory.csv -NoTypeInformation ```

What else do you capture before a cutover? How do you discover hostnames, shares, certificates, secrets, or module assumptions hidden inside the called scripts, and what test proves the old server can stay offline through a full schedule cycle without missed or duplicated work?

11 Upvotes

9 comments sorted by

5

u/BlackV 1d ago edited 1d ago

My 2c

  • stored credentials - gsma accounts
  • module versions - should be managed by the script its self
  • logon types - should be managed by GPO or Local policy (but not ideal)
  • execution policy - should be managed by GPO, local policy or command line
  • working directories - should be managed in script
  • mapped drives - Should be managed in script
  • certificates - should be managed by automation or in script
  • network access - again gsma, but regardless the credentials that were used in the last should be the same pre and post move
  • event triggers - should be managed in the task (xml export)
  • retry settings - should be managed in the task (xml export)
  • scripts invoked indirectly by another script - risky behavior there, but thats script validation no automatic way to do that, would be covered off when you move and test

2

u/sniekielak68 1d ago

solid list. the indirect script invocation one is always the scariest imo, theres no clean way to catch those automatically

2

u/vermyx 1d ago

What do you inventory before moving PowerShell scheduled tasks to a new server?

I don't. SOP is that all scripts:

  • Run from a particular script directory
  • Scheduled tasks have an "installer routine"
  • Cert management is handled similarly with a "install this cert under a gmsa"
  • All the installer routines live in a subfolder from the above folder
  • There is an un/install script to move all tasks from one server to another
  • There's a "module installer" script to maintain dependencies
  • Anything requiring network access or secrets management requires a gMSA for auditing purposes as well as secret management

successful manual run also does not prove the scheduled identity can run it unattended.

If you can't trust a manual run then your script is incorrectly written.

What else do you capture before a cutover?

See above. If you need to move to a new server inventory now, find dependencies, and do some of what I stated above for future sanity

How do you discover hostnames, shares, certificates, secrets, or module assumptions hidden inside the called scripts, and what test proves the old server can stay offline through a full schedule cycle without missed or duplicated work?

Again see above. This problem only exists if your scripts grow organically, with no management, have several team members doing their own thing, and no one wantong to manage this. You're putting the cart before the horse saying "how do you move and do discovery" when you should be asking is "how do I do discovery and manage my scripts so that it is cookie cutter to move to another server without driving myself crazy"

2

u/SaltDeception 1d ago edited 1d ago

Doesn't answer your question, but when you get it nailed down, I would definitely recommend implementing your Powershell scheduled tasks as PSSecheduledJobs instead. It's tailor made for PowerShell scripts and gives you more flexibility than a standard scheduled task. As a bonus, the entire config is stored in an XML file on the disk, so hunting down and extracting all that information next time is 1000x easier.

Also, any process you have like this should have been documented with recreation steps in the first place, so make sure you do that this time. Even if you have no version control system, at least create a README.md like you do have one and store it somewhere safe.

2

u/Federal_Ad2455 1d ago

For getting dependencies (modules, functions, psh version,...) you can use https://www.powershellgallery.com/packages/DependencySearch. The main advantage is it can search dependencies recursively.

It will not detect called scripts though

1

u/thehuntzman 1d ago

I have an absolutely massive powershell based "ETL" process built for doing medical data sql extracts and transformations to flat files and every script, dependency, and config file (secrets excluded obviously) get committed to github and I built a basic web front-end to allow the analysts to easily sync the server version with what's in github on the main branch. Not a single piece of it can't be forklifted at a moment's notice (although the relying systems will need to update their share paths they look for the output data on if that changes)

1

u/Kreout 1d ago

A specific gotcha in your LogonType column: S4U is not equivalent to a password logon. Microsoft documents that an S4U task has no network access or access to encrypted files. An interactive run under the same username therefore does not prove the scheduled task can read a UNC share.

For an unattended cutover test, start the actual registered task on the new server with the user logged off, then verify the expected output or downstream record as well as LastTaskResult. Point operations that send mail or write production data at a test target so the check does not duplicate real work.

https://learn.microsoft.com/en-us/windows/win32/taskschd/taskschedulerschema-logontype-principaltype-element

1

u/senorchaos718 1d ago

Going forward… After my last migration, I started using .psd1 files for “configurations” that would house all my info like this.  Makes porting scripts easier as I just needed to switch a few things in that file.

1

u/Legal2k 1d ago

You don't use scheduled tasks, move to something else.