Reputation:
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
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
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