1
\$\begingroup\$

On a CredSSP enabled server is a .psm1 script file that gets executed remotely from a client technology. The client passes in a couple execution parameters and the server script returns an object back to the client. This works great but the pattern I've implemented feels clunky. Is there room for improvement?

Client code calling remote server script:

$firstStanza=@{
    a = "Mary had"
    b = "a little"
    c = "lamb"
}

$secondStanza=@{
    d = "its fleece"
    e = "was white"
    f = "as snow"
}

$scriptBlock = {
    Param([Parameter(Mandatory=$true)]$param1,[Parameter(Mandatory=$true)]$param2)
    Import-Module C:\CreateNewObject.psm1
    CombineBothStanzas -firstStanza $param1 -secondStanza $param2
}
$bothStanzasCombined = Invoke-Command -ComputerName serverName.internalDomain.com -ScriptBlock $scriptBlock -ArgumentList $firstStanza,$secondStanza
Write-Output $bothStanzasCombined

Contents of remote script on server c:\CreateNewObject.psm1:

function CombineBothStanzas {
    Param([Parameter(Mandatory=$true)]$firstStanza,[Parameter(Mandatory=$true)]$secondStanza)
    return ($firstStanza + $secondStanza).GetEnumerator() | sort -Property name 
}

Remote server script operation returns this object to the client:

Name                           Value                                              
----                           -----                                          
a                              Mary had                                           
b                              a little                                           
c                              lamb                                               
d                              its fleece                                         
e                              was white                                          
f                              as snow 
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

A couple of things I see, if it is as simple as you suggest. First is the $using: context, where you can use local variables in remote execution. For example, you could remove the parameters from your scriptblock, and not have to pass arguments to the Invoke-Command call by doing this:

$scriptBlock = {
    Import-Module C:\CreateNewObject.psm1
    CombineBothStanzas -firstStanza $using:firstStanza -secondStanza $using:secondStanza
}

Second is that if your .psm1 file has but one purpose, and that is a singular function, why not just make it a script with parameters? Then you don't have to first import it then execute it.

Contents of remote script on server c:\CreateNewObject.ps1:

Param([Parameter(Mandatory=$true)]$firstStanza,[Parameter(Mandatory=$true)]$secondStanza)
return ($firstStanza + $secondStanza).GetEnumerator() | sort -Property name

Putting both of those into use, you end up with something like:

$firstStanza=@{
    a = "Mary had"
    b = "a little"
    c = "lamb"
}

$secondStanza=@{
    d = "its fleece"
    e = "was white"
    f = "as snow"
}

$scriptBlock = {
    . C:\CreateNewObject.ps1 -firstStanza $using:firstStanza -secondStanza $using:secondStanza
}

Invoke-Command -ComputerName serverName.internalDomain.com -ScriptBlock $scriptBlock
\$\endgroup\$
1
  • \$\begingroup\$ Thank you. That is a much more straight-forward approach. \$\endgroup\$
    – Neville
    Commented Dec 19, 2017 at 18:43

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.