Working with Windows PowerShell 2.0 advanced functionality
hey everyone, today i have a guest poster on my blog. Laurie McKnight from the VMM team will illustrate some of the advanced functionality you can achieve with Script Functions, Script Modules and Binary Modules in PowerShell.
How to save a PS 2.0 advanced function
CAUTION: Methods that work but are **NOT** recommended are included but struck out.
These method are included to clarify that using that method is not appropriate or not recommended.
To distinguish one type of advanced function from others based on file type, the following examples use these (arbitrary) naming conventions:
- ScriptFunction1.ps1 [referred to in text below as a "script-function"]
- ScriptModule1.psm1 [referred to in text below as a "script-module"]
- BinaryModule1.dll [referred to in text below as a "binary-module"]
Type an advanced function directly into a PS Profile file
Location / Action |
PERSONAL PATH and PROFILE: <C>:\Users\<YourAlias>\Documents\WindowsPowerShell\Profile.ps1
Type the advanced function directly into Profile.ps1 (your personal profile file).
|
ALL USERS PATH and PROFILE: <C>:\Windows\System32\WindowsPowerShell\V1.0\Microsoft.PowerShell_profile.ps1
NOTE: PowerShell 2.0 will still use "V1.0" in this path.
Type the advanced function directly into the Microsoft.PowerShell_profile.ps1 (all users profile file).
|
Call an advanced function (.ps1 or .psm1) from within a PS Profile file
Location / Action |
PERSONAL PATH and PROFILE + .ps1 FILE: <C>:\Users\<YourAlias>\Documents\WindowsPowerShell\Profile.ps1 <C>:\Users\<YourAlias>\Documents\WindowsPowerShell\ScriptFunction1.ps1
. .\ScriptFunction.ps1
NOTE: When the script is in the same directory as the profile file, notice that the syntax to use is "dot space dot." The dot followed by a space followed by a second dot and then the script/function name calls the script/function, that is, causes the script/function to act as if the entire advanced function had been typed into the profile file. When you use "dot sourcing," everything you define in the .ps1 file runs in the same shared session state; therefore, variables, functions, etc, are visible globally.
Alternatively, you "dot source" a script by using a dot, then a space, then the complete path as follows:
. C:\MyScripts\MyAdvFunc1.ps1
|
PERSONAL PATH and PROFILE + psm1 FILE -- OK only for informal testing; this is **NOT** the recommended way to store modules: <C>:\Users\<YourAlias>\Documents\WindowsPowerShell\Profile.ps1 <C>:\Users\<YourAlias>\Documents\WindowsPowerShell\ScriptModule1.psm1
Import-Module ScriptModule1.psm1
NOTE: You might assume that the Import-Module command calls the module/function, that is, causes the module/function to act as if the entire module/function had been typed into the profile file. However, modules have their own session state (part of memory that stores things such as values of variables, etc.) and therefore behave differently from the dot sourcing of .ps1 files. In the module case, only those things that you export from the module are visible globally; everything else is private to the module's session state (this is like a C# class). You specify what to export using Export-ModuleMember cmdlet in your .psm1 file. Example: At the end of a .psm1 file named NewDiffDiskVMModlue.psm1 that defines a function named New-DiffVM, after the final "}", you can add the following command: Export-ModuleMember -Function New-DiffVM In the absence of a call to Export-ModuleMember, all commands (functions + cmdlets) are exported by default (i.e. public) and variables and aliases are not exported (i.e. kept private to the module).
NOTE: The Import-Module cmdlet looks for files in the following order:
|
ALL USERS PATH - CAUTION: Not recommended -- not secure!
Do **not** save the advanced function as a script file (.ps1 file) or as a module file (.psm1 file) in the same folder as the all users Microsoft.PowerShell_profile.ps1 and then call it from within the profile file.
This does work if, for example, you want to openly share scripts within an organization, but is a potential security risk if sensitive processes are contained in the scripts.
|
Recommended method for individual advanced functions:
Save an advanced function as a script-module (.psm1) or binary-module (.dll) in a sub-folder under Modules, & then import the module
REQUIRED:
- (1) Add a subfolder under the Modules folder.
- (2) Use the same name for the subfolder and for the (primary) module file.
- (3) Use a separate folder for each module.
OPTIONAL:
- A module manifest (.psd1 file) is optional but strongly recommended for complex modules, especially if more than one .psm1 file (or more than one DLL file) exists.
- If you do include a .psd1 file, its name must be the same as the folder and module file names.
DEFAULT MODULE PATHS:
- PS looks for modules in the default directories if you do not specify the full path to a module. The default value of $env:PSModulePath is:
$home\Documents\WindowsPowerShell\Modules; $pshome\Modules
- You can customize the module path by using the PSModulePath environment variable. For more information, type Get-Help about_Environment_Variables.
Location / Action |
PERSONAL PATH + .psm1 MODULE: <C>:\Users\<YourAlias>\Documents\WindowsPowerShell\Modules\ScriptModule1\ScriptModule1.psm1 [ REQUIRED ] <C>:\Users\<YourAlias>\Documents\WindowsPowerShell\Modules\ScriptModule1\ScriptModule1.psd1 [ OPTIONAL ]
Import-Module ScriptModule1
|
PERSONAL PATH + .dll MODULE: <C>:\Users\<YourAlias>\Documents\WindowsPowerShell\Modules\BinaryModule1\BinaryModule1.dll [ REQUIRED ] <C>:\Users\<YourAlias>\Documents\WindowsPowerShell\Modules\BinaryModule1\BinaryModule1.psd1 [ OPTIONAL ]
Import-Module BinaryModule1
|
ALL USERS PATH + .psm1 MODULE -- Do NOT put your module here unless it is a Windows component (Active Directory, IIS BITS, etc)
Import-Module ScriptModule1
IF YOUR MODULE IS **NOT** A WINDOWS COMPONENT, USE ONE OF THESE METHODS INSTEAD:
https://msdn.microsoft.com/en-us/library/dd878350(VS.85).aspx
|
ALL USERS PATH + .dll MODULE -- Do NOT put your module here unless it is a Windows component (Active Directory, IIS BITS, etc)
Import-Module BinaryModule1
IF YOUR MODULE IS **NOT** A WINDOWS COMPONENT, USE ONE OF THESE METHODS INSTEAD:
https://msdn.microsoft.com/en-us/library/dd878350(VS.85).aspx.
|
Recommended method for a set of advanced functions:
Save a set of advanced functions in a sub-folder under Modules; create a script-module to call the set of functions; & then import the module:
NOTE: The information on this page is **not** about product specific modules.
A product specific module is saved under Program Files, and its path is added to the PSModulePath environment variable. See:
https://msdn.microsoft.com/en-us/library/dd878350(VS.85).aspx
Location / Action |
PERSONAL PATH + FUNCTIONS + .psm1 MODULE: <C>:\Users\<YourAlias>\Documents\WindowsPowerShell\Modules\ScriptModule1\ScriptModule1.psm1 [REQUIRED] <C>:\Users\<YourAlias>\Documents\WindowsPowerShell\Modules\ScriptModule1\ScriptModule1.psd1 [ OPTIONAL ]
NOTE: In this case, it is the .psm1 file name (not the .ps1 file names) that matches the folder name.
<C>:\Users\<YourAlias>\Documents\WindowsPowerShell\Modules\ScriptModule1\Script-Function1.ps1 <C>:\Users\<YourAlias>\Documents\WindowsPowerShell\Modules\ScriptModule1\Script-Function2.ps1 <C>:\Users\<YourAlias>\Documents\WindowsPowerShell\Modules\ScriptModule1\Script-Function3.ps1 <C>:\Users\<YourAlias>\Documents\WindowsPowerShell\Modules\ScriptModule1\Script-Function4.ps1 <C>:\Users\<YourAlias>\Documents\WindowsPowerShell\Modules\ScriptModule1\Script-Function5.ps1
. $psSScriptRoot\ScriptFunction1.ps1 . $psSScriptRoot\ScriptFunction2.ps1 . $psSScriptRoot\ScriptFunction3.ps1 . $psSScriptRoot\ScriptFunction4.ps1 . $psSScriptRoot\ScriptFunction5.ps1
NOTE: Each entry must be on a new line.
Import-Module ScriptModule1
NOTE: This command imports the script-module file (.psm1 file) -AND- all of the script-function files (.ps1 files) listed in the script-module file, all in one step.
LATER: If you add another script-function to this sub-folder later, use the following command to reload the module with the new file: Import-Module ScriptModule1 -Force
|
ALL USERS PATH + FUNCTIONS + .psm1 MODULE -- Do NOT put your module here unless it is a Windows component (Active Directory, IIS BITS, etc)
NOTE: In this case, it is the .psm1 file name (not the .ps1 file names) that matches the folder name.
. $psSScriptRoot\ScriptFunction1.ps1 . $psSScriptRoot\ScriptFunction2.ps1 . $psSScriptRoot\ScriptFunction3.ps1 . $psSScriptRoot\ScriptFunction4.ps1 . $psSScriptRoot\ScriptFunction5.ps1
NOTE: Each entry must be on a new line.
Import-Module ScriptModule1
NOTE: This command imports the script-module file (.psm1 file) -AND- all of the script-function files (.ps1 files) listed in the script-module file, all in one step.
LATER: If you add another script-function to this sub-folder later, use the following command to reload the module with the new file: Import-Module ScriptModule1 -Force
IF YOUR MODULE IS **NOT** A WINDOWS COMPONENT, USE ONE OF THESE METHODS INSTEAD:
https://msdn.microsoft.com/en-us/library/dd878350(VS.85).aspx.
|
For more information, type:
- Get-Help about_Scripts
- Get-Help about_Scopes
- Get-Help about_Modules
- Get-Help about_Profiles
- Get-Help about_Functions
- Get-Help about_Functions_Advanced
- Get-Help about_Functions_Advanced_Methods
- Get-Help about_Functions_Advanced_Parameters
- Get-Help about_Functions_CmdletBindingAttribute