Unable To Load PowerShell Module - powershell

I have created a *.psm1 and *.psd1 file. The reside in a directory (folder) with the same name as the files. This directory is in c:\Program Files\WindowsPowerShell\Modules\...
Import-module reports no error and Get-Module shows the module after. Test-ModuleManifest returns the correct manifest. However, the cmdlet itself is not recognized by Powershell. Also noted is the Test-ModuleManifest does not show any Exported Commands (is that normal?).
File security is good and when I put the *.psm1 in the Autoload folder it works as expected.
The usual mistakes and errors have been checked as well as extensive Googling. Several of the modules from the PS Gallery have been imported successfully. No one in this shop has been able to figure out what is missing.
This failure is occurring on several different platforms, all Windows (either 7 or 10) with both AMD and Intel cores.
Anyone run into this problem? Were you able to solve the issue?
This is my ModuleManifest, generated with New-ModuleManifest & modified with ISE.
# Module manifest for module 'Convert-F2C'
#
# Generated by: me
#
# Generated on: 4/25/2017
#
#{
# Script module or binary module file associated with this manifest.
# RootModule = ''
# Version number of this module.
ModuleVersion = '1.0'
# Supported PSEditions
# CompatiblePSEditions = #()
# ID used to uniquely identify this module
GUID = '252b9222-9bc8-4634-b658-dd234b483152'
# Author of this module
Author = 'me'
# Company or vendor of this module
CompanyName = 'my company'
# Copyright statement for this module
Copyright = '(c) 2017 Me. All rights reserved.'
# Description of the functionality provided by this module
Description = 'Converts Fahrenheit to Celsius temperatures'
# Minimum version of the Windows PowerShell engine required by this module
# PowerShellVersion = ''
# Name of the Windows PowerShell host required by this module
# PowerShellHostName = ''
# Minimum version of the Windows PowerShell host required by this module
# PowerShellHostVersion = ''
# Minimum version of Microsoft .NET Framework required by this module. This
prerequisite is valid for the PowerShell Desktop edition only.
# DotNetFrameworkVersion = ''
# Minimum version of the common language runtime (CLR) required by this
module. This prerequisite is valid for the PowerShell Desktop edition only.
# CLRVersion = ''
# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to
importing this module
# RequiredModules = #()
# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = #()
# Script files (.ps1) that are run in the caller's environment prior to
importing this module.
# ScriptsToProcess = #()
# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = #()
# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = #()
# Modules to import as nested modules of the module specified in
RootModule/ModuleToProcess
# NestedModules = #()
# Functions to export from this module, for best performance, do not use
wildcards and do not delete the entry, use an empty array if there are no
functions to export.
FunctionsToExport = 'Convert-F2C'
# Cmdlets to export from this module, for best performance, do not use
wildcards and do not delete the entry, use an empty array if there are no
cmdlets to export.
CmdletsToExport = #()
# Variables to export from this module
VariablesToExport = #()
# Aliases to export from this module, for best performance, do not use
wildcards and do not delete the entry, use an empty array if there are no
aliases to export.
AliasesToExport = '*'
# DSC resources to export from this module
# DscResourcesToExport = #()
# List of all modules packaged with this module
# ModuleList = #(Convert-F2c.psm1)
# List of all files packaged with this module
# FileList = #()
# Private data to pass to the module specified in
RootModule/ModuleToProcess. This may also contain a PSData hashtable with
additional module metadata used by PowerShell.
PrivateData = #{
PSData = #{
# Tags applied to this module. These help with module discovery in
online galleries.
# Tags = #()
# A URL to the license for this module.
# LicenseUri = ''
# A URL to the main website for this project.
# ProjectUri = ''
# A URL to an icon representing this module.
# IconUri = ''
# ReleaseNotes of this module
ReleaseNotes = 'Initial creation, first manifested module by
author'
} # End of PSData hashtable
} # End of PrivateData hashtable
# HelpInfo URI of this module
# HelpInfoURI = ''
# Default prefix for commands exported from this module. Override the
default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''
}

If you have these files for you module:
MyModule.psd1
MyModule.psm1
ExtraModule.psm1
You need to update this line:
# NestedModules = #()
To this:
NestedModules = #('MyModule','ExtraModule')
And ensure that your FunctionsToExport either lists all your functions or you can use FunctionsToExport = '*' to export them all.

