April 5th, 2013

How to Remove a Loaded Module

Doctor Scripto
Scripter

Summary: Bruce Payette talks about how to remove a module that has been loaded into your Windows PowerShell environment.

Microsoft Scripting Guy, Ed Wilson, is here. This week we will not have our usual PowerTip. Instead we have excerpts from seven books from Manning Press. In addition, each blog will have a special code for 50% off the book being excerpted that day. Remember that the code is valid only for the day the excerpt is posted. The coupon code is also valid for a second book from the Manning collection.

This excerpt is from Windows PowerShell in Action
  By Bruce Payette

Photo of book cover

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 in this blog, which is based on Chapter 9 of Windows PowerShell in Action, Second Edition.

One of the unique features that Windows PowerShell modules offer is the idea of a composite management application. This is conceptually similar to the idea of a web mashup, which takes an existing service and tweaks it or layers on top of it to achieve a more specific purpose. The notion of management mashups is important as we move into the era of “software+services” (or “clients+clouds,” if you prefer).

Low operating costs make hosted services attractive. The issue is how you manage all these services, especially when you need to delegate administrative responsibilities to slices of the organization.

For example, you might have each department manage its user resources such as mailboxes, customer lists, and web portals. To do this, you need to slice the management interfaces and republish them as a single coherent management experience.

Sounds like magic, doesn’t it? Well, much of it still is, but Windows PowerShell modules can help because they allow you to merge the interfaces of several modules and republish only those parts of the interfaces that need to be exposed.

Removing a loaded module

Modules are loaded by using the Import-Module cmdlet. The syntax for this cmdlet is shown in the following screenshot. As you can see, this cmdlet has a lot of parameters, allowing it to address a wide variety of scenarios.

Image of syntax

Because your Windows PowerShell session can be long running, there may be times when you want to remove a module. 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 who are working in an application environment that’s encapsulating various stages in the process as modules. A typical user rarely needs to remove a module. The Windows PowerShell team almost cut this feature because it turns out to be quite hard to do in a sensible way.

Here is the syntax for Remove-Module:

Image of syntax

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 module tables are organized in the environment. This organization is shown here.

Image of module arrangement

First let’s talk about the global module table. This is the master table that has references to all the modules that have been loaded 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 the following image, Module1 and Module3 are loaded from the global module environment, so there are references from the top-level module 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. You’ll remove Module3 from the global environment. The updated arrangement of modules is shown here.

Image of module arrangement

Next, you’ll update Module3 and reload it at the top level. The final arrangement of modules is shown here.  

Image of module arrangement

In the final arrangement of modules in the previous image, there are two versions of Module3 loaded into the same session. Although this is extremely complicated, it permits multiple 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. Eventually 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 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. Functions, aliases, and variables are data structures that are dynamically allocated and can be replaced. Cmdlets are backed by .NET classes, which can’t be unloaded from a session because .NET doesn’t allow the assemblies that contain these classes to be unloaded. Because of this, the implementation of the cmdlet table depends on hiding or shadowing 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 that has imported colliding functions, aliases, or variables (because the old definitions were overridden instead of shadowed), the definitions are removed.

Modules are manipulated, managed, and imported by using cmdlets in Windows PowerShell. Unlike many languages, no special syntax is needed. Modules are discovered, in memory and on disk, by using the Get-Module cmdlet. They’re loaded with Import-Module and removed from memory with Remove-Module. These three cmdlets are all you need to know if you only want to use modules on your system. In this blog, we zeroed in on removing a loaded module.

~Bruce

Here is the code for the discount offer today at www.manning.com: scriptw5
Valid for 50% off PowerShell in Action and SharePoint Web Parts in Action
Offer valid from April 5, 2013 12:01 AM until April 6, midnight (EST)

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

Author

The "Scripting Guys" is a historical title passed from scripter to scripter. The current revision has morphed into our good friend Doctor Scripto who has been with us since the very beginning.

1 comment

Discussion is closed. Login to edit/delete existing comments.

  • Mark Heath

    If I’m developing a binary module, or need to upgrade a binary module I’ve developed, you are saying there is no way to unload this dll so I can build a new version and overwrite the old?

    I have to kill powershell to do this?

    That’s a massive pain for me. At least this explains why I can’t do it.

    Thanks