user16004320
user16004320

Reputation:

Ignore non used parameters in powershell

I have been using different params for different functions that are called from the script externally.

However I noticed that some of functions are failing because its going through all my params instead of the ones I want.

For example, I have a function named Add-License that adds a license to a microsoft account. However it only worked when I commented out the other params that aren't needed. Here is the code:

param (
    $command,
    $tenantID,
    $appID,
    # $emailresult, #If I don't comment these out, the Add-License function wont work. But I need these all here for other functions.
    # $empw,
    # $emname,
    # $emupn,
    # $emalias,
    # $fname,
    # $lname,
    # $disname,
    $emailaddress,
    $SkuIDresult
    

)

### functions that do other stuff
function Add-License {
    ## Connect to Microsoft Graph Powershell
    $StoreName = [System.Security.Cryptography.X509Certificates.StoreName]::My 
    $StoreLocation = [System.Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser
    $Store = [System.Security.Cryptography.X509Certificates.X509Store]::new($StoreName, $StoreLocation) 
    $Flag = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable
    $Certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($CertificateFilePath, $pfxPassword, $Flag)
    $Store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
    $Store.Add($Certificate)
    $Store.Close()
    [Convert]::ToBase64String($Certificate.GetRawCertData())
    $Thumbprint = $Certificate.Thumbprint
    Connect-MgGraph -ClientID $appID -TenantId $TenantId -CertificateThumbprint $Thumbprint 
    Set-MgUserLicense -UserId $emailaddress -addlicenses @{SkuId = $SkuIDresult} -RemoveLicenses @() 
    ## Disconnect from Microsoft Graph Powershell
    Disconnect-MgGraph
}
& $command

If I don't comment out the params, it will fail on the $emailaddress

Is there a way I can make a different list of params for each function so they don't get confused?

Thank you for your time,

UPDATE: I used @Mathias R. Jessen suggestion to try and add the params to the function itself then call the function. However this didn't work as I can't convert my arguments into a list from the outside.

I am using python to call the powershell module using the subprocess module. Because of this my python code looks something like this:

def flow_add_license_to_user_microsoft():
    sqlite_companysearch.company_userselection()
    intermedia_functions.email_selection_only()
    eopappidresult = sqlite_companysearch.comp_searchone.selection_results_eopappid
    onmdomainresult = sqlite_companysearch.comp_searchone.selection_results_onmdomain
    msubresult = sqlite_companysearch.comp_searchone.selection_results_msub
    subprocess.run(["powershell", "microsoft_functions.ps1", "Add-License", onmdomainresult, eopappidresult, intermedia_functions.email_selection_only.email_select, msubresult])
    return

So i need onmdomainresult eopappidresult intermedia_functions.email_selection_only.email_select and msubresult to show up as $tenantID $appID $emailaddress $SkuIDresult for the subprocess command to powershell. I hope this makes more sense.

I tried using what he said here:

param(
  [string]
  $CommandName,

  [System.Collections.IDictionary]
  $Arguments
)

### functions and what not
& $CommandName @Arguments

but I got an error saying:

microsoft_functions.ps1: Cannot process argument transformation on parameter 'Arguments'. Cannot convert the "jsffinancial2.onmicrosoft.com" value of type "System.String" to type "System.Collections.IDictionary"

Upvotes: 1

Views: 1174

Answers (2)

user16004320
user16004320

Reputation:

So I am going to give the answer to @Mathias as I think his answer will help others better if they ever search this.

However what fixed my issues was to add the actual argument flags in the my subprocess command when I use python to call the powershell module. I also added a DefaultParameterSetName to the arguments params.

Here is what my params look like in the script. I didn't put them in the function itself as it wasn't working for me:

param (
    $command,
    [CmdletBinding(DefaultParameterSetName = 'license')]
    $appID,
    [CmdletBinding(DefaultParameterSetName = 'license')]
    $tenantID,
    [CmdletBinding(DefaultParameterSetName = 'email')]
    $eoptenantID,
    [CmdletBinding(DefaultParameterSetName = 'email')]
    $emailresult,
    [CmdletBinding(DefaultParameterSetName = 'email')]
    $empw,
    [CmdletBinding(DefaultParameterSetName = 'email')]
    $emname,
    [CmdletBinding(DefaultParameterSetName = 'email')]
    $emupn,
    [CmdletBinding(DefaultParameterSetName = 'email')]
    $emalias,
    [CmdletBinding(DefaultParameterSetName = 'email')]
    $fname,
    [CmdletBinding(DefaultParameterSetName = 'email')]
    $lname,
    [CmdletBinding(DefaultParameterSetName = 'email')]
    $disname,
    [CmdletBinding(DefaultParameterSetName = 'license')]
    $emailaddress,
    [CmdletBinding(DefaultParameterSetName = 'license')]
    $SkuIDresult
)

Then from my python script I call which ever command I need like this:

subprocess.run(["powershell", "microsoft_functions.ps1", 
    "Reset-Email", "-appID", eopappidresult, 
    "-eoptenantID", onmdomainresult, 
    "-empw", intermedia_functions.email_pd.pd, 
    "-emailaddress", intermedia_functions.email_selection_only.email_select])

Upvotes: 0

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174435

First thing you'll want to do is add explicit parameters to Add-License instead of relying on variables inherited from the calling scope:

function Add-License {
    param(
      [string]$CertificateFilePath,
      [string]$PfxPassword,
      [string]$AppId,
      [string]$TenantId,
      [string]$EmailAddress,
      [guid]$SkuId
    )
    
    ## Connect to Microsoft Graph Powershell
    $StoreName = [System.Security.Cryptography.X509Certificates.StoreName]::My 
    $StoreLocation = [System.Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser
    $Store = [System.Security.Cryptography.X509Certificates.X509Store]::new($StoreName, $StoreLocation) 
    $Flag = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable
    $Certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($CertificateFilePath, $pfxPassword, $Flag)
    $Store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
    $Store.Add($Certificate)
    $Store.Close()
    [Convert]::ToBase64String($Certificate.GetRawCertData())
    $Thumbprint = $Certificate.Thumbprint
    Connect-MgGraph -ClientID $appID -TenantId $TenantId -CertificateThumbprint $Thumbprint 
    Set-MgUserLicense -UserId $EmailAddress -addlicenses @{SkuId = $SkuID} -RemoveLicenses @() 
    ## Disconnect from Microsoft Graph Powershell
    Disconnect-MgGraph
}

Now Add-License will no longer be affected by the values of the parameter variables from the script, because a more local variable (the parameter we've defined in Add-License's param() block) with the same name exists.

Since you want to provide different sets of parameter arguments do different commands dynamically, you might want to consider re-designing your script parameters to take a dictionary/hashtable of arguments instead of individual ones:

param(
  [string]
  $CommandName,

  [System.Collections.IDictionary]
  $Arguments
)

# ... function definitions here

& $CommandName @Arguments

The @Arguments syntax that I'm using here is known as splatting and it will cause PowerShell to pass the dictionary entries as named parameters to the command.

Now you can invoke Add-Licenses by calling the script like this:

$addLicenseArgs = @{ 
  CertificateFilePath = 'path\to\certfile.pfx'
  PfxPassword         = '<pfx password goes here>'
  AppId               = '<appId>'
  TenantId            = '<tenantId>'
  EmailAddress        = '[email protected]'
  SkuId               = '<SkuId>' -as [guid]
}

.\script.ps1 -CommandName Add-Licenses -Arguments $addLicenseArgs

Which, if we were to invoke Add-License directly, would be equivalent to calling:

Add-License -CertificateFilePath 'path\to\certfile.pfx' -PfxPassword '<pfx password goes here>' -AppId '<appId>' -TenantId '<tenantId>' -EmailAddress '[email protected]' -SkuId $('<SkuId>' -as [guid])

Upvotes: 2

Related Questions