330
CHAPTER 9
U
SING
AND
AUTHORING
MODULES
load the module and stop looking
}
else
{
continue with the next path element
}
}
foreach ($pathElement in $ENV:PSModulePath) 
{
if (the specified module name has a known extension)
{
Join the path element and module base name and name
to create a new path
if (the composite path exists)
{
load the module and stop looking
}
else
{
continue with the next path element
}
}
else
{
foreach ($extension in ".psd1",".psm1", ".dll"
{
Join the path element and module base name, module name
and extension.
if (the composite path exists)
{
load the module and stop looking
}
else
{
continue with the next path element
}
}
if (no module was found) 
{
generate an error 
}
As you can see from the number of steps in the algorithm, the search mechanism used 
in loading a module is sophisticated but also a bit complicated. Later on we’ll look at 
ways to get more information about what’s being loaded.
Now that you know what modules are available, you need to be able to load them. 
You’ll learn how next.
Reorder pdf page - re-order PDF pages in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
Support Customizing Page Order of PDF Document in C# Project
reorder pdf pages; move pdf pages in preview
Reorder pdf page - VB.NET PDF Page Move Library: re-order PDF pages in vb.net, ASP.NET, MVC, Ajax, WinForms, WPF
Sort PDF Document Pages Using VB.NET Demo Code
change page order in pdf file; rearrange pdf pages in reader
W
ORKING
WITH
MODULES
331
9.3.2
Loading a module
Modules are loaded using the 
Import-Module
cmdlet. The syntax for this cmdlet is 
shown in figure 9.2. As you can see, this cmdlet has a lot of parameters, allowing it to 
address a wide variety of scenarios. We’ll look at the basic features of this cmdlet in 
this section and cover some obscure features in later sections of this chapter.
This cmdlet has a lot of parameters. We’ll cover many of them in the next sec-
tions. Some of the more advanced parameters will be covered in chapters 10 and 11.
Loading a module by name
The most common way to load a module is to specify its name. You saw how to find 
modules using the 
Get-Module
cmdlet in the previous section. One of the modules you 
discovered was 
PSDiagnostics
. Let’s use 
Import-Module
to load this module now:
PS (1) > Import-Module psdiagnostics
By default, nothing is output when you load a module. This is as expected and desir-
able because when you’re loading library modules in scripts or in your profile, you 
don’t want chattiness. Unless there’s an error, loading a module should be silent. 
When you do want to see what was loaded, use 
Get-Module
:
PS (2) > Get-Module
ModuleType Name                      ExportedCommands 
---------- ----                      ----------------
Script     psdiagnostics             {Enable-PSTrace, Enable-...
Import-Module 
[-Name] <String[]>
-Assembly <Assembly[]>
-ModuleInfo <PSModuleInfo[]>
[-Global] 
[-Prefix <String> ]
[-Function <String[]> ]
[-Cmdlet <String[]> ]
[-Variable <String[]> ]
[-Alias <String[]> ]
[-Force] 
[-PassThru ]
[-AsCustomObject ]
[-Version <Version> ]
[-ArgumentList <Object[]> ]
[-DisableNameChecking]
[-Verbose]
Specifies module to load
by name, assembly object, 
or PSModuleInfo object
Names of members to
import from module
Cmdlet name
Returns PSModuleInfo
object for module being loaded
Loads into global
scope instead of 
module ccope
Prefix for imported
module members
Forces module
to be reloaded
Displays imports and exports
on verbose stream
Disables checking verb used
in command names
Version of
module to load
List of arguments passed
to module script
Returns custom object instead
of PSModuleInfo object
Figure 9.2 The syntax for the 
Import-Module
cmdlet. This cmdlet is used to import mod-
ules into the current module context or the global context if 
-Global
is specified.
C# TIFF: How to Reorder, Rearrange & Sort TIFF Pages Using C# Code
C# TIFF Page Sorting Overview. RasterEdge XDoc.Tiff for .NET is powerful enough to enable C# users to reorder and rearrange multi-page Tiff file flexibly.
reorder pdf page; how to move pages around in a pdf document
C# PDF: C# Code to Process PDF Document Page Using C#.NET PDF
C# PDF Page Processing: Sort PDF Pages - online C#.NET tutorial page for how to reorder, sort, reorganize or re-arrange PDF document files using C#.NET code.
pdf reverse page order online; how to rearrange pages in a pdf file
332
CHAPTER 9
U
SING
AND
AUTHORING
MODULES
This shows that you have one module loaded named 
PSDiagnostics
. This output is 
substantially abbreviated when displayed as a table, so let’s use 
Format-List
to see 
the details of the loaded modules just as you did when you were exploring the on-disk 
modules:
PS (3) > Get-Module | fl
Name              : psdiagnostics 
Path              : C:\Windows\system32\WindowsPowerShell\v1.0\M
odules\psdiagnostics\PSDiagnostics.psm1 
Description       : 
ModuleType        : Script 
Version           : 1.0.0.0 
NestedModules     : {}
ExportedFunctions : {Disable-PSTrace, Disable-PSWSManCombinedTra
ce, Disable-WSManTrace, Enable-PSTrace...} 
ExportedCmdlets   : {}
ExportedVariables : {}
ExportedAliases   : {}
Let’s examine this output for a minute. The most obvious thing to notice is that the 
ExportedFunctions
member in the output is no longer empty. When you load a mod-
ule, you can finally see all the available exported members. The other thing to notice 
is that the module type has been changed from 
Manifest
to 
Script
. Again, the details 
of the implementation of the module aren’t known until after the module has been 
loaded. We’ll cover module manifests and the details on module types in chapter 10. 
To  see  what commands  were  imported,  you  can  use 
Get-Command
with the 
-Module
option:
PS (5) > Get-Command -Module psdiagnostics
CommandType     Name                     Definition 
-----------     ----                     ----------
Function        Disable-PSTrace          ... 
Function        Disable-PSWSManCombin... ... 
Function        Disable-WSManTrace       ... 
Function        Enable-PSTrace           ... 
Function        Enable-PSWSManCombine... ... 
Function        Enable-WSManTrace        ... 
Function        Get-LogProperties        ... 
Function        Set-LogProperties        ... 
Function        Start-Trace              ... 
Function        Stop-Trace               ...
This list matches the list of exports from the module, as you can see with 
Get-Module
:
PS (6) > (Get-Module psdiag*).exportedfunctions
Key                              Value 
---                              -----
Disable-PSTrace                  Disable-PSTrace 
Disable-PSWSManCombinedTrace     Disable-PSWSManCombinedTrace
VB.NET PDF: VB.NET Guide to Process PDF Document in .NET Project
It can be used to add or delete PDF document page(s), sort the order of PDF pages, add image to PDF document page and extract page(s) from PDF document in VB
how to rearrange pages in pdf using reader; reorder pdf pages online
.NET Multipage TIFF SDK| Process Multipage TIFF Files
are easily to access, extract, swap, reorder, insert, mark up and delete pages in any multi-page TIFF images upload to SharePoint and save to PDF documents
reorder pages in pdf; change pdf page order online
W
ORKING
WITH
MODULES
333
Disable-WSManTrace               Disable-WSManTrace 
Enable-PSTrace                   Enable-PSTrace 
Enable-PSWSManCombinedTrace      Enable-PSWSManCombinedTrace 
Enable-WSManTrace                Enable-WSManTrace 
Get-LogProperties                Get-LogProperties 
Set-LogProperties                Set-LogProperties 
Start-Trace                      Start-Trace 
Stop-Trace                       Stop-Trace
Let’s remove this module using the 
Remove-Module
cmdlet and look at other ways 
you can specify which module to load:
PS (7) > Remove-Module PSDiagnostics
Again the command completes with no output. 
In addition to loading a module by name, you can also load it by path, again par-
alleling the way executables work. Let’s do this with the 
PSDiagnostics
module. 
You saw the path in the output of the earlier example. We’ll use this path to load the 
module. Because this  is a system module, it’s loaded  from the PowerShell install 
directory. This means that you can use the built-in 
$PSHOME
variable in the path: 
PS (8) > Import-Module $PSHOME/modules/psdiagnostics/psdiagnostics
Call 
Get-Module
verify that it has been loaded
PS (9) > Get-Module
ModuleType Name                      ExportedCommands 
---------- ----                      ----------------
Script     psdiagnostics             {Enable-PSTrace, Enable-...
and there it is.
By loading a module using a full path, you know exactly which file will be pro-
cessed. This can be useful when you’re developing modules, as you’ll see in section 9.4. 
Let’s remove this module again as we move on to the next example:
PS (7) > Remove-Module PSDiagnostics
Tracing module loads with -Verbose
So far you’ve allowed the modules to be loaded without caring about the details of 
what’s happening. This is fine as long as everything works, but remember how com-
plex the module search algorithm was. When you get into more complex scenarios 
where you’re loading multiple modules, it’s useful to see what’s happening. You can 
do this by specifying the 
-Verbose
flag:
PS (15) > Import-Module psdiagnostics -Verbose 
VERBOSE: Loading module from path 
'C:\Windows\system32\WindowsPowerShell\v1.0\Modules\psdiagnostic 
s\psdiagnostics.psd1'.
VERBOSE: Loading module from path 
'C:\Windows\system32\WindowsPowerShell\v1.0\Modules\psdiagnostic 
s\PSDiagnostics.psm1'.
VB.NET PDF: Create PDF Document Viewer in C#.NET for Document
Support navigating to the previous or next page of the PDF document; Able to insert, delete or reorder PDF document page in VB.NET document viewer;
how to move pages within a pdf document; how to move pages in pdf files
VB.NET PowerPoint: Sort and Reorder PowerPoint Slides by Using VB.
Sort and Reorder PowerPoint Slides Range with VB.NET PPT PPT Page Extracting. dedicated to provide powerful & profession imaging controls, PDF document, image
move pages in pdf reader; rearrange pdf pages
334
CHAPTER 9
U
SING
AND
AUTHORING
MODULES
VERBOSE: Importing function 'Disable-PSTrace'.
VERBOSE: Importing function 'Disable-PSWSManCombinedTrace'. 
VERBOSE: Importing function 'Disable-WSManTrace'.
VERBOSE: Importing function 'Enable-PSTrace'.
VERBOSE: Importing function 'Enable-PSWSManCombinedTrace'. 
VERBOSE: Importing function 'Enable-WSManTrace'.
VERBOSE: Importing function 'Get-LogProperties'.
VERBOSE: Importing function 'Set-LogProperties'.
VERBOSE: Importing function 'Start-Trace'.
VERBOSE: Importing function 'Stop-Trace'. 
All of the output that begins with 
VERBOSE:
is generated when the 
-Verbose
flag is 
specified. It shows two things: the path to the module file and a list of all members (in 
this case, functions) being imported into your session. This is pretty straightforward 
with a simple scenario, but you’ll see that it can become much more complicated 
when we get to nested modules in section 9.4.6.
Imports and Exports
So far, you’ve defaulted to loading everything that a module exports into your session. 
You don’t have to do that—and there are cases where you don’t want to do it. Import-
ing too many commands clutters up your session and makes it hard to find what 
you’re looking for. To avoid this, you can control what gets imported by using the 
-Function
-Cmdlet
-Alias
, and 
-Variable
parameters on 
Import-Module
. As 
you’d expect, each of these parameters controls a particular type of import from the 
module. You’ve seen all the command types previously as well as PowerShell variables. 
The 
PSDiagnostics
module only exports functions, so you can use that feature to 
restrict what gets loaded. Say you only wanted to load 
Enable-PSTrace
. Here’s what 
this would look like:
PS (12) > Import-Module  psdiagnostics -Verbose -Function Enable-
PSTrace 
VERBOSE: Loading module from path 
'C:\Windows\system32\WindowsPowerShell\v1.0\Modules\psdiagnostic 
s\psdiagnostics.psd1'.
VERBOSE: Loading module from path 
'C:\Windows\system32\WindowsPowerShell\v1.0\Modules\psdiagnostic 
s\PSDiagnostics.psm1'.
VERBOSE: Importing function 'Enable-PSTrace'.
PS (13) > get-command -module psdiagnostics
CommandType     Name                     Definition 
-----------     ----                     ----------
Function        Enable-PSTrace           ...
In the verbose output, you see that only 
Enable-PSTrace
was imported into your 
session.
Now you know how to avoid creating clutter in your session. But what if it’s too 
late and you already have too much stuff loaded? You’ll learn how to fix that next.
C# PDF Page Rotate Library: rotate PDF page permanently in C#.net
PDF document page, it is also featured with the functions to merge PDF files using C# .NET, add new PDF page, delete certain PDF page, reorder existing PDF
reorder pages in a pdf; reordering pages in pdf
VB.NET TIFF: VB.NET Sample Code to Process & Manage TIFF Page
TIFF page, and sort & reorder TIFF pages from VB.NET programming, this TIFF page processing control powerful & profession imaging controls, PDF document, image
rearrange pdf pages online; pdf change page order online
W
ORKING
WITH
MODULES
335
9.3.3
Removing a loaded module
Because your PowerShell session can be long running, there may be times when you 
want to remove a module. As you saw earlier, you do this with the 
Remove-Module 
cmdlet.
NOTE
Typically, the only people who remove modules are those who 
are  developing  the  module in question or those  are  working  in  an 
application environment that’s encapsulating various stages in the pro-
cess as modules. A typical user rarely needs to remove a module. The 
PowerShell team almost cut this feature because it turns out to be quite 
hard to do in a sensible way.
The syntax for 
Remove-Module
is shown in figure 9.3.
Figure 9.3 The syntax for 
Remove-Module
. Note that this command doesn’t take wildcards.
When a module is removed, all the modules it loaded as nested modules are also 
removed from the global module table. This happens even if the module was explicitly 
loaded at the global level. To illustrate how this works, let’s take a look at how the mod-
ule tables are organized in the environment. This organization is shown in figure 9.4.
First let’s talk about the global module table. This is the master table that has ref-
erences to all the modules that have been loaded either explicitly or implicitly by 
another module. Any time a module is loaded, this table is updated. An entry is also 
made in the environment of the caller. In figure 9.4, modules 1 and 3 are loaded
Remove-Module 
[-Name] <String[]>
[-ModuleInfo] <PSModuleInfo[]>
[-Force]
[-Verbose] 
Lists all modules instead
of just default set
Name or PSModuleInfo
identifying module 
to remove
Cmdlet name
Forces module to be removed
even if used by other modules  
Global module table
Global
environment
Module1
Module3
Module2
Figure 9.4 How the 
module tables are orga-
nized. The global module 
table holds a reference 
to all loaded modules. 
Each module in turn has 
a reference to the mod-
ules it has loaded.
336
CHAPTER 9
U
SING
AND
AUTHORING
MODULES
from the global module environment, so there are references from the top-level mod-
ule table. Module1 loads Module2, causing a reference to be added the global module 
table and the private module table for Module1. Module2 loads Module3 as a nested 
module. Because Module1 has already been loaded from the global environment, no 
new entry is added to the global module table, but a private reference is added to the 
module table for Module2.
Now you’ll remove Module3 from the global environment. The updated arrange-
ment of modules is shown in figure 9.5.
Next, you’ll update Module3 and reload it at the top level. The final arrangement 
of modules is shown in figure 9.6.
Global module table
Global
environment
Module1
Module3
Module2
Figure 9.5 How the module tables are organized after Module3 is removed at 
the top level. The global module table no longer has a reference to Mo-dule3, 
but the local module table for Module2 still has a link to that object.
Global module table
Global
environment
Module1
Module3
(original)
Module2
Module3
(new)
Figure 9.6 How the module tables are organized when the revised Module3 
is loaded at the top level. The global module table now has a reference to the 
new Module3, but the local module table for Module2 still has a link to the 
original Module3. 
W
RITING
SCRIPT
MODULES
337
In the final arrangement of modules in figure 9.6, there are two versions of Module3 
loaded into the same session. Although this is extremely complicated, it permits mul-
tiple versions of a module to be loaded at the same time in the same session, allowing 
different modules that depend on different versions of a module to work at the same 
time. This is a pretty pathological scenario, but the real world isn’t always tidy. Even-
tually you do have to deal with things you’d rather ignore, so it’s good to know how.
How exported elements are removed
With an understanding of how modules are removed, you also need to know how the 
imported members are removed. There are two different flavors of member removal 
behavior depending on the type of member you’re removing. Functions, aliases, and 
variables have one behavior. Cmdlets imported from binary modules have a slightly 
different behavior. This is an artifact of the way the members are implemented. Func-
tions, aliases, and variables are data structures that are dynamically allocated and so can 
be replaced. Cmdlets are backed by .
NET
classes, which can’t be unloaded from a ses-
sion because .
NET
doesn’t allow the assemblies containing these classes to be unloaded. 
Because of this, the implementation of the cmdlet table depends on hiding or shadow-
ing a command when there’s a name collision when importing a name from a module. 
For the other member types, the current definition of the member is replaced. So why 
does this matter? It doesn’t matter at all until you try to remove a module. 
If you remove a module that has imported cmdlets, causing existing cmdlets to be 
shadowed, when the module is removed the previously shadowed cmdlets become 
visible again. But when you remove a module importing colliding functions, aliases, 
or variables, because the old definitions were overridden instead of shadowed, the 
definitions are removed.
Okay, this has gotten a bit heavy. Let’s move on to something more creative and 
exciting. In section 9.4, you’ll finally start writing your own modules. 
9.4
W
RITING
SCRIPT
MODULES
In this section we’ll start writing modules instead of just using them. For now, we’ll 
limit our coverage to script modules. This is because script modules are written in the 
PowerShell language—something you’re familiar with by now. In section 9.5, we’ll 
expand our coverage to include binary modules, which requires dabbling with C#. 
When showing you how to write script modules, we’ll also explain how script 
modules work in more detail. Let’s start by describing what a script module is. A 
script module is a file that contains PowerShell script text with a .psm1 extension 
instead of a .ps1 extension. In other words, a PowerShell script module is just a script 
with a different extension.
NOTE
Because a script module is a form of script, it obeys execution 
policy just like a script. So, before you can load a script module, you’ll 
need to change the execution policy to be 
RemoteSigned
as a mini-
mum, as described in section 8.1.1.
338
CHAPTER 9
U
SING
AND
AUTHORING
MODULES
Is it as simple as that? Well, almost. Let’s walk through an example where you convert 
a script into a module and see what changes during the process.
9.4.1
A quick review of scripts
You’re going to write a short script to work with in this conversion exercise. This 
script is indented to implement a simple counter. You get the next number from the 
counter by calling 
Get-Count
and you reset the sequence using the 
Reset-Count 
command. Here’s what the script looks like:
PS (STA) (27) > Get-Content counter.ps1 
$script:count = 0 
$script:increment = 1
function Get-Count 
{
return $script:count += $increment 
}
function Reset-Count 
{
$script:count=0
setIncrement 1 
}
function setIncrement ($x) 
{
$script:increment = $x 
}
As you can see, this script defines the two functions we mentioned, 
Get-Count
and 
Reset-Count
. But it also defines a number of other things that aren’t part of the 
specification:  a  helper  function, 
setIncrement
 and  two  script-level  variables, 
$count
and 
$increment
. These variables hold the state of the counter. Obviously 
just running the script won’t be useful as the commands are defined at the script 
scope and are removed when the script exits. Instead, you’ll dot-source the script to 
load the script members into your environment:
PS {2) > . .\counter.ps1 
PS {3) >
This  creates the  elements  without  showing anything  (which is what  you  want a 
library to do in most cases.) Now manually verify that you got what you intended:
PS {3) > Get-Command *-count
CommandType     Name                    Definition 
-----------     ----                    ----------
Function        Get-Count               ... 
Function        Reset-Count             ...
W
RITING
SCRIPT
MODULES
339
The functions are there so you can try them out. Start with 
Get-Count
:
PS (4) >     Get-Count 
PS (5) > Get-Count 
2
Each  call to 
Get-Count
returns the next number in the sequence. Now use the 
Reset-Count
command
PS (6) > Reset-Count
and call 
Get-Count
to verify that the count has been reset:
PS (7) > Get-Count 
1
Okay, great. But what about the other private members in the script? Using 
Get-
Command
you see that the 
setIncrement
function is also visible:
PS (8) > Get-Command setIncrement
CommandType     Name                    Definition 
-----------     ----                    ----------
Function        setIncrement            param($x)...
And you can even call it directly:
PS (9) > setIncrement 7 
PS (10) > Get-Count 
PS (11) > Get-Count 
15
Because this function was supposed to be a private implementation detail, the fact 
that it’s publicly visible isn’t desirable. Likewise, you can also get at the state variables 
you created:
PS (12) > Get-Variable count, increment
Name                           Value 
----                           -----
count                          15 
increment                      7
The problem with this is clear: 
$count
isn’t a unique name so the chance of it collid-
ing with a similarly named variable from another script is high. This lack of isolation 
between scripts makes using dot-sourcing a fragile way to build libraries.
Finally, let’s try to remove this script, emulating what you’ve been doing with 
Remove-Module
. This turns out to be quite complicated. You end up having to write 
a command that looks like this:
PS (13) > Remove-Item -Verbose  variable:count, 
>>> variable:increment,function:Reset-Count,
Documents you may be interested
Documents you may be interested