Module Manifest Help

This topic contains 4 replies, has 2 voices, and was last updated by Profile photo of Anthony Stewart Anthony Stewart 2 years, 2 months ago.

  • Author
    Posts
  • #19295
    Profile photo of Anthony Stewart
    Anthony Stewart
    Participant

    [Question starts after code]

    Here's the back story, I'm working on converting some computer and user login scripts from VBS to PS for my job.
    We have several hundred client machines on campus and each lab of computers need to do something a little different.
    The main difference is installing and setting default printers.
    The computers are running our build of Windows 7, because of this, we can't use the PrintManagement module that comes with Windows 8.
    So I wrote this Module, OITPrinterManagement.psm1, i'll include a couple functions so you get the idea, but don't have to suffer through The Great Wall of Text.

     Get-OITPrinter
    .EXAMPLE
        PS C:\> Get-OITPrinter "Fax"
    .EXAMPLE
        PS C:\> "Fax" | Get-OITPrinter
    #>
    function Get-OITPrinter
    {
        [CmdletBinding(DefaultParameterSetName="Names")]
        Param
        (
            #Name(s) of printers to search for
            [Parameter(Mandatory=$false,
                       Position=0,
                       ValueFromPipeline=$false,
                       ValueFromPipelineByPropertyName=$false,
                       ParameterSetName="Names")]
            [string[]]$Names,
    
            #InputObject (Names) passed in through pipeline
            [Parameter(Mandatory=$false,
                       ValueFromPipeline=$true,
                       ValueFromPipelineByPropertyName=$true,
                       ParameterSetName="InputObject")]
            [string[]]$InputObject
        )
    
        #Only ran once
        Begin
        {
            [System.Collections.ArrayList]$returnValue = @()
            $printers = Get-WmiObject -Class Win32_Printer
        }
    
        #Run once for the Names Paramenter Set
        #Run once for every pipeline input
        Process
        {
            switch ($PSCmdlet.ParameterSetName)
            {
                "InputObject"
                {
                    #Loop through each printer installed
                    foreach ($printer in $printers)
                    {
                        #If using pipeline
                        if ($input -ne $null)
                        {
                            if ($printer.Name -eq [string]$input)
                            {
                                $returnValue += $printer
                            }
                        }
                        else
                        {
                            foreach ($inputObj in $InputObject)
                            {
                                if ($printer.Name -eq [string]$inputObj)
                                {
                                    $returnValue += $printer
                                }
                            }
                        }
                    }
                }
                
                "Names"
                {
                    if ($Names.Count -gt 0)
                    {
                        #Adds every printer that has it's name in the $Names variable
                        foreach ($printer in $printers)
                        {
                            foreach($name in $Names)
                            {
                                if ($printer.Name -eq $name)
                                {
                                    $returnValue += $printer
                                }
                            }
                        }
                    }
                    else
                    {
                        #Add every printer
                        $returnValue += $printers
                    }
                }
            }
        }
    
        End
        {
            return $returnValue
        }
    }
    
     Set-OITDefaultPrinter "Fax"
    #>
    function Set-OITDefaultPrinter
    {
        [CmdletBinding()]
        Param
        (
            # Param1 help description
            [Parameter(Mandatory=$true,
                       ValueFromPipelineByPropertyName=$true,
                       Position=0)]
            [string]
            $Name
        )
        
        #Get the printer and set it to be the default printer
        $printer = Get-OITPrinter -Names $Name
        $printer.SetDefaultPrinter()
    }
    

    The code works, you can suggest changes if you see potential bugs, but that's not the point of this post.

    Anyway, I made a Module Manifest to better document the module, but i'm having trouble using it correctly.
    Here is the manifest (trimmed):

    #
    # Module manifest for module 'PrinterManagement'
    #
    # Generated by: Anthony Stewart
    #
    # Generated on: 9/2/2014
    #
    
    @{
    
    # Script module or binary module file associated with this manifest.
    RootModule = 'OITPrinterManagement.psm1'
    
    # Version number of this module.
    ModuleVersion = '1.0'
    
    # ID used to uniquely identify this module
    GUID = 'ce70242b-b0fc-496f-adf9-09d632e1c302'
    
    # Author of this module
    Author = 'Anthony Stewart'
    
    # Company or vendor of this module
    CompanyName = 'OIT@UTK'
    
    # Copyright statement for this module
    Copyright = '(c) 2014 Anthony Stewart. All rights reserved.'
    
    # Description of the functionality provided by this module
    Description = 'This module was made to be used as a replacement for the PrintManagement module created by Microsoft. The PrintManagement module is only available starting with Windows 8, Windows Server 2012.
                   Because of this fact, we cannot use the PrintManagement module cmdlets on the Windows 7 lab computers.'
    
    # Minimum version of the Windows PowerShell engine required by this module
    PowerShellVersion = '3.0'
    
    # Modules that must be imported into the global environment prior to importing this module
    RequiredModules = @('Microsoft.PowerShell.Management';)
    
    # Functions to export from this module
    FunctionsToExport = ""
    
    # Cmdlets to export from this module
    CmdletsToExport = 'Get-OITPrinter',
                      'Add-OITPrinter',
                      'Remove-OITPrinter',
                      'Set-OITDefaultPrinter'
    
    # Variables to export from this module
    VariablesToExport = '*'
    
    # Aliases to export from this module
    AliasesToExport = '*'
    
    }
    

    Here is the folder structure:

    |-Modules
      |-OITPrinterManagement
        |-OITPrinterManagement.psd1
        |-OITPrinterManagement.psm1
    

    But here are the results of my work:

    PS C:\Windows\system32> Import-Module OITPrinterManagement -Verbose
    VERBOSE: Loading module from path '\\hathor.utk.tennessee.edu\LABS\PowerShell\Modules\OITPrinterManagement\OITPrint
    erManagement.psd1'.
    VERBOSE: Loading module from path '\\hathor.utk.tennessee.edu\LABS\PowerShell\Modules\OITPrinterManagement\OITPrint
    erManagement.psm1'.
    VERBOSE: Exporting function 'Get-OITPrinter'.
    VERBOSE: Exporting function 'Add-OITPrinter'.
    VERBOSE: Exporting function 'Remove-OITPrinter'.
    VERBOSE: Exporting function 'Set-OITDefaultPrinter'.
    
    PS C:\Windows\system32> Get-Module OITPrinterManagement* -Verbose -All
    
    ModuleType Version    Name                                ExportedCommands                                        
    ---------- -------    ----                                ----------------                                        
    Script     1.0        OITPrinterManagement                                                                        
    

    Using the Module Manifest, the Cmdlets aren't being exported correctly, and I can't figure out what I need to do so that they will work.

    I can always not use Module Manifest, but it seems like this is something that should be easy to do.

    As always, any help is appreciated.

    -Anthony Stewart

  • #19296
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Those are functions, not Cmdlets. Cmdlets refer to PowerShell commands that are written in a .NET language (usually C#), and will be contained in a .dll file that the module loads.

  • #19299
    Profile photo of Anthony Stewart
    Anthony Stewart
    Participant

    Thanks, moving the "function" names to "FunctionsToExport" did it!
    Now I get this:

    PS C:\Windows\system32> Get-Module OITPrinterManagement
    
    ModuleType Version    Name                                ExportedCommands                                                                                                                                                      
    ---------- -------    ----                                ----------------                                                                                                                                                      
    Script     1.0        OITPrinterManagement                {Add-OITPrinter, Get-OITPrinter, Remove-OITPrinter, Set-OITDefaultPrinter}
    

    Should the ModuleType be Script and not Manifest like PS displays for Microsoft modules?

  • #19300
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Yep, that's normal. I'm not sure if I have this 100% correct, but I think if your manifest has a "RootModule" or "ModuleToProcess" key, you'll see the module type that is associated with that module. (If it's a .psm1 file, it'll say Script, if it's a .dll file, it'll say Binary.) Modules that show up as type Manifest seem to just have NestedModules listed, and no root module (though that's based on some very quick spot-checking of manifests; I haven't looked at all of them.)

  • #19301
    Profile photo of Anthony Stewart
    Anthony Stewart
    Participant

    Ok, Thanks again! That's been bugging me for a couple weeks now.

You must be logged in to reply to this topic.