I got it to work by setting the RootModule parameter. Doing this is not in any literature or references but the module functions appropriately now.
# Script module or binary module file associated with this manifest.
RootModule = 'ModuleName (no extension)'

Specifying the full-path (upto '.psm1') in the RootModule parameter in a manifest file didn't resolve the issue, as the ExportedCommands property was still empty.
Running Import-Module MyFirstModule -Verbose says that it is loading module from path '.psd1', not '.psm1'.
Running Import-Module with a full-path that ends with '.psm1' loaded the module properly, (i.e. the module functions appear in ExportedCommands), but in this case, when you run Get-Module, ModuleType is Script, not Manifest. So I guess the issue seems to occur when a manifest file is in the module directory and is not recognized properly.

Related

How to make sure PowerShell module manifest (.psd1) is used

I created a PowerShell module MyUtil.psm1 and a manifest file MyUtil.psd1 for it. In the psd1 file it has the prefix defined to prevent name conflicts for exported functions:
DefaultCommandPrefix = 'MyToolbox'
This way, after running Import-Module .\MyUtil.psd1, a function like Get-Command in the psm1 file will be Get-MyToolboxCommand, everything is fine. But if someone runs Import-Module .\MyUtil.psm1 to import the psm1 file directly, the psd1 file is simply not used and the prefix I want won't be applied.
If I want to prevent this (importing MyUtil.psm1 directly), is there a way to ONLY allow importing the corresponding psd1 manifest file instead of the psm1 file? Or a programmatic way to detect that this module was not imported through psd1 so I can warn the user to use psd1?
Ok, this is a bit annoying, but it works. You can use the Export-ModuleMember cmdlet with no args to stop the psm1 from exporting anything, but you need to send a value from the psd1 to the psm1 during the import. That way we know when we're being called with the psd1. So first off, add a value to the PrivateData hashtable in your PSD:
PrivateData = #{
FromPSD = $true
PSData = #{
Then you need to access it in the psm1 file. You can in a function, but not inline, so we have to stick it into a function.
function Get-PD
{
[CmdletBinding()]
$MyInvocation.MyCommand.Module.PrivateData
}
(I totally stole this from this SO answer Accessing PrivateData during Import-Module).
Then you wrap it all up by calling this code in the module which will get run as the module is loaded.
$MyPD = Get-PD
if($MyPD.Count -eq 0)
{
Export-ModuleMember
}
Now, if you don't want this pesky extra function to be referenced when the module is loaded, you'll need to populate the FunctionsToExport in the psd1 file with the list of functions you want the users to have access to.
You can use: #Requires
For example:
Require that Hyper-V (version 1.1 or greater) is installed.
#Requires -Modules #{ ModuleName="Hyper-V"; ModuleVersion="1.1" }
Requires that Hyper-V (only version 1.1) is installed.
#Requires -Modules #{ ModuleName="Hyper-V"; RequiredVersion="1.1" }
Requires that any version of PSScheduledJob and PSWorkflow, is installed.
#Requires -Modules PSWorkflow, PSScheduledJob
About Requires

PowerShell Publish-Module is already used for a different item on the specified repository

