Modules

A module is a package that can contain Windows PowerShell cmdlets, aliases, functions, variables, type/format XML, help  les, other scripts, and even providers. In short, a Windows PowerShell module can contain the kinds of things that you might put into your profile.

There are several advantages of modules over snap-ins:

■  Anyone who can write a Windows PowerShell script can create a module.

■  To install a module, you do not need to write a Windows Installer package.

■  To install a module, you do not have to have administrator rights.

There are two locations for windows Powershelgl modules: user’s home directory, Powershell home directory. These locations are defined in $env:psmodulepath. You can add additional default module path location by editing this variable. Note that the modules directory in the User’s home directory is not present until we manually create it (we will create it later), the module directory in the PowerShell home directory exist by default.

The sequence the powershell to search the module is : user’s module directory first, powershell home directory second.

Listing available modules

The PS modules exist in two states: loaded and unloaded.

  • List all loaded modules: Get-module, two basic modules exist in powershell, microsoft.Powershell.management and Microsoft.PowerShell.Utility modules.
  • List all loaded and unloaded modules: get-module -ListAvailable
Loading modules (Import-Module)

If the module exists, the Import-Module cmdlet completes without displaying any information.

 To see the functions exposed by the module, you can use the Get-Command -module <modulename> command.

The one problem with using the Get-Module cmdlet is that it truncates the exportedcommands property, only part of the commands show (the truncate behavior is controlled by the value assigned to the $formatEnumeration automatic variable).

ModuleType Name                     ExportedCommands              


---------- ----                     ---------------- 

Manifest   netconnection            {Get-NetConnectionProfile, Set-Net...



The easy solution to this problem is to pipeline the resulting psmoduleinfo object to the Select-Object cmdlet and expand the exportedcommands property.

PS C:\> Get-Module net* | select -ExpandProperty *comm*

The *comm* is unique enough to identify the exportedcommands.

Note: In Windows PowerShell 2.0, if a wildcard pattern matches more than one module name, the  rst matched module loads and the remaining matches are ignored. This leads to inconsistent and unpredictable results. Therefore, Windows PowerShell 3.0 changes this behavior to generate an error when a wildcard pattern matches more than one module name.
Creating a Per-user modules folder

We are going to create a function named Copy-Module([string]$name) to create a module folder and copy modules from a known folder “c:\fso” to this new created folder, where $name is the fullname(including path) of the module in c:\fso.

We break the procedure into these steps:

Step1. Test the OS version, determine the module path.

User’s modules directory is in a different location depending on the version of the operating system. On Windows XP and Windows Server 2003, the user’s modules folder is in the My Documents folder, and on Windows Vista and above, the user’s modules folder is in the Documents folder under the user’s profile folder. Powershell 3.0 does not install on Windows Vista or below, so don’t need to check the modules folder.

Step2. Create the module folder:

Once we have determined the OS version and modules folder path, it’s time to determine if the module folder exist or not. We can use test-path cmdlet to test the existence of modules folder, and use new-item to create the folder if it does not exist:

Function Test-ModulePath
{
 $VistaPath = "$env:userProfile\documents\WindowsPowerShell\Modules"

 $XPPath =  "$env:Userprofile\my documents\WindowsPowerShell\Modules"

 if ([int](Get-OperatingSystemVersion).substring(0,1) -ge 6)

{
if(-not(Test-Path -path $VistaPath))
{
New-Item -Path $VistaPath -itemtype directory | Out-Null

       } #end if

   } #end if

Else {

if(-not(Test-Path -path $XPPath)) {

New-Item -path $XPPath -itemtype directory | Out-Null } #end if

   } #end else

} #end Test-ModulePath

Out-Null: Hides the output instead of sending it down the pipeline or displaying it.

Step3. Child folder for the module:

Once we have created the modules folder, it’s time to create a child folder. A module installs into a folder that has the same name as the module itself. The name of the module is the name of the folder. For the module to be valid, it needs a file of the same name with either a  .psm1 or .psd1 extension.

Before creating the child folder, we need to get the path of the modules folder:

The value of the PSModulePath environmental variable is a string, not an array. You can test it by command:

PS C:\>$env:PSModulePath

C:\Users\frank\Documents\WindowsPowerShell\Modules;C:\Program Files\WindowsPowerShell\Modules;C:\Windows\system32\WindowsPow
erShell\v1.0\Modules\

So if you want to get the first path “C:\Users\frank\Documents\WindowsPowerShell\Modules”, using of $env:psmodulePath[0] is wrong, which result in only letter C.

So you need to split the string upon semicolons, and pass them to an array. By default, the system.string class separate string by space, so you need to tell the method upon which sign to separate the string.

$arryModulePath=$env:PSModulePath.split(";")
$arryModulePath

$userpath=$arryModulePath[0]
"User's modules folder: "+$arryModulePath[0]

the result will be:

C:\Users\frank\Documents\WindowsPowerShell\Modules
C:\Program Files\WindowsPowerShell\Modules
C:\Windows\system32\WindowsPowerShell\v1.0\Modules\

User's modules folder: C:\Users\frank\Documents\WindowsPowerShell\Modules

Then we can get the child path by adding $userpath and module name ( because the child folder’s name is same as the module name).

We can use the join-path cmdlet to do this job, and .basename property to get the module’s file name without the file extension. Recall that the $name is the fullname(including path) of the module in c:\fso. We can get the target path of the module:

$ModulePath = Join-Path -path $userPath `

              -childpath (Get-Item -path $name).basename

And then create the child folder:

New-Item -path $modulePath -itemtype directory | Out-Null

Step4. Copy the modules to the child folders

Copy-Item -path $name -destination $ModulePath | Out-Null

 <<The whole script:>>
Copy-Modules.ps1 Function Get-OperatingSystemVersion { (Get-WmiObject -Class Win32_OperatingSystem).Version } #end Get-OperatingSystemVersion Function Test-ModulePath {  $VistaPath = "$env:userProfile\documents\WindowsPowerShell\Modules"  $XPPath =  "$env:Userprofile\my documents\WindowsPowerShell\Modules"  if ([int](Get-OperatingSystemVersion).substring(0,1) -ge 6) { if(-not(Test-Path -path $VistaPath)) { New-Item -Path $VistaPath -itemtype directory | Out-Null        } #end if    } #end if Else { if(-not(Test-Path -path $XPPath)) { New-Item -path $XPPath -itemtype directory | Out-Null } #end if    } #end else } #end Test-ModulePath Function Copy-Module([string]$name) { $UserPath = $env:PSModulePath.split(";")[0] $ModulePath = Join-Path -path $userPath ` -childpath (Get-Item -path $name).basename New-Item -path $modulePath -itemtype directory | Out-Null Copy-Item -path $name -destination $ModulePath | Out-Null } #***Entry point To script*** Test-ModulePath Get-ChildItem -Path C:\fso -Include *.psm1,*.psd1 -Recurse | ForEach-Object { Copy-Module -name $_.fullname }
Creating a module drive

