2

I'm trying to write a Powershell function to create an OrganizationalUnit. I'm a PS newbie but I've pieced together:

function makeOU ($cn, $path)
{
  $sb = [scriptblock]::Create(
      "New-ADOrganizationalUnit $cn -path `"$path`"
        -ProtectedFromAccidentalDeletion 0"
    )

  Invoke-Command -ComputerName $server -Credential $Credential `
    -ScriptBlock $sb
}

But when I invoke this later in the script, I get a message that -ProtectedFromAccidentalDeletion is an unknown cmdlet. If I make the command one line

"New-ADOrganizationalUnit $cn -path `"$path`" -ProtectedFromAccidentalDeletion 0"

it works.

As I see it, at the end of

      "New-ADOrganizationalUnit $cn -path `"$path`"

there is an open parenthesis and an open quote so PS should be looking for more input. Ending that line with a back tick didn't help. Nor did converting the argument to Create() to the form @" ... "@. (This is different from Why I am getting PowerShell Parsing Error? in that I don't have any back ticks, certainly none with spaces after them.)

If I'm making an newbie error here and there's a better way to pass the function parameters to Invoke-Command, I'm open to rewriting but failing that, how can break the string passed to Create() onto multiple lines?

1

3 Answers 3

3

Chris Nelson: Your "if you really want to" makes it sound like I'm doing something grossly anti-idomatic to PS. I'm perfectly willing to believe that so I wonder how you'd write it.

Thing is, backticks are frowned upon in Posh community:

In general, the community feels you should avoid using those backticks as "line continuation characters" when possible. They're hard to read, easy to miss, and easy to mistype. Also, if you add an extra whitespace after the backtick in the above example, then the command won't work. The resulting error is hard to correlate to the actual problem, making debugging the issue harder.

The preferred way to avoid long lines is to use splatting (see About_Splatting) and PowerShell's implied line continuation inside parentheses, brackets, and braces -- these should always be used in preference to the backtick for line continuation when applicable, even for strings

Since you've asked, how I'd write it, here is some examples:

"Structured"

function makeOU ($cn, $path)
{
    $Template = 'New-ADOrganizationalUnit {0} -Path "{1}" -ProtectedFromAccidentalDeletion 0'
    $ScriptBlock = [scriptblock]::Create(($Template -f $cn, $path))

    Invoke-Command -ComputerName $server -Credential $Credential -ScriptBlock $ScriptBlock
}

"Splatted"

function makeOU ($cn, $path)
{
    $Template = 'New-ADOrganizationalUnit {0} -Path "{1}" -ProtectedFromAccidentalDeletion 0'
    $ScriptBlock = $Template -f $cn, $path

    $Splat = @{
        ComputerName = $server
        Credential = $Credential
        ScriptBlock = [scriptblock]::Create($ScriptBlock)
    }

    Invoke-Command @Splat
}

"Oneliner"

function makeOU ($cn, $path)
{
    Invoke-Command -ComputerName $server -Credential $Credential -ScriptBlock (
        [scriptblock]::Create(
            ('New-ADOrganizationalUnit {0} -Path "{1}" -ProtectedFromAccidentalDeletion 0' -f $cn, $path)
        )
    )
}

# Or, using parentheses:

function makeOU ($cn, $path)
{
    Invoke-Command -ComputerName (
        $server
    ) -Credential (
        $Credential
    ) -ScriptBlock (
        [scriptblock]::Create(
            ('New-ADOrganizationalUnit {0} -Path "{1}" -ProtectedFromAccidentalDeletion 0' -f $cn, $path)
        )
    )
}
Sign up to request clarification or add additional context in comments.

Comments

2

Well, if you really want to format it that way, try this:

function makeOU ($cn, $path)
{
  $sb = [scriptblock]::Create(
      "New-ADOrganizationalUnit $cn -path (
        `"$path`"
       ) -ProtectedFromAccidentalDeletion 0"
    )

  Invoke-Command -ComputerName $server -Credential $Credential `
    -ScriptBlock $sb
}

2 Comments

Your "if you really want to" makes it sound like I'm doing something grossly anti-idomatic to PS. I'm perfectly willing to believe that so I wonder how you'd write it.
@ChrisNelson Sure, see my other answer.
1

If you know how-to escape inner " double quotes, and you know how-to spread a command on multiple lines using a Grave Accent as an escape character:

  Invoke-Command -ComputerName $server -Credential $Credential `
    -ScriptBlock $sb

then you know how-to do the last in a script block as well: just double the Grave Accent character:

  $sb = [scriptblock]::Create(
      "New-ADOrganizationalUnit $cn -path `"$path`" ``
        -ProtectedFromAccidentalDeletion 0"
    )

1 Comment

I prefer this answer because it makes consistent use of back ticks to escape things which will be evaluated again. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.