I've already published with the Publish-Module many modules but suddenly I get this message only for PSGallery
The specified name '$moduleName' is already used for a different item on the specified repository 'PSGallery'. Run 'Find-Script -Name
$moduleName -Repository PSGallery' to check whether the specified name '$moduleName' is already taken.
where $moduleName is the name of the module. The PowerShell I use is
Publish-Module -Path $path -NuGetApiKey $key -Repository PSGallery -WhatIf
Find-Module reports that $moduleName is indeed a module.
On PowerShell gallery it presents the artificat as a module
Same Publish-Module works for any other PSRepository.
Any ideas anyone?
Update 1
I used Fiddler to compare the data flow between two modules.
Publish-Module at some point executes this (The name of the module with the problem is ISHDeploy.12.0.0)
https://www.powershellgallery.com/api/v2/items/psscript/FindPackagesById()?id='ISHDeploy.12.0.0'&$skip=0&$top=40
and returns
<id>https://www.powershellgallery.com/api/v2/items/psscript/Packages(Id='ISHDeploy.12.0.0',Version='0.1')</id>
<category term="NuGetGallery.V2FeedPackage" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="edit" title="V2FeedPackage" href="Packages(Id='ISHDeploy.12.0.0',Version='0.1')" />
<title type="text">ISHDeploy.12.0.0</title>
<summary type="text"/>
<updated>2016-08-01T18:36:38Z</updated>
<author>
<name>SDL plc</name>
</author>
<link rel="edit-media" title="V2FeedPackage" href="Packages(Id='ISHDeploy.12.0.0',Version='0.1')/$value" />
<content type="application/zip" src="https://www.powershellgallery.com/api/v2/package/ISHDeploy.12.0.0/0.1.0" />
<m:properties>
<d:Version>0.1</d:Version>
<d:NormalizedVersion>0.1.0</d:NormalizedVersion>
<d:Copyright>SDL plc. All rights reserved.</d:Copyright>
<d:Created m:type="Edm.DateTime">2016-06-24T13:11:21.6</d:Created>
<d:Dependencies/>
<d:Description>Deployment automation module for SDL Knowledge Center Content Manager 12.0.0 (LiveContent Architect, Trisoft InfoShare)</d:Description>
<d:DownloadCount m:type="Edm.Int32">33</d:DownloadCount>
<d:GalleryDetailsUrl>https://www.powershellgallery.com/packages/ISHDeploy.12.0.0/0.1.0</d:GalleryDetailsUrl>
<d:IconUrl m:null="true" />
<d:IsLatestVersion m:type="Edm.Boolean">true</d:IsLatestVersion>
<d:IsAbsoluteLatestVersion m:type="Edm.Boolean">true</d:IsAbsoluteLatestVersion>
<d:IsPrerelease m:type="Edm.Boolean">false</d:IsPrerelease>
<d:Language m:null="true" />
<d:Published m:type="Edm.DateTime">2016-06-24T13:11:21.6</d:Published>
<d:PackageHash>0BsR7SQjEe7q5XO0IJqMOTS5iySLVYSzUFqHte4Hjng6Fxi+8BaUy3RNqmXs9Q53+QgrddI7e5Lij29kQlLS/g==</d:PackageHash>
<d:PackageHashAlgorithm>SHA512</d:PackageHashAlgorithm>
<d:PackageSize m:type="Edm.Int64">2723982</d:PackageSize>
<d:ProjectUrl>https://sdl.github.io/ISHDeploy/12.0.0/Index.html</d:ProjectUrl>
<d:ReportAbuseUrl>https://www.powershellgallery.com/package/ReportAbuse/ISHDeploy.12.0.0/0.1.0</d:ReportAbuseUrl>
<d:ReleaseNotes>https://sdl.github.io/ISHDeploy/12.0.0/CHANGELOG.html</d:ReleaseNotes>
<d:RequireLicenseAcceptance m:type="Edm.Boolean">false</d:RequireLicenseAcceptance>
<d:Summary m:null="true" />
<d:Tags m:null="true" />
<d:Title m:null="true" />
<d:VersionDownloadCount m:type="Edm.Int32">33</d:VersionDownloadCount>
<d:MinClientVersion m:null="true" />
<d:LastEdited m:type="Edm.DateTime">2016-06-24T14:14:56.217</d:LastEdited>
<d:LicenseUrl m:null="true" />
<d:LicenseNames m:null="true" />
<d:LicenseReportUrl m:null="true" />
<d:Workflows/>
<d:ItemType>Module</d:ItemType>
<d:FileList>ISHDeploy.12.0.0.nuspec|ISHDeploy.12.0.0.dll|ISHDeploy.12.0.0.dll-Help.xml|ISHDeploy.12.0.0.psd1|ISHDeploy.12.0.0.xml|Microsoft.Web.Administration.dll|System.Data.SqlServerCe.dll|amd64\sqlceca40.dll|amd64\sqlcecompact40.dll|amd64\sqlceer40EN.dll|amd64\sqlceme40.dll|amd64\sqlceqp40.dll|amd64\sqlcese40.dll|amd64\Microsoft.VC90.CRT\Microsoft.VC90.CRT.manifest|amd64\Microsoft.VC90.CRT\msvcr90.dll|amd64\Microsoft.VC90.CRT\README_ENU.txt|x86\sqlceca40.dll|x86\sqlcecompact40.dll|x86\sqlceer40EN.dll|x86\sqlceme40.dll|x86\sqlceqp40.dll|x86\sqlcese40.dll|x86\Microsoft.VC90.CRT\Microsoft.VC90.CRT.manifest|x86\Microsoft.VC90.CRT\msvcr90.dll|x86\Microsoft.VC90.CRT\README_ENU.txt</d:FileList>
<d:Cmdlets>Disable-ISHUITranslationJob Enable-ISHUITranslationJob Disable-ISHUIQualityAssistant Enable-ISHUIQualityAssistant Disable-ISHUIContentEditor Enable-ISHUIContentEditor Disable-ISHExternalPreview Enable-ISHExternalPreview Set-ISHContentEditor Test-ISHContentEditor Get-ISHPackageFolderPath Set-ISHUIEventMonitorTab Move-ISHUIEventMonitorTab Remove-ISHUIEventMonitorTab Remove-ISHIntegrationSTSCertificate Set-ISHIntegrationSTSCertificate Save-ISHIntegrationSTSConfigurationPackage Set-ISHIntegrationSTSWSFederation Set-ISHIntegrationSTSWSTrust Save-ISHIntegrationDBSTSSQLServerConfiguration Clear-ISHDeploymentHistory Get-ISHDeployment Get-ISHDeploymentHistory Undo-ISHDeployment Set-ISHAPIWCFServiceCertificate</d:Cmdlets>
<d:Functions/>
<d:DscResources/>
<d:RoleCapabilities/>
<d:GUID>68ae5b26-edc0-453a-a720-ecc99d9b603e</d:GUID>
<d:PowerShellVersion>3.0</d:PowerShellVersion>
<d:PowerShellHostVersion m:null="true" />
<d:DotNetFrameworkVersion>4.5</d:DotNetFrameworkVersion>
<d:CLRVersion>4.0</d:CLRVersion>
<d:ProcessorArchitecture m:null="true" />
<d:CompanyName>SDL plc</d:CompanyName>
<d:Owners>SDL</d:Owners>
</m:properties>
</entry>
</feed>
I compared with another module and I can't find any significant differences that could matter. It looks like something from this output halts the rest of the execution. Something in the xml is interpreted as a script entity although the xml clearly states that this a module
<d:ItemType>Module</d:ItemType>
The manifest of the module to publish is
#
# Module manifest for module 'ISHDeploy.12.0.0'
#
# Generated by: SDL plc
#
# Generated on: 01-Aug-16
#
#{
# Script module or binary module file associated with this manifest.
RootModule = 'ISHDeploy.12.0.0'
# Version number of this module.
ModuleVersion = '0.2'
# ID used to uniquely identify this module
GUID = '68ae5b26-edc0-453a-a720-ecc99d9b603e'
# Author of this module
Author = 'SDL plc'
# Company or vendor of this module
CompanyName = 'SDL plc'
# Copyright statement for this module
Copyright = 'SDL plc. All rights reserved.'
# Description of the functionality provided by this module
Description = 'Deployment automation module for SDL Knowledge Center Content Manager 12.0.0 (LiveContent Architect, Trisoft InfoShare)'
# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '3.0'
# Name of the Windows PowerShell host required by this module
# PowerShellHostName = ''
# Minimum version of the Windows PowerShell host required by this module
# PowerShellHostVersion = ''
# Minimum version of Microsoft .NET Framework required by this module
DotNetFrameworkVersion = '4.5'
# Minimum version of the common language runtime (CLR) required by this module
CLRVersion = '4.0'
# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to importing this module
# RequiredModules = #()
# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = #()
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = #()
# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = #()
# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = #()
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = #()
# Functions to export from this module
FunctionsToExport = '*'
# Cmdlets to export from this module
CmdletsToExport = '*'
# Variables to export from this module
VariablesToExport = '*'
# Aliases to export from this module
AliasesToExport = '*'
# DSC resources to export from this module
# DscResourcesToExport = #()
# List of all modules packaged with this module
# ModuleList = #()
# List of all files packaged with this module
# FileList = #()
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = #{
PSData = #{
# Tags applied to this module. These help with module discovery in online galleries.
# Tags = #()
# A URL to the license for this module.
# LicenseUri = ''
# A URL to the main website for this project.
# ProjectUri = ''
# A URL to an icon representing this module.
# IconUri = ''
# ReleaseNotes of this module
# ReleaseNotes = ''
} # End of PSData hashtable
} # End of PrivateData hashtable
# HelpInfo URI of this module
HelpInfoURI = 'https://sdl.github.io/ISHDeploy/12.0.0/'
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''
}
I verified that the GUID is the same just in case it mattered for the gallery
Conclusion
I copy the summary from my answer bellow
Summary is that a module in gallery without tags is evaluated also a script and blocks the Publish-Module
I found what the problem was. It is actually a bug on the PackageManagement.
Summary is that a module in gallery without tags is evaluated also a script and blocks the Publish-Module

