Agree with the try...catch approach, but the if ($?) {} works well too, but won't catch exceptions that would normally throw the script completely.
Either way, one of the strengths of PowerShell is also one of its weaknesses. I'm talking about pipelining. Yes, it's great that you can pass objects down the pipe, but when you're script is running in production, and you need to gracefully fail, create a meaningful log, return a meaningful return code, possibly SMS the person on standby and maybe even run a recovery job, a pipeline that has just barfed on the 50th object it came across, when there's another 70 to go isn't of much use.
In a production script, I'd strongly recommend staging your "pipe work". That is, use the power of the pipeline to gather your work queue (Get-VM | Where-Object, blah, blah), and shove this into an array of objects.
Then use a Foreach-Object to step through the objects in your work queue. Within the Foreach-Object, use your try...catch when it comes to things like Remove-Snapshot, and interrogate the returned exception object in order to provide your return code / log file / alert / recovery sequence, etc.