Need help writing better PS code

please help me write the below function better.

Context: This script/function lives on my local machine. I want to pass variables to the function, then pass them into an invoke-command script block to be run on a remote machine.

This code works, but i don’t feel like its good practice, or the best way of doing it, as i have to pass my params around multiple times, and it all just feels a bit clunky…

In addition i would like to get results back from the remote machine, so that i can run additional commands back in my local session, but using variables created from the remote session. I know i can do something like $results = invoke-command, but is that the best, and will that work when its already inside another function…

function Create-NewVM
  param($param1, $param2, $param3, $param4)

   $ScriptBlock = 
    param ($param1, $param2, $param3, $param4)

    # do a bunch of stuff on my remote machine
    $var = xyz

    $htmlBlock = @"          
     Whether i do $var or $($var) here, either way, when i try to expand it later, it is empty.  What am i doing wrong?

    # I try to now expand $htmlBlock in a Send-MailMessage command, but $var is blank, empty.. ??
    Send-Mail-Message -body $htmlBlock...

$s = New-PSSession hypervhost.fqdn
Invoke-Command -Session $s -ScriptBlock $ScriptBlock -ArgumentList $param1, $param2, $param3, $param4


Create-NewVM -computername "vm01" $param1 $param2 $param3 $param4

I know there are a few issues i have raised here, so please feel free to ignore some, i mainly want to see if there is a better structure/method/layout to writing this as a whole. If you can answer the knitty gritty details about $htmlBlock and returning variables back to my local session, that is just a bonus, however i can work that out myself later, once i get the main design of the code looking better.

thank you for any of your help.

I don’t see any problems with your parameters. One, you have to pass them into your Create-NewVM function*, two, if you’re going to get their values to a remote computer they’re going to need a parameter block inside your script block variable, and three, you’ll need to use the -AgrumentList parameter and your parameters again.

If you’re working with PowerShell 3.0, you can use the Using scope modifier to get your local variables into a PS Remoting session, and make this a little less “clunky.” I did a super quick write up here, and more recently discussed it here and here. You’re using the PowerShell 2.0 version of getting local variables into a PS Remoting session.

  • Create is not an approved verb and so I’d suggest you not use it. Please stick to only using approved verbs. Check Get-Verb for a full list. If you really want to use Create, then make Create-NewVM an alias for the true function name you’ll use, that includes an approved verb.

$var = xyz
The above variable assignment is running the function xyz and putting the results inside $var. Do you have a function called xyz? Probably not. If you’re trying to get the string value ‘xyz’ into the variable $var, then put single quotes around it. If there is a function called xyz, then you need to change it to use an approved verb :), and include the code so we can try and determine why it’s not returning a value(s).

Define your scriptblock outside of the function and pass it in.

This looks ugly given I have to use write-host here but for ex.

$scriptblock = {write-host $param1 $param2 $param3 $param4}

function Create-NewVM
param ($scriptblock, $param1, $param2, $param3, $param4)

Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $param1, $param2, $param3, $param4


Create-NewVM -computername "vm01" $scriptblock one two three four

I second the approved verb but sometimes you may want to passive aggressively pass on to your helpdesk do-somethingamonkeycoulddo.

Thank you both for your feedback very much, i take it on board, and will adjust as you have advised.

Please also check out below. It might give you a couple of ideas to improve your code.

I hope that helps and I’m looking forward to future questions from you with improved code samples.


I think he wanted to avoid the redundant code of passing the params around. You can pass the scriptblock as an argument and achieve the same thing. Learning to do it this way will help in advanced job tracker functions down the road.