Variables I listed to export in my powershell module manifest aren't actually exporting

I am creating a script module and using a manifest to export script members and set other module properties. I have followed just about every example manifest I've found and even used New-ModuleManifest to create a baseline manifest with the properties I want, I still cannot get the variables I want to export to actually export.
The intention here is to do all declarations in the manifest without having to use Export-ModuleMember in the module script.
Here is the script module:
#
# Widget.psm1
#
[System.Random]$rGen = New-Object System.Random;
[string]$WidgetBaseName = $null;
[string]$WidgetColor = "Blue";
function Get-WidgetName
{
param
(
[Parameter(Mandatory=$true)]
[string]$widgetName,
[switch]$appendRandomNumber
)
if (![string]::IsNullOrEmpty($WidgetBaseName))
{
$widgetName = $WidgetBaseName + $widgetName;
}
if ($appendRandomNumber)
{
return [string]::Format("{0}{1:D4}", $widgetName, $rGen.Next(10000));
}
else
{
return $widgetName;
}
}
function Get-WidgetBlessing()
{
return [string]::Format("A thousand blessings upon your {0} widget!", $WidgetColor);
}
And this is the manifest:
#
# Widget.psd1
#
#{
# Script module or binary module file associated with this manifest
RootModule = 'Widget.psm1'
# Version number of this module.
ModuleVersion = '0.0.0.1'
# ID used to uniquely identify this module
GUID = 'c4437164-ea47-4148-97ed-48737bd5824d'
# Author of this module
Author = 'Widget Developer'
# Company or vendor of this module
CompanyName = 'Fictional Company Inc.'
# Copyright statement for this module
Copyright = '(c) 2016 Fictional Company. All rights reserved.'
# Description of the functionality provided by this module
Description = 'Widget Module'
# Minimum version of the Windows PowerShell engine required by this module
# PowerShellVersion = ''
# Name of the Windows PowerShell host required by this module
# PowerShellHostName = ''
# Minimum version of the Windows PowerShell host required by this module
# PowerShellHostVersion = ''
# Minimum version of the .NET Framework required by this module
# DotNetFrameworkVersion = ''
# Minimum version of the common language runtime (CLR) required by this module
# CLRVersion = ''
# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to importing this module
# RequiredModules = #()
# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = #()
# Script files (.ps1) that are run in the caller's environment prior to importing this module
# ScriptsToProcess = #()
# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = #()
# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = #()
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = #()
# Functions to export from this module
FunctionsToExport = #( "Get-WidgetName", "Get-WidgetBlessing" )
# Cmdlets to export from this module
# CmdletsToExport = #()
# Variables to export from this module
VariablesToExport = 'WidgetBaseName', 'WidgetColor'
# Aliases to export from this module
AliasesToExport = '*'
# List of all modules packaged with this module
# ModuleList = #()
# List of all files packaged with this module
# FileList = #()
# Private data to pass to the module specified in RootModule/ModuleToProcess
# PrivateData = ''
# HelpInfo URI of this module
# HelpInfoURI = ''
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''
}
To check what members get exported, I run the following commands in my PowerShell window:
Import-Module Widget
Get-Module -Name Widget | fl
This is the output. Note the conspicuous absence of any exported variables.
Name : Widget
Path : D:\SRE\PowerShell\Widget\Widget.psm1
Description : Widget Module
ModuleType : Script
Version : 0.0.0.1
NestedModules : {}
ExportedFunctions : {Get-WidgetBlessing, Get-WidgetName}
ExportedCmdlets :
ExportedVariables :
ExportedAliases :
Why is this? I'm using the manifest that New-ModuleManifest generated (New-ModuleManifest -VariablesToExport WidgetBaseName WidgetColor). Is that tool broken, or is there something else in the manifest that is causing this behavior?
UPDATE:
I added the following line to the end of the module script:
Export-ModuleMember -Variable WidgetBaseName, WidgetColor
I changed the value of VariablesToExport to '*' in the manifest file.
Now when I import the module and run the check as described above, I get this instead:
Name : Widget
Path : D:\SRE\PowerShell\Widget\Widget.psm1
Description : Widget Module
ModuleType : Script
Version : 0.0.0.1
NestedModules : {}
ExportedFunctions :
ExportedCmdlets :
ExportedVariables : {WidgetBaseName, WidgetColor}
ExportedAliases :
... where did my exported functions go?
So for the sake of completeness and for anybody that lands on this question in the future I am going to sum up the conversation we had in the comments to the OP's question.
All functions are exported from a module by default, no other members exhibit this behavior. It is as if Export-ModuleMember -Function * is implicitly called from within the module. You can then further restrict what functions are exported via the ExportedFunctions key in the module manifest, e.g. ExportedFunctions : {Get-WidgetBlessing, Get-WidgetName}.
If you want to export variables or aliases you have to explicitly add a call to Export-ModuleMember -Variable <what you want to export> or Export-ModuleMember -Alias <what you want to export> in your module. However, once you have added an explicit call to Export-ModuleMember the implicit call to Export-ModuleMember -Function * no longer happens. You have to remember to add Export-ModuleMember -Function * to your module explicitly if you add even one other explicit call to Export-ModuleMember or else your functions will no longer continue to be exported.
Actually noticed the valid response is opposite to documentation.
From Microsoft
FunctionsToExport
Specifies the functions to export from this module, for best
performance, do not use wildcards and do not delete the entry, use an
empty array if there are no functions to export. By default, no
functions are exported. You can use this key to list the functions
that are exported by the module. The module exports the functions to
the caller's session state. The caller's session state can be the
global session state or, for nested modules, the session state of
another module. When chaining nested modules, all functions that are
exported by a nested module will be exported to the global session
state unless a module in the chain restricts the function by using the
FunctionsToExport key. If the manifest exports aliases for the
functions, this key can remove functions whose aliases are listed in
the AliasesToExport key, but this key cannot add function aliases to
the list. Example: FunctionsToExport = #("function1", "function2",
"function3")
VariablesToExport
Specifies the variables that the module exports to the caller's
session state. Wildcard characters are permitted. By default, all
variables ('*') are exported. You can use this key to restrict the
variables that are exported by the module. The caller's session state
can be the global session state or, for nested modules, the session
state of another module. When you are chaining nested modules, all
variables that are exported by a nested module will be exported to the
global session state unless a module in the chain restricts the
variable by using the VariablesToExport key. If the manifest also
exports aliases for the variables, this key can remove variables whose
aliases are listed in the AliasesToExport key, but this key cannot add
variable aliases to the list. Example: VariablesToExport =
#('$MyVariable1', '$MyVariable2', '$MyVariable3')

