3

I have a Powershell module that consists of 4 .psm1 files:

  • DatabaseUserManagement.psm1 - Contains most of my public cmdlets.
  • PermissionControl.psm1 - Contains the final public cmdlet.
  • ErrorHandling.psm1 - Contains a private error handling function.
  • Helper functions - Contains about 10 small private helper functions.

For whatever reason, the function in PermissionControl.psm1 (Set-UserPermission) doesn't seem to be able to see any of the helper functions:

Comments added for clarity

PermissionControl.psm1

Function Set-UserPermission
{
    [CmdletBinding()]
    Param(
        # 3 parameters here. [string]$LogonName, [string]$Area and [string]$Permissions
    )

    $SamAccountName = (Get-SAMAccountName $LogonName) # Fails, can't find cmdlet.
    $Login = (Get-Login $SamAccountName) # Ditto
    $User = (Get-User $Login) # Ditto
    ...
)

DatabaseUserManagement.psm1

Function Add-DatabaseUser
{
    [CmdletBinding()]
    Param(
       # 3 parameters here. [string]$LogonName, [string]$UserName = '' and [switch]$FullAccess
    )

    $SAMAccountName = (Get-SAMAccountName $LogonName) # Works
    $Server = Get-Server # Ditto
    $Database = Get-Database # Ditto
    ...
)

HelperFunctions.psm1 (only those mentioned in previous code)

Function Get-SAMAccountName([string]$LogonName)
{
    Write-Output('{0}\{1}' -f (Get-DomainName), $LogonName)
}

Function Get-Login([string]$SAMAccountName)
{
    Write-Output((Get-Server).Logins[$SAMAccountName])
}

Function Get-User([Microsoft.SqlServer.Management.Smo.Login]$Login)
{
    Write-Output((Get-Database).Users[($Login.GetDatabaseUser((Get-Database).Name))])
}

Function Get-Server()
{
    Write-Output((New-Object Microsoft.SqlServer.Management.Smo.Server (Get-ServerInstanceName)))
}

Function Get-Database()
{
    Write-Output((Get-Server).Databases[(Get-DatabaseName)])
}

DatabaseUserManagement.psd1

@{
    ModuleToProcess = 'DatabaseUserManagement.psm1'
    ModuleVersion = '1.0.1'
    GUID = 'bd4390dc-a8ad-4bce-8d69-f53ccf8e4163'
    Author = 'removed'
    CompanyName = 'removed'
    Copyright = 'removed'
    Description = 'removed'
    PowerShellVersion = '2.0'
    DotNetFrameworkVersion = '4.0'
    ProcessorArchitecture = 'amd64'
    RequiredAssemblies = @(
        'Microsoft.SqlServer.Smo.dll'
    )
    NestedModules = @(
         'ErrorHandling.psm1'
        ,'PermissionControl.psm1'
        ,'HelperFunctions.psm1'

    )
    FunctionsToExport = @(
         'Add-DatabaseUser'
        ,'Get-DatabaseUser'
        ,'Get-DatabaseUserInformation'
        ,'Remove-DatabaseUser'
        ,'Set-UserPermission'
    )
    PrivateData = @{
         DatabaseName =       'removed'
        ;DomainName =         'removed'
        ;ServerInstancename = 'removed'
    }
}

The error I get is as follows:

Get-SAMAccountName : The term 'Get-SAMAccountName' is not recognized as the name
of a cmdlet, function, script file, or operable program. Check the spelling of
the name, or if a path was included, verify that the path is correct and try
again.
At G:\My Documents\WindowsPowerShell\Modules\databaseusermanagement\PermissionControl.psm1:52 char:21
+     $SamAccountName = (Get-SAMAccountName $LogonName)
+                        ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Get-SAMAccountName:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
Jake
  • 1,701
  • 3
  • 23
  • 44
  • So I will assume that you do not get errors while importing the module? – Matt Sep 23 '15 at 12:21
  • Yes, the module appears to import with no errors. – Jake Sep 23 '15 at 12:27
  • didn't forget to export this function from HelperFunctions.psd1 ? – Loïc MICHEL Sep 23 '15 at 12:36
  • Does it need to be? I thought exporting functions was only for ones that you want the user to have access to. Calling `Get-SAMAccountName` on it's own is useless in this particular module. Also, since it works without being exported in DatabaseUserManagement.psm1, I don't see why it would fail in a different file. – Jake Sep 23 '15 at 12:37
  • 2
    `PermissionControl.psm1` does not import `HelperFunctions.psm1`, so of course functions inside `PermissionControl.psm1` can not use functions from `HelperFunctions.psm1`. All nested modules are independent from each other. – user4003407 Sep 23 '15 at 12:38
  • Ok... is there any way to fix this apart from moving `Set-UserPermission` to DatabaseUserManagement.psm1? – Jake Sep 23 '15 at 12:40
  • 3
    The members of the nested modules are imported into the caller's session state only when the root module exports the nested module members explicitly or when the root module omits the Export-ModuleMember command. This will export all commands by default, including commands from nested modules. https://technet.microsoft.com/en-us/library/dd878297(v=vs.85).aspx – Loïc MICHEL Sep 23 '15 at 12:42
  • 1
    so adding Get-SAMAccountName in the functionstoexport table of DatabaseUserManagement.psd1 should work – Loïc MICHEL Sep 23 '15 at 12:44
  • 2
    `Import-Module (Join-Path $PSScriptRoot HelperFunctions.psm1)` – user4003407 Sep 23 '15 at 12:45
  • 1
    @Kayasax In that case, you just expose helper function into global scope. And `PermissionControl.psm1` will use that helper function from global scope. And if someone redefine `Get-SAMAccountName` in global scope, then `PermissionControl.psm1` will use that redefined version of it, while `DatabaseUserManagement.psm1` will use old version imported from `HelperFunctions.psm1`. – user4003407 Sep 23 '15 at 13:03
  • @PetSerAl yep I have not though about that. We could use the modulename\functionname notation to overcome this but in fact it's not handly – Loïc MICHEL Sep 23 '15 at 13:25

0 Answers0