An easy way to work with modules is to create a couple of Windows PowerShell drives using the  lesystem provider.

To create a Windows PowerShell drive for the user module location, you use the New-PSDrive cmdlet, specify a name, such as mymods, use the  lesystem provider, and obtain the root location from the $PSModulePath environmental variable by using the split method from the .NET Framework String class.

E.g.  create a User’s modules folder:

PS C:\> New-PSDrive -Name mymods -PSProvider filesystem -Root ($env:PSModulePath.Split(";")[0])

Then you can treat it like a C: , D: drive, if you want to work in your User module path for a long time,  it saves a lot of typing by using  cd mymods: command.

Because you are running the commands inside a script, the new PowerShell drives by default will live within the script scope. Once the script ends, the script scope goes away. This means the Windows PowerShell drives will not be available once the script ended—which would defeat your purposes in creating them in the  first place. You can add -scope Global option to prevent this.

New-PSDrive -Name mymods -PSProvider filesystem -Root ($env:PSModulePath.Split(";")[0]) -scope Global
Module dependencies

One problem with using modules is you now have a dependency to external code, and this means that a script that uses the module must have the module installed.

Windows PowerShell 3.0 adds additional capabilities to the #requires statement. The #requires statement can check for Windows PowerShell version, modules, snap-ins, and even module and snap-in version numbers.

Central share

Using a module from a central  file share is no different from using a module from one of the two default locations.

keep in mind a couple of things: The  first is that a Windows PowerShell module is basically a script—in our particular application. If the script execution policy is set to the default level of Restricted, an error will be generated—even if the logged-on user is an administrator. Even if the execution policy is set to Restricted on a particular machine, you can always run a Windows PowerShell script (or module) if you start Windows PowerShell with the bypass option.

One of the really cool uses of a shared module is to permit centralization of Windows PowerShell profiles for networked users.

Creating a module

The easiest way to create a module is to use functions you have previously written. One of the first things to do is to locate the functions you wish to store in the module.

People usually place together related functions that you will more than likely want to use in a single session.

The steps to create, install and import a module:

1. Place functions into a text  file and save the  file with a .psm1 extension.

2. Copy the newly created module containing the functions to the modules directory. Use the

Copy-Modules.ps1 script to do this.

3. Obtain a listing of available modules by using the Get-Modules cmdlet with the -ListAvailable switched parameter.

4. Optionally, import modules into your current Windows PowerShell session by using the Import-Module cmdlet.

5. See what commands are available from the newly created module by using the Get-Command cmdlet with the -module parameter.

6. Use Get-Help to obtain information about the imported functions.

7. Use the functions like you would use any other cmdlet.