I\'m developing a custom PowerShell module, which I\'d like to use in context of a remote session to a different computer. The following code (which obviously doesn\'t work)
Here's another approach: Recreate the module in a remote session, without copying any files.
I've made no attempt to cope with dependencies between modules, but this seems to work ok for simple self contained modules. It relies on the module being available in the local session, as this makes determining exports easier, but with a bit of extra work it would also work with a module file.
function Import-ModuleRemotely([string] $moduleName,[System.Management.Automation.Runspaces.PSSession] $session)
{
$localModule = get-module $moduleName;
if (! $localModule)
{
write-warning "No local module by that name exists";
return;
}
function Exports([string] $paramName, $dictionary)
{
if ($dictionary.Keys.Count -gt 0)
{
$keys = $dictionary.Keys -join ",";
return " -$paramName $keys"
}
}
$fns = Exports "Function" $localModule.ExportedFunctions;
$aliases = Exports "Alias" $localModule.ExportedAliases;
$cmdlets = Exports "Cmdlet" $localModule.ExportedCmdlets;
$vars = Exports "Variable" $localModule.ExportedVariables;
$exports = "Export-ModuleMember $fns $aliases $cmdlets $vars;";
$moduleString= @"
if (get-module $moduleName)
{
remove-module $moduleName;
}
New-Module -name $moduleName {
$($localModule.Definition)
$exports;
} | import-module
"@
$script = [ScriptBlock]::Create($moduleString);
invoke-command -session $session -scriptblock $script;
}
Thanks for this thread it was helpfull….
But i actually rewrote the function.
Be aware, that nether the original function in this post or this rewritten function includes module manifest data. So you cant rely on version checks on the module.
function Import-ModuleRemotely {
Param (
[string] $moduleName,
[System.Management.Automation.Runspaces.PSSession] $session
)
Import-Module $moduleName
$Script = @"
if (get-module $moduleName)
{
remove-module $moduleName;
}
New-Module -Name $moduleName { $($(Get-Module $moduleName).Definition) } | Import-Module
"@
Invoke-Command -Session $Session -ScriptBlock {
Param($Script)
. ([ScriptBlock]::Create($Script))
Get-Module
} -ArgumentList $Script
}
What about making scriptblock out of your custom function and sending it off to terget servers using Invoke-command
Import-module YourModule
$s = [scriptblock]::Create($(get-item Function:\Your-ModuleFunction).Definition)
Invoke-Command -ScriptBlock $s -Computername s1,s2,sn
I don't believe this is supported right of the box without any "hacks". The smart move would probably be to put the module on a public location like a fileserver and import it on the server when you need it. Ex:
$session = new-pssession -computerName server01
invoke-command -session $session -scriptblock {
#Set executionpolicy to bypass warnings IN THIS SESSION ONLY
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
#Import module from public location
Import-Module \\fileserver\folders\modulelocation...
<# use function defined in MyCustomModule here #>
}
There were some great comments to the question, and I've spent some time investigating various ways to approach the problem.
To begin with, what I've initially asked for is not possible. I mean, if you go the module way, then the module should be physically present on a target machine to be able to Import-Module
into remote session.
To abstract my question further, I'm trying to create a reusable PowerShell-based framework for the product deployments. It's going to be a push-manner deployments, meaning that we encourage people to run some scripts on a local machine to deploy to some remote server. As far as I investigated the area, there are two possible ways which are friendly to the common sense.
The process to follow:
*.psm1
)PSModulePath
variable to include the new modules locationInvoke-Command -Session $s -ScriptBlock {...}
Import-Module CustomModule
- it will search the CustomModule
on a remote machine and obviously will find itThe following are the reasons to love this approach for:
The following is important to take into consideration:
xcopy
from the shared folder. Besides, the delivery mechanism should support upgrade / downgrade and (preferably) multi-instance installations, but that's more related to my task than to the problem in generalThe process to follow:
Invoke-Command -Session $s -FilePath .\myscript.ps1
to load the functions defined in a script to the remote sessionInvoke-Command -Session $s -ScriptBlock {...}
and refer to your custom functions - they will be there in a sessionThe following are good points of this approach:
Sure, it's not ideal:
Finally, I should say that remote machine still needs to be prepared for the remoting. This is what I mean:
Set-ExecutionPolicy Unrestricted
Enable-PSRemoting