Reputation: 15623
Is it possible to register a new PowerShell module just by defining a new module manifest and putting it in the specified directory?
E.g. a a new module named SampleModule
should be created. I put the empty manifest file SampleModule.psd1
in the directory <%PSModulePath%>\SampleModule
. (It doesn't matter which (user or global) module path is used).
This is enough for PowerShell to list my new module with the Get-Module -ListAvailable
command.
In the next step I try to fill the manifest and set the ModuleToProcess
property to an assembly, which is located in another directory. Calling Import-Module
fails, PowerShell cannot find the assembly.
Upvotes: 1
Views: 1662
Reputation: 15623
The Get-Module
cmdlet with the -ListAvailable
parameter works nice. The problem was the architecture, i.e. 32-bit PowerShell host could not list 64-bit modules...
Upvotes: 1
Reputation: 8367
It is indeed. In fact, I have a really nifty trick that does this for the SQL snapin. The first chunk of the code is a function that will create a module manifest for you from one of of the module locations. It will still prompt you (as the New-ModuleManifest cmdlet does) for some required parameters, like description. It finds any types and format files, as well any .dll's named .ps.dll (most snapins follow this convention), and then it creates a module manifest that wraps the original module. The second chunk of code does this specificially for the SQL PSSnapin.
function New-ModuleManifestFromSnapIn {
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='Medium')]
param(
[Parameter(Mandatory=$true, Position=0)]
[System.String]
${Path},
# The location in the filesystem where the V1 snapin resides
[Parameter(Mandatory=$true)]
[System.String]
${OriginalPath},
[System.Guid]
${Guid},
[Parameter(Mandatory=$true)]
[AllowEmptyString()]
[System.String]
${Author},
[Parameter(Mandatory=$true)]
[AllowEmptyString()]
[System.String]
${CompanyName},
[Parameter(Mandatory=$true)]
[AllowEmptyString()]
[System.String]
${Copyright},
[ValidateNotNull()]
[System.Version]
${ModuleVersion},
[Parameter(Mandatory=$true)]
[AllowEmptyString()]
[System.String]
${Description},
[System.Reflection.ProcessorArchitecture]
${ProcessorArchitecture},
[System.Version]
${PowerShellVersion},
[System.Version]
${ClrVersion},
[System.Version]
${DotNetFrameworkVersion},
[System.String]
${PowerShellHostName},
[System.Version]
${PowerShellHostVersion},
[System.Object[]]
${RequiredModules},
[AllowEmptyCollection()]
[System.String[]]
${ScriptsToProcess},
[AllowEmptyCollection()]
[System.Object[]]
${ModuleList},
[AllowNull()]
[System.Object]
${PrivateData},
[Switch]
${PassThru}
)
process {
$types = Get-ChildItem $originalPath -Filter *.types.ps1xml
$formats = Get-ChildItem $originalPath -Filter *.format.ps1xml
$dlls = Get-ChildItem $originalPath -Filter *.ps*.dll
$null = $psBoundParameters.Remove("OriginalPath")
$psBoundParameters += @{
VariablesToExport = "*"
FunctionsToExport = "*"
AliasesToExport = "*"
CmdletsToExport = "*"
FileList = @()
RequiredAssemblies = @()
ModuleToProcess = ""
NestedModules = @($dlls | Select-Object -ExpandProperty FullName)
TypesToProcess = @($types | Select-Object -ExpandProperty FullName)
FormatsToProcess = @($formats | Select-Object -ExpandProperty FullName)
}
New-ModuleManifest @psBoundParameters
}
}
This chunk will show create a manifest by pointing the tool @ SQL.
$basePath = $env:SqlSamplesSourceDataPath | Split-Path
if (${env:ProgramFiles(x86)}) {
$basePath = $basePath.Replace($env:ProgramFiles, ${env:ProgramFiles(x86)})
}
$path = Join-Path $basePath "Binn"
$basicMetaData = @{
Author = "Microsoft Corporation"
Description = "A Manifest to enable using the SQL PowerShell snapin in V2"
CompanyName = "Microsoft Corporation"
Copyright = (Get-Date).Year
}
New-ModuleManifestFromSnapin -Path $psScriptRoot\Sql.psd1 -OriginalPath $path @BasicMetaData
The final chunk will copy any files named the current culture (i.e. SQL\en-us) into the module directory, which will make Get-Help work for the cmdlets.
This trick has worked for a few snapins, but may require some customizations for each snapin you want to re-expose as a module. Luckily, this is a one time cost.
$Culture = Get-Culture
$CultureList = "$path\$culture",
(Join-Path $path $culture.ThreeLetterIsoLanguageName),
(Join-Path $path $culture.TwoLetterIsoLanguageName)
$CultureDirectory = Get-Item $CultureList -ErrorAction SilentlyContinue |
Select-Object -First 1
if ($CultureDirectory) {
$localDir = Join-Path $psScriptRoot (Split-Path $CultureDirectory -Leaf)
$item = Get-Item $localDir -ErrorAction SilentlyContinue
if ($item) {
Remove-Item $item -Recurse -Force
}
Copy-Item $CultureDirectory $LocalDir -Recurse
}
Hope this helps
Upvotes: 1