Auto-Complete on functions in custom modules?

Mar 23, 2011 at 2:34 PM

Hi there,

is tab expansion supposed to work for functions in custom modules? It is not working for me.

I got a "Util" module in "%HOME%\Documents\WindowsPowerShell\Modules\Util"

and a util.psm1 containing:

Function get-assemblyname([string]$pathToAssembly)
{
    // stuff
}

and a util.psd1 referencing util.psm1.

Shoud PowerTab provide expansions for that automatically or do I have to "tell" PowerTab about my function somehow?

Coordinator
Mar 29, 2011 at 12:42 AM

It should pick it up if it is public like so:  Get-<TAB>

It won't matter what order the modules are loaded.

Mar 29, 2011 at 8:30 AM
Edited Mar 29, 2011 at 8:31 AM

 

All functions are exportet. I can use them all without problems. But their tab expansion is not showing up. I attached both util.psd1 and util.psm1, so someone may try to reproduce my issue.


util1.psd1
=========================================== @{ # Script module or binary module file associated with this manifest ModuleToProcess = 'util.psm1' # Version number of this module. ModuleVersion = '1.0' # ID used to uniquely identify this module GUID = '2bbac205-f240-43b3-a746-5b0d1038f5b7' # Author of this module Author = 'Janosch Peters' # Company or vendor of this module CompanyName = 'XXXX GmbH & Co. KG' # Copyright statement for this module Copyright = '(c) 2011 XXXXX. All rights reserved.' # Description of the functionality provided by this module Description = '' # 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 = @('mscorlib.dll') # 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 = '*' # 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 = @() # List of all files packaged with this module FileList = @() # Private data to pass to the module specified in ModuleToProcess PrivateData = '' }


 util.psm1

 

===========================================
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

# .SYNOPSIS
# Gets the full name of the assembly
#
# .DESCRIPTION
# Returns the full assembly name. This includes the filename without suffix, the version, the culture and the publik key token.
#
# .PARAMETER $pathToAssembly
# The path to the assembly file. Both absolute and relative paths are supported.
#
Function Get-Assemblyname([string]$pathToAssembly)
{
	if( [System.IO.File]::Exists($pathToAssembly) )
	{
		$o =[System.Reflection.Assembly]::LoadFile($pathToAssembly)
		write-host "Loaded assembly from: " $pathToAssembly
	}
	else
	{
		$wrkDirPath = [System.IO.Path]::Combine( $pwd, $pathToAssembly ) 

		if( [System.IO.File]::Exists($wrkDirPath)  )
		{
			$o =[System.Reflection.Assembly]::LoadFile($wrkDirPath)
			write-host "Loaded assembly from: " $wrkDirPath
		}	
		else
		{
			write-host "Could not load assembly from '" $pathToAssembly "'."
			return
		}
	}
	
	$name = $o.GetName()
	write-host ""
	write-output $name.FullName
	write-host ""
}


# .SYNOPSIS
# Removes all site colections created with New-SPSiteFromTemplates
#
# .PARAMETER $path
#  The path from which the site collections should be removed. Example: 'http://sp2010s1n1/sites'
#
# .EXAMPLE
# New-SPSiteFromTemplates "http://sp2010s1n1/sites" 
#
function Remove-SPSiteFromTemplates([string]$path) 
{
	$templates = Get-SPWebTemplate
	foreach($tpl in $templates)
	{
		$scUrlSuffix = $tpl.Title -replace " ", ""
		$scUrl = "{0}/{1}" -f $path, $scUrlSuffix
		
		$outStr = 'Deleting Site Collection "{0}" ' -f $scUrl 
		write-output $outStr
		$createSiteExpr = 'Remove-SPSite -Identity "{0}" -Confirm:$False' -f $scUrl, $tpl.Name
		invoke-expression $createSiteExpr
	}
}

# .SYNOPSIS 
# Creates a site collection for every available site template
#
# .PARAMETER $path
#  The path in which the site collections should be created. Example: 'http://sp2010s1n1/sites'
#
# .PARAMETER $loginName 
# The user which is used to create the site collections. Example: 'SUPSTANCE\jane.doe'
#
# .EXAMPLE
# New-SPSiteFromTemplates "http://sp2010s1n1/sites" "SUPSTANCE\jane.doe"
#
function New-SPSiteFromTemplates( [string]$path, [string]$loginName ) 
{
	$templates = Get-SPWebTemplate
	foreach($tpl in $templates)
	{
		$scUrlSuffix = $tpl.Title -replace " ", ""
		$scUrl = "{0}/{1}" -f $path, $scUrlSuffix
		
		$outStr = 'Creating Site Collection "{0}" with template "{1}"' -f $scUrl, $tpl.Name 
		write-output $outStr
		$createSiteExpr = 'New-SPSite -Url "{0}" -OwnerAlias $loginName -Template "{1}" -name "{2}"' -f $scUrl, $tpl.Name, $scUrlSuffix
		invoke-expression $createSiteExpr
	}
}

# .SYNOPSIS 
# Sets the theme of a SPWeb.
#
# .PARAMETER $Url
#  The URL of the SPWeb on which the theme should be applied.
#
# .PARAMETER $Theme 
# The filename (without extension) of the theme file.
#
# .EXAMPLE
# Set-SPTheme "http://sp2010s1n1/sites/123" "my_theme"
#
function Set-SPTheme([string]$Url, [string]$Theme) {

	$curWeb = Get-SPWeb $Url
	$themeUrl = "{0}/_catalogs/theme/{1}.thmx" -f $curWeb.Site.ServerRelativeUrl.TrimEnd("/"), $Theme
	$themeObj = [Microsoft.SharePoint.Utilities.ThmxTheme]::Open($curWeb.Site, $themeUrl)
	
	if( $themeObj )
	{
		$themeObj.ApplyTo($curWeb,$TRUE)
		$curWeb.Update()
	}
	else
	{
		Write-ColorOutput red "Did not find theme file on this site collection. Aborting."
	}

	$curWeb.Dispose()
}

# .SYNOPSIS 
# This function re-applies a theme to all sites of a given site collection.
#
# .PARAMETER $Theme
#  The filename (without extension) of the theme that should be re-applied.
#
# .PARAMETER $SiteCollectionFeatureId
#  The GUID of the site collection feature which should be re-activated.
#
# .PARAMETER $SiteFeatureId
#  The GUID of the site feature which should be re-activated.
#
# .EXAMPLE
# get-content sites.txt | .\set-spsitestheme.ps1 -theme SP2010_NSN_Theme_Dark_Font_Blue_Links -SiteFeatureId "15C0003E-42E4-487E-A2E7-B4E523FC3457" -WebFeatureId "3BE5F09D-E5C7-406E-B516-450EA5CBC95B"
#
function Set-SPSitesTheme([string]$Theme, [string]$SiteCollectionFeatureId, [string]$SiteFeatureId) 
{
	process {
		$site = Get-SPSite -Identity $_
		
		if( $site )
		{
			$allSubWebs = $site.allwebs
			Write-ColorOutput green "`nProcessing site:  $($site.url)"

			$feature = Get-SPFeature -identity $SiteCollectionFeatureId -site $site.url

			if($site.Features[$feature.ID]) {
				Disable-SPFeature  -identity $feature.ID -url $site.url -force -Confirm:$false
				Write-ColorOutput cyan "Site Collection feature deactivated"
			}
			
			Enable-SPFeature  -identity $feature.ID -url $site.url -force
			Write-ColorOutput cyan "Site Collection feature activated"

			foreach($web in $allSubWebs)
			{
				$webFeature = Get-SPFeature -identity $WebFeatureId -web $web.url
				Write-ColorOutput green "Processing web:  $($web.url)"

				if($web.Features[$webFeature.ID]) { 
					$applyThemeCmd = '.\Set-SPTheme -url "{0}" -theme "{1}"' -f $web.url, $theme
					Write-ColorOutput cyan "Reapplying theme to $($web.url)"
					invoke-expression $applyThemeCmd
				}
				else {
					Enable-SPFeature -identity $webFeature.ID -url $web.url -force
				}
			}
		}
		else
		{
			Write-ColorOutput red "`nDid not find site: $($_)"
		}
	}
}

# .SYNOPSIS 
# This function behaves like 'Write-Output' but it writes colored output to the console.
#
# .PARAMETER $ForegroundColor
#  The text color of the message.
#
# .EXAMPLE
# Write-ColorOutput red (ls)
#
# .EXAMPLE
# ls | Write-ColorOutput yellow
#
function Write-ColorOutput($ForegroundColor)
{
    # save the current color
    $fc = $host.UI.RawUI.ForegroundColor

    # set the new color
    $host.UI.RawUI.ForegroundColor = $ForegroundColor

    # output
    if ($args) {
        Write-Output $args
    }
    else {
        $input | Write-Output
    }

    # restore the original color
    $host.UI.RawUI.ForegroundColor = $fc
}

#export-modulemember Get-Assemblyname, Remove-SPSiteFromTemplates, New-SPSiteFromTemplates, Set-SPTheme, Set-SPSitesTheme , Write-ColorOutput

Coordinator
Apr 4, 2011 at 12:12 AM

I downloaded your module and tried it out.  I was able to see your functions in tab expansion.  Are the normal PowerShell commands showing up in tab expansion?

Apr 4, 2011 at 7:32 AM

Yes, normal PowerShell commands do show up . I did some testing and found out that PowerTab does not get any commands defined in my modules (I only have two, though: "util" and "PowerTab"). So it seems it has trouble to parse my modules. I load my modules on startup thru the "Microsoft.PowerShell_profile.ps1" file:

import-module util -DisableNameChecking
import-module powertab -DisableNameChecking

I also tried dot-sourcing and the '&-operator' (dunno if this makes sense at all), but still no tab expansion. I tried to investigate the issue myself, but I could not find the definition of "Invoke-Tabexpansion'. Apart from the built-in commands, tab expansion also works with sharepoint commands, but those are included via a snap-in not a module.

Thanks for helping, but Im quiet clueless why this isn't working.

Coordinator
Apr 8, 2011 at 2:24 AM

PowerTab just uses Get-Command to find out what functions and cmdlets there are. Hmm..

Apr 8, 2011 at 7:51 AM

Jason, I was wrong. Im right now banging my head on my desk because of my stupidity. Im new to PowerShell and the "tab expansion" I was talking about is just the built-in autocomplete of Powershell. So PowerTab was not working at all.

I decided to re-install powertab and now it works. I suspect that the error I got might have to do with signing/unblocking, because now I "unblocked" all script files in the powertab module. I didnt do that during my first installation.

Anyway, thanks for trying to help and thanks for the great module.