Is there a way to have PowerShell display the options possible for a parameter? I have the following Parameter which requires one of the resource groups in Azure to be selected.
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true, HelpMessage = "Enter the name of the resource group you would like to use.")]
[ValidateScript( {$_ -in (Get-AzureRMResourceGroup | Select-Object -ExpandProperty ResourceGroupName)})]
[String]$ResourceGroup
)
ValidateScript will check to see if it is one of the Resource groups in Azure, but my question is how can I display a list of the resource groups so that the person running the script knows what possible options they can input for the parameter? Can I use Write-Host or something within the Param block?
Something like this would be great to display on the line above where they input the value for the parametera (but not static options I want the script to query azure and display the list of resource groups the user can choose):
Please choose one of the following resource Groups: RG1 RG2 RG3 RG4
Thank you.
As PetSerAI mentioned the answer is to use tab completion.
Related
I'm trying to pull out a listing of all groups in our Azure Active Directory org along with all the associated members (be them users, groups, contacts, etc).
Since I was unable to locate a method to do this through the various Microsoft portals with a simple export button I began the process of obtaining access to the Microsoft Graph API/SDK via Powershell.
I'm by no means a PowerShell expert as it's not one of my go-to scripts; however, from what I can tell the ability to pull group info in this fashion is fairly limited.
The following is what I've been able to accomplish thus far:
Pull in a list of the groups using Get-MgGroup -All
Use Get-MgGroupMembers to pull back a list of Directory Objects.
This is where I get stuck. From what I've read it looks like a Directory Object by default only returns the ID and the Deleted Date. I'd like to get a display Name for these objects; I can obviously do this by running the appropriate 'Get' cmdlet for the type of directory object (i.e. Get-MgUser); From what I can tell the type of directory object can't be gleaned via PowerShell with out 'trial-and-error'... This seems highly inefficient to simply get a displayName.
Is there a more effective way to determine either the displayName of a Directory Object via a PowerShell cmdlet or at the very least a type so I can write a case statement to run the right cmdlet on the first try?
For the record this is going to be incorporated in to a Powershell Script, the current iteration of which looks like this and sorta works okay... assuming the Id passed in $member.Id belongs to a User type directory object.
Connect-MgGraph
$groups=Get-mgGroup -All
ForEach ($group in $groups){
$members = #{}
$members = Get-MgGroupMember -GroupId $group.Id -All
ForEach ($member in $members){
$user = Get-MgUser $member.Id
Write-Output $object.ODataType
Write-output $group.DisplayName "," $member.Id "," $user.UserType"," $user.DisplayName "," $user.UserPrincipalName "," $user.Mail >> C:scripts\Azure_Groups.txt
}
}
Would appreciate any direction/assistance on this. Thanks in advance!
Not sure why its not returning all the details on the PowerShell query:
This is working fine in MS Graph Explorer with the results showing all the details of the members:
For more details:https://learn.microsoft.com/en-us/graph/api/group-list-members?view=graph-rest-1.0&tabs=http#example-1-get-the-direct-membership-in-a-group
This question already has an answer here:
Can a PowerShell function handle multiple input types?
(1 answer)
Closed 1 year ago.
I have a script that deals with Active Directory User objects (Microsoft.ActiveDirectory.Management.ADUser). I explicitly list the type in the function that processes these objects:
function Write-ADUser {
param (
[Microsoft.ActiveDirectory.Management.ADUser]$user
)
(...)
I also want this function to be able to take objects from remote sessions. The challenge is that objects returned from remote sessions are of the deserialized variety:
C:\> icm -session $sess { get-aduser -identity testuser -credential $cred } | gm
TypeName: Deserialized.Microsoft.ActiveDirectory.Management.ADUser
Is there a way to have my function param block accept either the "live" object or the deserialized variant? My function doesn't need to use methods - the deserialized variant has (or can be made to have) what I need.
The parameter sets idea was interesting and a helpful lead. After reviewing the documentation, this is the best option I could come up with:
function Write-ADUser {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
[ValidateScript({
if ($_.GetType().Name -notin #('ADUser', 'PSObject')) {
throw ("Error: Invalid type ````{0}'' - expecting ADUser.") -f $_.GetType().Name
} else {
$true
}
})]
$user
)
...
One other comment. When looking into parameter sets I kept getting an error about ADUser. However, upon further digging I believe that error is because the Microsoft Active Directory PowerShell module isn't installed on my test computer. Therefore, the 'ADUser' type isn't defined. Because I want this script to run on computers that don't necessarily have the ADModule I am using the above logic. However, if I could guarantee that ADModule was present then I think parameter sets would be the way to go.
Apologies for not providing clearer requirements. I'm still learning PowerShell...
Note - updated based on feedback from #zett42
I am trying to setup dynamic parameters that vary depending on if you are adding or modifying/removing a drone. Ex: If you are adding a drone you would need its IP/Name/Location.. To remove the drone you would only need its name. I have tried looking online and try various examples I've seen but I am completely stuck here. Any help to steer me in the right direction would be appreciated. I am somewhat new to powershell. Here's what I have.
[CmdletBinding(SupportsShouldProcess=$True)]
Param( [Parameter(Mandatory=$true,
HelpMessage = "Add remove or Modify a drone?")]
[ValidateSet("Add", "Remove", "Modify")]
[String]$Action)
DynamicParam{
if ($action = "Add"){
Param( [Parameter(Mandatory)]
[ValidateSet("NorthAmerica", "SouthAmerica", "NorthernEurope","UK", "CEE", "FRMALU", "SouthernEurope", "AsiaPacific")]
[String]$curRegion,
[Parameter(Mandatory)]
[IPAddress]$ip,
[Parameter(Mandatory)]
[String]$droneName)
}
if ($action = "Remove"){
Param(
[Parameter(Mandatory)]
[string]$droneRemoveName)
}
}
Consider driving your parameter constraints with named Parameter Sets instead. I'm suggesting this because dynamic parameters don't work quite like you think they do, but named parameter sets are an easier way to solve your problem. In case you're interested, here's a blog post explaining how to use dynamic parameters and it winds up being pretty manual parameter handling.
You can add a parameter to more than one parameter set depending on the contexts in which each parameter is required. Instead of using -Action ACTION as a driver for a dynamic parameter, use a [switch] instead, such as -Add and -Remove, and have each switch part of its own parameter set. For example, when defining your parameters, it may look something like this:
Param(
[Parameter(ParameterSetName='Remove')]
[switch]$Remove,
[Parameter(ParameterSetName='Add')]
[switch]$Add,
[Parameter(ParameterSetName='Remove', Mandatory)]
[Parameter(ParameterSetName='Add', Mandatory)]
[string]$IPAddress
)
In this example, -IPAddress is valid when you use the -Add or -Remove switch, but won't be relavant outside of this context. Of course, if a parameter should only be valid for a certain parameter set, don't define it under more than one parameter set name.
If you want to make sure at least one "action" switch is defined before executing, you can check that one of those parameters was used when invoking the cmdlet by checking $PSBoundParameters:
('Add' -in $PSBoundParameters.Keys) -Or ('Remove' -in $PSBoundParameters.Keys)
Good morning, everyone,
I have a problem in retrieving information from SharePoint groups. I do it in a workflow, first I get the list of all groups and then I use it in a foreach-parallel to list the members of these groups.
The problem is that the connection doesn't seem to be maintaining and my query doesn't recover all the groups.
Here is a piece of the code:
workflow GetGroup {
param(
[Parameter(Mandatory)]
[String]$SPOSite,
[System.Management.Automation.PSCredential]$SPOCreds
)
$KeepAlive = Connect-PnPOnline -Url $SPOSite -Credentials $SPOCreds -ReturnConnection
$GetGroups = Get-PnPGroup
ForEach -Parallel -ThrottleLimit 512 ($Group in $GetGroups)
{
$GroupName = $Group.LoginName
$Users = Get-PnPGroupMembers -Identity $groupName -Connection $workFlow:KeepAlive
}
}
GetGroup -SPOSite "https://xxx.sharepoint.com/sites/xx -SPOCreds (Get-Credential)
The expected result would be an array initialized at the beginning of the workflow with a PSCustomObject object that is added to our array. This table is made up of 3 things: The name of the group, the names of the people in that group, the emails of the people.
Unfortunately the table is only partially generated because a workflow here is the error I find nothing on the subject:
Impossible to link the "Connection" parameter. Impossible to convert the value "SharePointPnP.PowerShell.Commands.Base.SPOnlineConnection" of the type "SharePointPnP.PowerShell.Commands.
Deserialized.SharePointPnPnP.PowerShell.Commands.Base.SPOnlineConnection"
Thank you for your help.
I ran into the same error in a similar scenario, and this article helped me. Workflow is converting the Connection object ($KeepAlive in your case) to a deserialized format, and so the other cmdlet doesn't accept it. You will just have to wrap those cmdlets with InlineScript, or use a PowerShell script runbook instead of a PowerShell workflow runbook.
I'm new to powershell and my first module is for simply adding users to the local admin group on remote computers. It looks like:
function AddAdmin {
[CmdletBinding()]
Param(
[Parameter (Mandatory=$True,ValueFromPipeline=$True,Position=1) ]
[string[]]$Computer,
[Parameter (Mandatory=$True,ValueFromPipeline=$True,Position=2) ]
[string]$username
)
$Domain = "the domain"
$Group = [ADSI]"WinNT://$Computer/Administrators,group"
$Usertoadd = [ADSI]"WinNT://$Domain/$username,user"
$Group.Add($Usertoadd.Path)
}
so I can just type addadmin computername username and it gets added. I want to do the same for groups, the problem I'm having is figuring out how to set a parameter that has multiple values/words. For example let's say I want to add a group called Executive Team to local admins. addadmin computername executive team doesn't work - it only picks up executive as the value.
Googled quite a bit and can't seem to figure this out, I'm sure I'm missing something simple.
You just have to put the multiple words value into double quotes :
addadmin computername "executive team"
Positions start at 0, just FYI, and while JPBlanc's answer is correct (and honestly better from a technical standpoint) you should be able to add this to your Parameter list for the User Name to get the same results without having to put them in quotes.
ValueFromRemainingArguments = $true