. $PSCommand is a blocking (synchronous) call, which means that Exit on the next line isn't executed until $PSCommand has itself exited.
Given that $PSCommand here is your script, which never exits (even though it seemingly does), the Exit statement is never reached (assuming that the new version of the script keeps the same fundamental while loop logic).
While this approach works in principle, there are caveats:
You're using
., the "dot-sourcing" operator, which means the script's new content is loaded into the current scope (and generally you always remain in the same process, as you always do when you invoke a*.ps1file, whether with.or (the implied) regular call operator,&).
While variables / functions / aliases from the new script then replace the old ones in the current scope, old definitions that you've since removed from the new version of the script would linger and potentially cause unwanted side-effects.As you observe yourself, your self-updating mechanism will break if the new script contains a syntax error that causes it to exit, because the
Exitstatement then is reached, and nothing is left running.
That said, you could use that as a mechanism to detect failure to invoke the new version:- Use
try { . $ProfilePath } catch { Write-Error $_ }instead of just. $ProfilePath - and instead of the
Exitcommand, issue a warning (or do whatever is appropriate to alert someone of the failure) and then keep looping (continue), which means the old script stays in effect until a valid new one is found.
- Use
Even with the above, the fundamental constraint of this approach is that you may exceed the maximum call-recursion depth. The nested
.invocations pile up, and when the nesting limit is reached, you won't be able to perform another, and you're stuck in a loop of futile retries.
That said, as of Windows PowerShell v5.1 this limit appears to be around 4700 nested callslimit appears to be around 4900 nested calls, so if you never expect the script to be updated that frequently while a given user session is active (a reboot / logoff would start over), this may not be a concern.
Alternative approach:
A more robust approach would be to create a separate watchdog script whose sole purpose is to monitor for new versions, kill the old running script and start the new one, with an alert mechanism for when starting the new script fails.