2

I have a need to put a PowerShell script into a variable with double quotes like so. However I am not aware of the correct syntax for this as I see syntax errors with $script variable when I try this.

$script = "Invoke-Command -ComputerName $hostname -Credential $cred -ScriptBlock {Import-Module sqlserver; invoke-sqlcmd -ServerInstance $Using:hostname\MSSQLServer; invoke-sqlcmd "create login [$Using:sqluser] from windows";invoke-sqlcmd "alter server role sysadmin add member [$Using:sqluser]"}"

$runscript = Invoke-VMScript -VM $vm -ScriptText $script -GuestUser $tmpl_user -GuestPassword $tmpl_pass -ToolsWaitSecs 300 
1
  • 2
    Are you hoping to pass the script to Invoke-VMScript as-is? If so, use ' single-quotes instead of double-quotes. If you need to have some of the variables in the string expanded by PowerShell before invocation, you should keep the double-quotes, but make sure you escape the $ in front of any variable that you don't want PowerShell to expand Commented Oct 6, 2021 at 15:26

1 Answer 1

2

Invoke-VMScript -ScriptText accepts only a string containing PowerShell code, and has no support for separately passing arguments to that code.

The implications are:

  • In order to include variable values from the caller's scope you indeed need to use string interpolation (via an expandable string, "..."), as you have attempted.

    • Note that this situationally requires embedded quoting around reference to caller variables whose values may contain spaces or other special characters; e.g.
      "... -Foo '$foo' ...")
  • As Mathias R. Jessen points out, variable references you want to be evaluated on the target machine must have their $ sigil escaped as `$ so as to prevent premature interpolation on the caller's side; e.g. `$Using:sqluser

There's a catch, however:

  • Use of string interpolation imposes limits on what data types may be embedded in the string, as not all data types have string-literal representations that are recognized as the original type.

    • In your case, the caller-side $cred variable contains a [PSCredential] instance, which does not stringify meaningfully (and cannot, for security reasons): it meaninglessly expands to a verbatim string value of System.Management.Automation.PSCredential, i.e. the instance's type name.
      In other words: you cannot pass credentials this way.

    • A potential workaround requires up-front work on the target machine: You can try to save the credentials in encrypted form to a file and then deserialize that file at invocation time via Import-Clixml.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. I am going to try a few options that you noted.

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.