Dot source a "script" within a function

My PowerShell profile is getting a bit cumbersome and I find that I don't always use everything in it. I want to reduce the size of my profile and speed up the startup time that's been getting slower and slower, but I still want to be able to access those functions relatively quickly when I need them.
Is there a way to "dot source" a set of PowerShell functions and aliases from within a separate function such that the sourced functions will be available outside of that function call?
sourcing
After a great deal of effort (and to make sure I won't lose it later), here's what I've found works.
I've placed the following function in my profile:
function extras {. C:\...\WindowsPowerShell\extrafunctions.ps1}
And then I "dot source" the function within the PowerShell window.
. extras
And all my extra functions are available to the session without slowing down the startup time.
As others have already pointed out, the proper way to go about this would be to put those extra functions into a module. In its simplest form a module is a subfolder in one of the folders listed in $env:PSModulePath with a PowerShell script of the same name (but with the extension .psm1 instead of .ps1):
$env:USERPROFILE
`-Documents
`-WindowsPowerShell
`-Modules
`-ExtraFunctions
`-ExtraFunctions.psm1
ExtraFunctions.psm1 contains all your functions and ends with an Export-ModuleMember statement exporting the functions/aliases/… you want to publish:
function Get-Foo {
...
}
function New-Bar {
...
}
...
New-Alias -Name gf -Value Get-Foo
...
Export-ModuleMember -Function Get-Foo, New-Bar, ... -Alias gf, ...
That way you can import specific members:
PS C:\> Import-Module ExtraFunctions -Function Get-Foo
or everything at once:
PS C:\> Import-Module ExtraFunctions
A module can be unloaded via the Remove-Module cmdlet:
PS C:\> Remove-Module ExtraFunctions
With PowerShell v3 and newer you don't even need to import your module manually, because modules are loaded automatically when one of their exported functions/cmdlets is called.
If you want to put in some extra work you can add a module manifest:
#{
# Script module or binary module file associated with this manifest
ModuleToProcess = 'ExtraFunctions.psm1'
# Version number of this module.
ModuleVersion = '1.0'
# ID used to uniquely identify this module
GUID = 'dbf5a7ca-683a-4f18-a090-0700ecccf6ff'
# Author of this module
Author = 'Ansgar Wiechers'
# Company or vendor of this module
CompanyName = ''
# Copyright statement for this module
Copyright = ''
# Description of the functionality provided by this module
Description = 'Extra functions.'
# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = ''
# Name of the Windows PowerShell host required by this module
PowerShellHostName = ''
# Minimum version of the Windows PowerShell host required by this module
PowerShellHostVersion = ''
# Minimum version of the .NET Framework required by this module
DotNetFrameworkVersion = ''
# Minimum version of the common language runtime (CLR) required by this
# module
CLRVersion = ''
# Processor architecture (None, X86, Amd64, IA64) required by this module
ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to
# importing this module
RequiredModules = #()
# Assemblies that must be loaded prior to importing this module
RequiredAssemblies = #()
# Script files (.ps1) that are run in the caller's environment prior to
# importing this module
ScriptsToProcess = #()
# Type files (.ps1xml) to be loaded when importing this module
TypesToProcess = #()
# Format files (.ps1xml) to be loaded when importing this module
FormatsToProcess = #()
# Modules to import as nested modules of the module specified in
# ModuleToProcess
NestedModules = #()
# Functions to export from this module
FunctionsToExport = 'Get-Foo', 'New-Bar'
# Cmdlets to export from this module
CmdletsToExport = ''
# Variables to export from this module
VariablesToExport = ''
# Aliases to export from this module
AliasesToExport = 'gf'
# List of all modules packaged with this module
ModuleList = #()
# List of all files packaged with this module
FileList = 'ExtraFunctions.psm1'
# Private data to pass to the module specified in ModuleToProcess
PrivateData = ''
}
Manifests allow you for instance to define dependencies, or to split your module implementation into multiple files. They can be created manually or via the New-ModuleManifest cmdlet. Put the manifest into the root folder of the module:
$env:USERPROFILE
`-Documents
`-WindowsPowerShell
`-Modules
`-ExtraFunctions
+-ExtraFunctions.psd1
`-ExtraFunctions.psm1

Invoking functions from nested modules in a script module do not always trigger a module to autoload

If I create a manifest module with nested modules, exported functions from all nested modules after the first do not appear in the list of available commands and don't trigger the module to autoload.
They also do not appear when I run "Get-Module -ListAvailable".
Only the exported functions from the first nested module appear in the list of commands.
If I explicitly import the module, all exported functions are available.
In the example below, Update-LegacyServices is not available until the module has been explicitly imported.
The only way I can make it work it to rename my module files to end with ps1 instead of psm1 and include them in ScriptsToProcess, which seems like a bad idea.
Module manifest (psd1)
#{
# Script module or binary module file associated with this manifest.
# RootModule = ''
# Version number of this module.
ModuleVersion = '1.0.0.1'
# ID used to uniquely identify this module
GUID = 'c11d6aca-d531-4d06-a732-5fb95113357f'
# Author of this module
Author = 'luke'
# Company or vendor of this module
CompanyName = ''
# Copyright statement for this module
Copyright = ''
# Description of the functionality provided by this module
# Description = 'MyBudget Developer Powershell Module'
# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '4.0'
# Name of the Windows PowerShell host required by this module
# PowerShellHostName = ''
# Minimum version of the Windows PowerShell host required by this module
# PowerShellHostVersion = ''
# Minimum version of the .NET Framework required by this module
DotNetFrameworkVersion = '4.5.0'
# Minimum version of the common language runtime (CLR) required by this module
CLRVersion = '4.0.30319.18444'
# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to importing this module
RequiredModules = 'BitsTransfer'
# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = #()
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
ScriptsToProcess = #()
# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = #()
# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = #()
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
NestedModules = #('database\Database.psm1', 'build\Build.psm1')
# Functions to export from this module
#FunctionsToExport = '*'
# Cmdlets to export from this module
CmdletsToExport = '*'
# Variables to export from this module
VariablesToExport = '*'
# Aliases to export from this module
AliasesToExport = '*'
# List of all modules packaged with this module.
ModuleList = #('database\Database.psm1', 'build\Build.psm1')
# List of all files packaged with this module
# FileList = #()
# Private data to pass to the module specified in RootModule/ModuleToProcess
# PrivateData = ''
# HelpInfo URI of this module
# HelpInfoURI = ''
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''
}
Module 1 (Build\Build.psm1)
function Update-LegacyServices()
{
echo "Update"
}
Export-ModuleMember -Function Update-LegacyServices
Module 2 (database\Database.psm1)
Function Get-Backup($directory, $name)
{
echo "Get-Backup"
}
Export-ModuleMember -Function Get-Backup
I had this line in my .psd1 file
FunctionsToExport = 'FuncFromMainPsm1 FuncFromSecondPsm1'
which was what I inferred from the line generated by Powershell Tools for Visual Studio:
# Functions to export from this module
FunctionsToExport = '*'
This caused my Get-Module -ListAvailable to show what looked like the right thing
Script 1.0 MyMModule FuncFromMainPsm1 FuncFromSecondPsm1
But when I called FuncFromSecondPsm1 I'd get "The term 'FuncFromSecondPsm1' is not recognized...".
So I changed my export line to
FunctionsToExport = #('FuncFromMainPsm1', 'FuncFromSecondPsm1')
And now it all works. I can call both functions after my module loads, whether via autoload or Import-Module.
I have tried this with and without both ModuleList and FileList set. They make no difference.
Hy Paul, Hy Luken,
After struggling for a few hours on this topic (with the implicit and declared manifest approach), I opted for the auto generated manifest.
In essence, I wrote a ps1 script that generates the manifest, in two steps:
with some 'business' logic, discover what you want to expose
generate the module manifest
IMHO, Advantage of that approach: I 'fully' understand and master the exposure of the module content.
below you can find a PS code snippet that follows this approach, hoping it will benefit to other people.
# module discovery
$rootModule = "WdCore";
$modules = Get-ChildItem *.psm1;
$nestedmodulesNames = $modules | where { $_.BaseName -ne "WdCore"} | % { $_.BaseName } ;
# functions discovery
$modulesLines = $modules | Get-Content;
$functionsLines = $modulesLines | where { $_.contains("Function") };
$functionNamePattern = '^Function\s+(?<name>([a-z][0-9|A-Z|-]+))\s?{.*$';
$functionNames = $functionsLines | where { $_ -match $functionNamePattern } | select { $Matches['name'] } | % { $_.' $Matches[''name''] '};
# generate manifest
New-ModuleManifest `
-Path ./WdTools.psd1 -RootModule $rootModule `
-ModuleVersion '1.0' `
-NestedModules $nestedmodulesNames `
-FunctionsToExport $functionNames `
-Guid '57D7F213-2316-4786-8D8A-3E4B9262B1E5' `
-Author 'Blaise Braye' `
-Description 'This module provides working directory tooling' `
-PowerShellVersion '3.0' -ClrVersion '4.0';