6
\$\begingroup\$

Goal:

I am attempting to create a script that would automatically establish a PSSession to a Windows server for implicit remoting.

Problem:

Export-PSSession : Proxy creation has been skipped for the '%' command, because Windows PowerShell could not verify the safety of the command name.
At Z:Somewhere\aScript.ps1:12 char:3
+ Export-PSSession -Session $ServerPS -OutputModule 'First Module' - ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 + CategoryInfo : InvalidData: (:) [Export-PSSession], InvalidOperationException
 + FullyQualifiedErrorId : ErrorSkippedUnsafeCommandName,Microsoft.PowerShell.Commands.ExportPSSessionCommand

Side notes:

A large number of users will use this script to establish PSSessions daily, I am trying to find the most efficient way to get all the users to access these modules - Amodule, Bmodule and Cmodule. Additionally, the script still works despite the above mentioned error.

Here is a sample of my script:

$Server = New-PSSession -ComputerName ServerPS -Authentication Kerberos
Set-Alias -Name go -Value Get-CustomMods -Description 'Gets the modules'
function Get-CustomMods
{
 # Import first module
 Write-Verbose -Message 'Importing First module'
 Invoke-command { import-module 'Amodule.ps1' } -session $ServerPS
 Export-PSSession -Session $Server -OutputModule 'Amodule' -Force -AllowClobber
 # Import second module
 Write-Verbose -Message 'Importing Second Module'
 Invoke-command { import-module 'Bmodule.ps1'} -session $ServerPS
 Export-PSSession -Session $Server -OutputModule 'Bmodule' -Force -AllowClobber
 # Import third module 
 Write-Verbose -Message 'Importing Third Module'
 Invoke-command { import-module 'Cmodule.ps1' } -session $ServerPS
 Export-PSSession -Session $Server -OutputModule 'Cmodule' -Force -AllowClobber
}

Question:

Is there a more effective way to structure/write this script given my goal and problem?

asked Jan 14, 2017 at 20:09
\$\endgroup\$
4
  • \$\begingroup\$ Is this script working or not? I'm not sure. \$\endgroup\$ Commented Jan 14, 2017 at 21:48
  • 1
    \$\begingroup\$ Hello, I mentioned above that the script is still working despite the error. I will make it more noticeable. \$\endgroup\$ Commented Jan 14, 2017 at 21:49
  • 1
    \$\begingroup\$ Oh, I'm sorry, you're right, it's there. I don't know how I couldn't notice it. \$\endgroup\$ Commented Jan 14, 2017 at 21:51
  • \$\begingroup\$ Not a problem! I should have formatted the question better... \$\endgroup\$ Commented Jan 14, 2017 at 21:53

3 Answers 3

3
\$\begingroup\$

I wish I had more to offer but I wanted to add some pointers about the code I do see.

Code Repetition

If you find yourself repeating the same code over and over again you should be asking if there is another way.

Another function

You could easily wrap the block

 # Import first module
 Write-Verbose -Message 'Importing First module'
 Invoke-command { import-module 'Amodule.ps1' } -session $ServerPS
 Export-PSSession -Session $Server -OutputModule 'Amodule' -Force -AllowClobber

into its own function. That way if you need to make some changes they will be more centralized.

function Export-SessionModule{
 param(
 $session,
 $moduleName
 )
 # Import named module
 Write-Verbose -Message "Importing $moduleName module"
 Invoke-command { import-module "$moduleName.ps1" } -session $session
 Export-PSSession -Session $session -OutputModule $moduleName -Force -AllowClobber
}

Splatting

Note that this is meant to be a simple example. Things like parameter typing might be advisable but were omitted for brevity. If functions are overkill for this little script of yours something else to consider would be splatting your parameters that are the same across cmdlet calls.

$exportPSSessionParams = @{
 Session = $session
 Force = $true
 AllowClobber = $true
}
# .....
Export-PSSession -OutputModule 'Amodule' @exportPSSessionParams
# .....
Export-PSSession -OutputModule 'Bmodule' @exportPSSessionParams
# .....
Export-PSSession -OutputModule 'Cmodule' @exportPSSessionParams

Variable Names

You follow the verb-noun convention for your functions which is good.

Your session variable name is a little misleading. You call it $server. I usually see that representing a string with a server name. Since it is a session object it would be clearer if it was named as such. $session at a minimum or even $serverSession if you prefer. This could clash with your $sessionPS which is more reason to make them clear.

Function Declaration

You are supposed to declare your functions before you use them. That being said, you would typically find functions at the beginning of scripts. While the order you have things declared will not be a problem (since it is working) I wanted to be sure that was understood.

If you were to call go after your created the alias it would fail.

Your Problem

Like I said I don't have much to offer here. I would like to point out that I think you scrubbed your code incorrectly since the code in your error does not match your code block.

  • Have you checked on SO for that message already? There are a few different causes although I didn't find an exact match. Admittingly I do not work with modules much.
  • I would debug this by seeing if it is the same module and if perhaps how it is being called is causing some problems. Perhaps being run more than once in a session? (AllowClobber should have fixed that though)
answered Jan 17, 2017 at 2:47
\$\endgroup\$
1
  • \$\begingroup\$ Excellent advice. I implemented this and it works besutifully. \$\endgroup\$ Commented Jan 17, 2017 at 4:33
1
\$\begingroup\$

Let's ask why Windows PowerShell could not verify the safety of the command name, and let's ask which command name considered unsafe? Unfortunately, I can't verify my suspicion about go alias:

Set-Alias -Name go -Value Get-CustomMods -Description 'Gets the modules'

However, I'd remove above command at all, or at least add -Option Constant,ReadOnly as follows:

Set-Alias -Name go -Value Get-CustomMods -Option Constant,ReadOnly -Description 'Gets the modules'
answered Jan 15, 2017 at 2:21
\$\endgroup\$
2
  • \$\begingroup\$ 'Go' is the literal alias for my actual script. Additionally, I have attempted to add '-Option Constant,ReadOnly.' this doesn't remove the error. However, I wanted to know the benefit of keeping such options. And, if it's better practice to remove the alias as you said, or did you mean to chance the '-Name' of the alias. \$\endgroup\$ Commented Jan 15, 2017 at 2:56
  • \$\begingroup\$ With some research I found out what the -Option switch does. \$\endgroup\$ Commented Jan 15, 2017 at 15:46
0
\$\begingroup\$

How about this in everyone's profile.ps1: put the 3 ps1 up on a fileshare / server somewhere, or post a gist on GitHub.

iex ((New-ObjectSystem.Net.WebClient).DownloadString('\\Server\File\Share\Amodule.ps1')
iex ((New-ObjectSystem.Net.WebClient).DownloadString('\\Server\File\Share\Bmodule.ps1')
iex ((New-ObjectSystem.Net.WebClient).DownloadString('\\Server\File\Share\Cmodule.ps1')
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
answered Jan 15, 2017 at 1:29
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.