Azure / azure-powershell

Microsoft Azure PowerShell
Other
4.26k stars 3.86k forks source link

New-AzActionGroup Please stop these archaic witchery practices, compel to hashtables. #12267

Open Manbearpiet opened 4 years ago

Manbearpiet commented 4 years ago

Description

I tried creating an actiongroup today, however I found something in the help of this cmdlet which I haven't seen in a while. The cmdlet forces me to create a dictionary which creates multiple lines of code, where I'm used to creating resources from a single line of code with in example a line like this:

    New-AzActionGroup -ActionGroupId 'ActionHank' -WebhookProperty @{"superactionuri"="https://allyouralertsarebelongto.me"}

However I'm required to create a dictionary, using New-Object. This seems like a robust, but less user-friendly way of receiving an object which contains a string as a name and a string as a value. Is it possible to explore options to support use of for example hashtables? The steps I've supplied are from the help documentation of New-AzActionGroup. My thanks in advance and I wish you all a pleasant day!

Steps to reproduce

    PS C:\>$dict = New-Object "System.Collections.Generic.Dictionary``2[System.String,System.String]"
    PS C:\>$dict.Add('key1', 'value1')
    PS C:\>$actionGrp1 = New-AzActionGroup -ActionGroupId 'actiongr1' -WebhookProperty $dict

Environment data

$PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.0.2
PSEdition                      Core
GitCommitId                    7.0.2
OS                             Microsoft Windows 10.0.18363
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Module versions

ModuleType Version    PreRelease Name                                PSEdition ExportedCommands
---------- -------    ---------- ----                                --------- ----------------
Script     4.3.0                 Az                                  Core,Desk
Script     4.1.0                 Az                                  Core,Desk
Script     3.7.0                 Az                                  Core,Desk
Script     1.9.0                 Az.Accounts                         Core,Desk {Disable-AzDataCollection, Disable-AzContextAutosave, Enable-AzDa…
Script     1.8.0                 Az.Accounts                         Core,Desk {Disable-AzDataCollection, Disable-AzContextAutosave, Enable-AzDa…
Script     1.7.5                 Az.Accounts                         Core,Desk {Disable-AzDataCollection, Disable-AzContextAutosave, Enable-AzDa…
Script     1.7.4                 Az.Accounts                         Core,Desk {Disable-AzDataCollection, Disable-AzContextAutosave, Enable-AzDa…
Script     1.1.1                 Az.Advisor                          Core,Desk {Get-AzAdvisorRecommendation, Enable-AzAdvisorRecommendation, Dis…
Script     1.1.2                 Az.Aks                              Core,Desk {Get-AzAks, New-AzAks, Remove-AzAks, Import-AzAksCredential…}
Script     1.1.1                 Az.Aks                              Core,Desk {Get-AzAks, New-AzAks, Remove-AzAks, Import-AzAksCredential…}
Script     1.0.3                 Az.Aks                              Core,Desk {Get-AzAks, New-AzAks, Remove-AzAks, Import-AzAksCredential…}
Script     1.1.3                 Az.AnalysisServices                 Core,Desk {Resume-AzAnalysisServicesServer, Suspend-AzAnalysisServicesServe…
Script     1.1.2                 Az.AnalysisServices                 Core,Desk {Resume-AzAnalysisServicesServer, Suspend-AzAnalysisServicesServe…
Script     2.0.1                 Az.ApiManagement                    Core,Desk {Add-AzApiManagementApiToProduct, Add-AzApiManagementProductToGro…
Script     2.0.0                 Az.ApiManagement                    Core,Desk {Add-AzApiManagementApiToProduct, Add-AzApiManagementProductToGro…
Script     1.4.0                 Az.ApiManagement                    Core,Desk {Add-AzApiManagementApiToProduct, Add-AzApiManagementProductToGro…
Script     1.1.0                 Az.ApplicationInsights              Core,Desk {Get-AzApplicationInsights, New-AzApplicationInsights, Remove-AzA…
Script     1.0.3                 Az.ApplicationInsights              Core,Desk {Get-AzApplicationInsights, New-AzApplicationInsights, Remove-AzA…
Script     1.3.6                 Az.Automation                       Core,Desk {Get-AzAutomationHybridWorkerGroup, Remove-AzAutomationHybridWork…
Script     3.1.0                 Az.Batch                            Core,Desk {Remove-AzBatchAccount, Get-AzBatchAccount, Get-AzBatchAccountKey…
Script     3.0.0                 Az.Batch                            Core,Desk {Remove-AzBatchAccount, Get-AzBatchAccount, Get-AzBatchAccountKey…
Script     2.0.2                 Az.Batch                            Core,Desk {Remove-AzBatchAccount, Get-AzBatchAccount, Get-AzBatchAccountKey…
Script     1.0.3                 Az.Billing                          Core,Desk {Get-AzBillingInvoice, Get-AzBillingPeriod, Get-AzEnrollmentAccou…
Script     1.0.2                 Az.Billing                          Core,Desk {Get-AzBillingInvoice, Get-AzBillingPeriod, Get-AzEnrollmentAccou…
Script     1.4.3                 Az.Cdn                              Core,Desk {Get-AzCdnProfile, Get-AzCdnProfileSsoUrl, New-AzCdnProfile, Remo…
Script     1.4.2                 Az.Cdn                              Core,Desk {Get-AzCdnProfile, Get-AzCdnProfileSsoUrl, New-AzCdnProfile, Remo…
Script     1.5.0                 Az.CognitiveServices                Core,Desk {Get-AzCognitiveServicesAccount, Get-AzCognitiveServicesAccountKe…
Script     1.3.0                 Az.CognitiveServices                Core,Desk {Get-AzCognitiveServicesAccount, Get-AzCognitiveServicesAccountKe…
Script     1.2.3                 Az.CognitiveServices                Core,Desk {Get-AzCognitiveServicesAccount, Get-AzCognitiveServicesAccountKe…
Script     4.2.0                 Az.Compute                          Core,Desk {Remove-AzAvailabilitySet, Get-AzAvailabilitySet, New-AzAvailabil…
Script     4.1.0                 Az.Compute                          Core,Desk {Remove-AzAvailabilitySet, Get-AzAvailabilitySet, New-AzAvailabil…
Script     3.7.0                 Az.Compute                          Core,Desk {Remove-AzAvailabilitySet, Get-AzAvailabilitySet, New-AzAvailabil…
Script     3.6.0                 Az.Compute                          Core,Desk {Remove-AzAvailabilitySet, Get-AzAvailabilitySet, New-AzAvailabil…
Script     1.0.3                 Az.ContainerInstance                Core,Desk {New-AzContainerGroup, Get-AzContainerGroup, Remove-AzContainerGr…
Script     1.1.1                 Az.ContainerRegistry                Core,Desk {New-AzContainerRegistry, Get-AzContainerRegistry, Update-AzConta…
Script     1.1.0                 Az.DataBoxEdge                      Core,Desk {Get-AzDataBoxEdgeJob, Get-AzDataBoxEdgeDevice, Invoke-AzDataBoxE…
Script     1.8.2                 Az.DataFactory                      Core,Desk {Set-AzDataFactoryV2, Update-AzDataFactoryV2, Get-AzDataFactoryV2…
Script     1.8.0                 Az.DataFactory                      Core,Desk {Set-AzDataFactoryV2, Update-AzDataFactoryV2, Get-AzDataFactoryV2…
Script     1.7.0                 Az.DataFactory                      Core,Desk {Set-AzDataFactoryV2, Update-AzDataFactoryV2, Get-AzDataFactoryV2…
Script     1.0.2                 Az.DataLakeAnalytics                Core,Desk {Get-AzDataLakeAnalyticsDataSource, New-AzDataLakeAnalyticsCatalo…
Script     1.2.8                 Az.DataLakeStore                    Core,Desk {Get-AzDataLakeStoreTrustedIdProvider, Remove-AzDataLakeStoreTrus…
Script     1.0.0                 Az.DataShare                        Core,Desk {New-AzDataShareAccount, Get-AzDataShareAccount, Remove-AzDataSha…
Script     1.1.0                 Az.DeploymentManager                Core,Desk {Get-AzDeploymentManagerArtifactSource, New-AzDeploymentManagerAr…
Script     1.0.0                 Az.DesktopVirtualization            Core,Desk {Disconnect-AzWvdUserSession, Get-AzWvdApplication, Get-AzWvdAppl…
Script     1.0.2                 Az.DevTestLabs                      Core,Desk {Get-AzDtlAllowedVMSizesPolicy, Get-AzDtlAutoShutdownPolicy, Get-…
Script     1.1.2                 Az.Dns                              Core,Desk {Get-AzDnsRecordSet, New-AzDnsRecordConfig, Remove-AzDnsRecordSet…
Script     1.2.3                 Az.EventGrid                        Core,Desk {New-AzEventGridTopic, Get-AzEventGridTopic, Set-AzEventGridTopic…
Script     1.5.0                 Az.EventHub                         Core,Desk {New-AzEventHubNamespace, Get-AzEventHubNamespace, Set-AzEventHub…
Script     1.4.3                 Az.EventHub                         Core,Desk {New-AzEventHubNamespace, Get-AzEventHubNamespace, Set-AzEventHub…
Script     1.5.0                 Az.FrontDoor                        Core,Desk {New-AzFrontDoor, Get-AzFrontDoor, Set-AzFrontDoor, Remove-AzFron…
Script     1.4.0                 Az.FrontDoor                        Core,Desk {New-AzFrontDoor, Get-AzFrontDoor, Set-AzFrontDoor, Remove-AzFron…
Script     1.0.1                 Az.Functions                        Core,Desk {Get-AzFunctionApp, Get-AzFunctionAppAvailableLocation, Get-AzFun…
Script     3.3.0                 Az.HDInsight                        Core,Desk {Get-AzHDInsightJob, New-AzHDInsightSqoopJobDefinition, Wait-AzHD…
Script     3.2.0                 Az.HDInsight                        Core,Desk {Get-AzHDInsightJob, New-AzHDInsightSqoopJobDefinition, Wait-AzHD…
Script     3.1.0                 Az.HDInsight                        Core,Desk {Get-AzHDInsightJob, New-AzHDInsightSqoopJobDefinition, Wait-AzHD…
Script     1.1.0                 Az.HealthcareApis                   Core,Desk {New-AzHealthcareApisService, Remove-AzHealthcareApisService, Set…
Script     1.0.2                 Az.HealthcareApis                   Core,Desk {New-AzHealthcareApisService, Remove-AzHealthcareApisService, Set…
Script     1.0.1                 Az.HealthcareApis                   Core,Desk {New-AzHealthcareApisService, Remove-AzHealthcareApisService, Set…
Script     2.5.0                 Az.IotHub                           Core,Desk {Add-AzIotHubKey, Get-AzIotHubEventHubConsumerGroup, Get-AzIotHub…
Script     2.3.0                 Az.IotHub                           Core,Desk {Add-AzIotHubKey, Get-AzIotHubEventHubConsumerGroup, Get-AzIotHub…
Script     2.0.0                 Az.KeyVault                         Core,Desk {Add-AzKeyVaultCertificate, Update-AzKeyVaultCertificate, Stop-Az…
Script     1.5.2                 Az.KeyVault                         Core,Desk {Add-AzKeyVaultCertificate, Update-AzKeyVaultCertificate, Stop-Az…
Script     1.3.2                 Az.LogicApp                         Core,Desk {Get-AzIntegrationAccountAgreement, Get-AzIntegrationAccountAssem…
Script     1.1.3                 Az.MachineLearning                  Core,Desk {Move-AzMlCommitmentAssociation, Get-AzMlCommitmentAssociation, G…
Script     1.0.2                 Az.ManagedServices                  Core,Desk {Get-AzManagedServicesAssignment, New-AzManagedServicesAssignment…
Script     1.0.2                 Az.MarketplaceOrdering              Core,Desk {Get-AzMarketplaceTerms, Set-AzMarketplaceTerms}
Script     1.1.1                 Az.Media                            Core,Desk {Sync-AzMediaServiceStorageKey, Set-AzMediaServiceKey, Get-AzMedi…
Script     2.0.1                 Az.Monitor                          Core,Desk {Get-AzMetricDefinition, Get-AzMetric, Remove-AzLogProfile, Get-A…
Script     2.0.0                 Az.Monitor                          Core,Desk {Get-AzMetricDefinition, Get-AzMetric, Remove-AzLogProfile, Get-A…
Script     1.6.2                 Az.Monitor                          Core,Desk {Get-AzMetricDefinition, Get-AzMetric, Remove-AzLogProfile, Get-A…
Script     3.1.0                 Az.Network                          Core,Desk {Add-AzApplicationGatewayAuthenticationCertificate, Get-AzApplica…
Script     3.0.0                 Az.Network                          Core,Desk {Add-AzApplicationGatewayAuthenticationCertificate, Get-AzApplica…
Script     2.4.0                 Az.Network                          Core,Desk {Add-AzApplicationGatewayAuthenticationCertificate, Get-AzApplica…
Script     1.1.1                 Az.NotificationHubs                 Core,Desk {Get-AzNotificationHub, Get-AzNotificationHubAuthorizationRule, G…
Script     2.2.0                 Az.OperationalInsights              Core,Desk {New-AzOperationalInsightsAzureActivityLogDataSource, New-AzOpera…
Script     2.0.0                 Az.OperationalInsights              Core,Desk {New-AzOperationalInsightsAzureActivityLogDataSource, New-AzOpera…
Script     1.3.4                 Az.OperationalInsights              Core,Desk {New-AzOperationalInsightsAzureActivityLogDataSource, New-AzOpera…
Script     1.3.1                 Az.PolicyInsights                   Core,Desk {Get-AzPolicyEvent, Get-AzPolicyState, Get-AzPolicyStateSummary, …
Script     1.3.0                 Az.PolicyInsights                   Core,Desk {Get-AzPolicyEvent, Get-AzPolicyState, Get-AzPolicyStateSummary, …
Script     1.2.1                 Az.PolicyInsights                   Core,Desk {Get-AzPolicyEvent, Get-AzPolicyState, Get-AzPolicyStateSummary, …
Script     1.1.2                 Az.PowerBIEmbedded                  Core,Desk {Remove-AzPowerBIWorkspaceCollection, Get-AzPowerBIWorkspaceColle…
Script     1.1.1                 Az.PowerBIEmbedded                  Core,Desk {Remove-AzPowerBIWorkspaceCollection, Get-AzPowerBIWorkspaceColle…
Script     1.0.3                 Az.PrivateDns                       Core,Desk {Get-AzPrivateDnsZone, Remove-AzPrivateDnsZone, Set-AzPrivateDnsZ…
Script     1.0.2                 Az.PrivateDns                       Core,Desk {Get-AzPrivateDnsZone, Remove-AzPrivateDnsZone, Set-AzPrivateDnsZ…
Script     2.10.0                Az.RecoveryServices                 Core,Desk {Get-AzRecoveryServicesBackupProperty, Get-AzRecoveryServicesVaul…
Script     2.9.0                 Az.RecoveryServices                 Core,Desk {Get-AzRecoveryServicesBackupProperty, Get-AzRecoveryServicesVaul…
Script     2.8.0                 Az.RecoveryServices                 Core,Desk {Get-AzRecoveryServicesBackupProperty, Get-AzRecoveryServicesVaul…
Script     1.2.1                 Az.RedisCache                       Core,Desk {Remove-AzRedisCachePatchSchedule, New-AzRedisCacheScheduleEntry,…
Script     1.0.3                 Az.Relay                            Core,Desk {New-AzRelayNamespace, Get-AzRelayNamespace, Set-AzRelayNamespace…
Script     2.2.0                 Az.Resources                        Core,Desk {Get-AzProviderOperation, Remove-AzRoleAssignment, Get-AzRoleAssi…
Script     2.0.1                 Az.Resources                        Core,Desk {Get-AzProviderOperation, Remove-AzRoleAssignment, Get-AzRoleAssi…
Script     1.13.0                Az.Resources                        Core,Desk {Get-AzProviderOperation, Remove-AzRoleAssignment, Get-AzRoleAssi…
Script     0.7.8                 Az.Security                         Core,Desk {Get-AzSecurityAlert, Set-AzSecurityAlert, Get-AzSecurityAutoProv…
Script     0.7.7                 Az.Security                         Core,Desk {Get-AzSecurityAlert, Set-AzSecurityAlert, Get-AzSecurityAutoProv…
Script     1.4.1                 Az.ServiceBus                       Core,Desk {New-AzServiceBusNamespace, Get-AzServiceBusNamespace, Set-AzServ…
Script     2.1.0                 Az.ServiceFabric                    Core,Desk {Add-AzServiceFabricClientCertificate, Add-AzServiceFabricCluster…
Script     2.0.1                 Az.ServiceFabric                    Core,Desk {Add-AzServiceFabricClientCertificate, Add-AzServiceFabricCluster…
Script     1.1.1                 Az.SignalR                          Core,Desk {New-AzSignalR, Get-AzSignalR, Get-AzSignalRKey, New-AzSignalRKey…
Script     2.8.0                 Az.Sql                              Core,Desk {Get-AzSqlDatabaseTransparentDataEncryption, Get-AzSqlDatabaseTra…
Script     2.6.1                 Az.Sql                              Core,Desk {Get-AzSqlDatabaseTransparentDataEncryption, Get-AzSqlDatabaseTra…
Script     2.5.0                 Az.Sql                              Core,Desk {Get-AzSqlDatabaseTransparentDataEncryption, Get-AzSqlDatabaseTra…
Script     1.1.0                 Az.SqlVirtualMachine                Core,Desk {New-AzSqlVM, Get-AzSqlVM, Update-AzSqlVM, Remove-AzSqlVM…}
Script     2.2.0                 Az.Storage                          Core,Desk {Get-AzStorageAccount, Get-AzStorageAccountKey, New-AzStorageAcco…
Script     2.0.0                 Az.Storage                          Core,Desk {Get-AzStorageAccount, Get-AzStorageAccountKey, New-AzStorageAcco…
Script     1.13.0                Az.Storage                          Core,Desk {Get-AzStorageAccount, Get-AzStorageAccountKey, New-AzStorageAcco…
Script     1.2.3                 Az.StorageSync                      Core,Desk {Invoke-AzStorageSyncCompatibilityCheck, New-AzStorageSyncService…
Script     1.0.1                 Az.StreamAnalytics                  Core,Desk {Get-AzStreamAnalyticsFunction, Get-AzStreamAnalyticsDefaultFunct…
Script     1.0.0                 Az.Support                          Core,Desk {Get-AzSupportService, Get-AzSupportProblemClassification, Get-Az…
Script     1.0.4                 Az.TrafficManager                   Core,Desk {Add-AzTrafficManagerCustomHeaderToEndpoint, Remove-AzTrafficMana…
Script     1.0.3                 Az.TrafficManager                   Core,Desk {Add-AzTrafficManagerCustomHeaderToEndpoint, Remove-AzTrafficMana…
Script     1.10.0                Az.Websites                         Core,Desk {Get-AzAppServicePlan, Set-AzAppServicePlan, New-AzAppServicePlan…
Script     1.9.0                 Az.Websites                         Core,Desk {Get-AzAppServicePlan, Set-AzAppServicePlan, New-AzAppServicePlan…
Script     1.8.0                 Az.Websites                         Core,Desk {Get-AzAppServicePlan, Set-AzAppServicePlan, New-AzAppServicePlan…
Binary     2.0.2.76              AzureAD                             Desk
Binary     2.0.2.102             AzureADPreview                      Desk

Debug output

New-AzActionGroup: Cannot bind parameter 'WebhookProperty'. Cannot create object of type "System.Collections.Generic.Dictionary`2[System.String,System.String]". The superactionuri property was not found for the System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]] object. The available property is: [Comparer <System.Collections.Generic.IEqualityComparer`1[[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]>] , [Count <System.Int32>] , [Keys <System.Collections.Generic.Dictionary`2+KeyCollection[[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]>] , [Values <System.Collections.Generic.Dictionary`2+ValueCollection[[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]>] , [IsReadOnly <System.Boolean>] , [IsFixedSize <System.Boolean>] , [SyncRoot <System.Object>] , [IsSynchronized <System.Boolean>]

Error output

   HistoryId: 10

Message        : Cannot bind parameter 'WebhookProperty'. Cannot create object of type
                 "System.Collections.Generic.Dictionary`2[System.String,System.String]". The superactionuri property was not found for the
                 System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral,
                 PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral,
                 PublicKeyToken=7cec85d7bea7798e]] object. The available property is: [Comparer
                 <System.Collections.Generic.IEqualityComparer`1[[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral,
                 PublicKeyToken=7cec85d7bea7798e]]>] , [Count <System.Int32>] , [Keys
                 <System.Collections.Generic.Dictionary`2+KeyCollection[[System.String, System.Private.CoreLib, Version=4.0.0.0,
                 Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral,
                 PublicKeyToken=7cec85d7bea7798e]]>] , [Values <System.Collections.Generic.Dictionary`2+ValueCollection[[System.String,
                 System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String,
                 System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]>] , [IsReadOnly <System.Boolean>] ,
                 [IsFixedSize <System.Boolean>] , [SyncRoot <System.Object>] , [IsSynchronized <System.Boolean>]
StackTrace     :    at System.Management.Automation.ParameterBinderBase.CoerceTypeAsNeeded(CommandParameterInternal argument, String
                 parameterName, Type toType, ParameterCollectionTypeInformation collectionTypeInfo, Object currentValue)
                    at System.Management.Automation.ParameterBinderBase.BindParameter(CommandParameterInternal parameter,
                 CompiledCommandParameter parameterMetadata, ParameterBindingFlags flags)
                    at System.Management.Automation.CmdletParameterBinderController.BindParameter(CommandParameterInternal argument,
                 MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
                    at System.Management.Automation.CmdletParameterBinderController.BindParameter(UInt32 parameterSets, CommandParameterInternal
                 argument, MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
                    at System.Management.Automation.CmdletParameterBinderController.BindParameters(UInt32 parameterSets, Collection`1 arguments)
                    at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParametersNoValidation(Collection`1 arguments)
                    at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection`1 arguments)
                    at System.Management.Automation.CommandProcessor.BindCommandLineParameters()
                    at System.Management.Automation.CommandProcessor.Prepare(IDictionary psDefaultParameterValues)
                    at System.Management.Automation.CommandProcessorBase.DoPrepare(IDictionary psDefaultParameterValues)
                    at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream)
                    at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
                 --- End of stack trace from previous location where exception was thrown ---
                    at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
                    at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][]
                 pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext funcContext)
                    at System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(InterpretedFrame frame)
                    at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
Exception      : System.Management.Automation.ParameterBindingException
InvocationInfo : {New-AzActionGroup}
Line           :     New-AzActionGroup -ActionGroupId 'ActionHank' -WebhookProperty @{"superactionuri"="https://allyouralertsarebelongto.me"}
Position       : At line:1 char:68
                 + … ookProperty @{"superactionuri"="https://allyouralertsarebelongto.me"} …
                 +               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HistoryId      : 10

Message        : Cannot create object of type "System.Collections.Generic.Dictionary`2[System.String,System.String]". The superactionuri
                 property was not found for the System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=4.0.0.0,
                 Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral,
                 PublicKeyToken=7cec85d7bea7798e]] object. The available property is: [Comparer
                 <System.Collections.Generic.IEqualityComparer`1[[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral,
                 PublicKeyToken=7cec85d7bea7798e]]>] , [Count <System.Int32>] , [Keys
                 <System.Collections.Generic.Dictionary`2+KeyCollection[[System.String, System.Private.CoreLib, Version=4.0.0.0,
                 Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral,
                 PublicKeyToken=7cec85d7bea7798e]]>] , [Values <System.Collections.Generic.Dictionary`2+ValueCollection[[System.String,
                 System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String,
                 System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]>] , [IsReadOnly <System.Boolean>] ,
                 [IsFixedSize <System.Boolean>] , [SyncRoot <System.Object>] , [IsSynchronized <System.Boolean>]
StackTrace     :    at System.Management.Automation.LanguagePrimitives.ConvertViaNoArgumentConstructor.Convert(Object valueToConvert, Type
                 resultType, Boolean recursion, PSObject originalValueToConvert, IFormatProvider formatProvider, TypeTable backupTable, Boolean
                 ignoreUnknownMembers)
                    at System.Management.Automation.LanguagePrimitives.ConvertViaNoArgumentConstructor.Convert(Object valueToConvert, Type
                 resultType, Boolean recursion, PSObject originalValueToConvert, IFormatProvider formatProvider, TypeTable backupTable)
                    at System.Management.Automation.LanguagePrimitives.ConversionData`1.Invoke(Object valueToConvert, Type resultType, Boolean
                 recurse, PSObject originalValueToConvert, IFormatProvider formatProvider, TypeTable backupTable)
                    at System.Management.Automation.LanguagePrimitives.ConvertTo(Object valueToConvert, Type resultType, Boolean recursion,
                 IFormatProvider formatProvider, TypeTable backupTypeTable)
                    at System.Management.Automation.ParameterBinderBase.CoerceTypeAsNeeded(CommandParameterInternal argument, String
                 parameterName, Type toType, ParameterCollectionTypeInformation collectionTypeInfo, Object currentValue)
Exception      : System.Management.Automation.PSInvalidCastException
InvocationInfo : {New-AzActionGroup}
Line           :     New-AzActionGroup -ActionGroupId 'ActionHank' -WebhookProperty @{"superactionuri"="https://allyouralertsarebelongto.me"}
Position       : At line:1 char:68
                 + … ookProperty @{"superactionuri"="https://allyouralertsarebelongto.me"} …
                 +               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HistoryId      : 10

Message        : The superactionuri property was not found for the System.Collections.Generic.Dictionary`2[[System.String,
                 System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String,
                 System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]] object. The available property is:
                 [Comparer <System.Collections.Generic.IEqualityComparer`1[[System.String, System.Private.CoreLib, Version=4.0.0.0,
                 Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]>] , [Count <System.Int32>] , [Keys
                 <System.Collections.Generic.Dictionary`2+KeyCollection[[System.String, System.Private.CoreLib, Version=4.0.0.0,
                 Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral,
                 PublicKeyToken=7cec85d7bea7798e]]>] , [Values <System.Collections.Generic.Dictionary`2+ValueCollection[[System.String,
                 System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String,
                 System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]>] , [IsReadOnly <System.Boolean>] ,
                 [IsFixedSize <System.Boolean>] , [SyncRoot <System.Object>] , [IsSynchronized <System.Boolean>]
StackTrace     :    at System.Management.Automation.LanguagePrimitives.CreateMemberNotFoundError(PSObject pso, DictionaryEntry property, Type
                 resultType)
                    at System.Management.Automation.LanguagePrimitives.SetObjectProperties(Object o, IDictionary properties, Type resultType,
                 MemberNotFoundError memberNotFoundErrorAction, MemberSetValueError memberSetValueErrorAction, Boolean enableMethodCall,
                 IFormatProvider formatProvider, Boolean recursion, Boolean ignoreUnknownMembers)
                    at System.Management.Automation.LanguagePrimitives.ConvertViaNoArgumentConstructor.Convert(Object valueToConvert, Type
                 resultType, Boolean recursion, PSObject originalValueToConvert, IFormatProvider formatProvider, TypeTable backupTable, Boolean
                 ignoreUnknownMembers)
Exception      : System.InvalidOperationException
InvocationInfo : {New-AzActionGroup}
Line           :     New-AzActionGroup -ActionGroupId 'ActionHank' -WebhookProperty @{"superactionuri"="https://allyouralertsarebelongto.me"}
Position       : At line:1 char:68
                 + … ookProperty @{"superactionuri"="https://allyouralertsarebelongto.me"} …
                 +               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HistoryId      : 10
vexx32 commented 4 years ago

Several things bother me about this (nice write up btw!).

One, when did documenting for PSv2 become a priority? This syntax is unnecessary, slow, archaic, and completely obtuse:

$dict = New-Object "System.Collections.Generic.Dictionary``2[System.String,System.String]"

Even if this was necessary (it's not, at all) this is probably the slowest and most arcane way you could think up to write this line of code.

$dict = [System.Collections.Generic.Dictionary[string, string]]::new()

That's perfectly serviceable. Please revise your docs. Even if you must support PS4 or below, there's absolutely no need to include the `2 nonsense, nor to fully qualify System.String; we have type accelerators for a reason.


That aside, this notion of providing a strongly-typed dictionary is all well and good, but it's not very compatible with PowerShell, which often relies on loose type restrictions for convenience.

Even if you must internally use such a dictionary, requiring one as input from PowerShell is just being needlessly difficult. PowerShell provides ample conversion methods for most types to make this easier. It would make interfacing with the cmdlet significantly easier to just do conversions as needed, and accept a standard hashtable as input like the rest of PowerShell does.

[Parameter]
public Hashtable InputParam = null;

// ...

Dictionary<string, string> convertedDict = new Dictionary<string, string>(inputParam.Count);
foreach (var key in InputParam.Keys)
{
    convertedDict.Add(
        LanguagePrimitives.ConvertTo<string>(key),
        LanguagePrimitives.ConvertTo<string>(value));
}

Please design PowerShell interfaces to be compatible with the PowerShell ecosystem. 💖

markcowl commented 4 years ago

Yes, we don't explicitly have this in our design guidelines, but it should be there - we have been requiring new cmdlets to follow this pattern for some time, and the cmdlet generator explicitly follows this pattern (Hashtables instead of Dictionary types).

In this case, we would have to worry about breaking changes if we changed the type, but short of that, if we added a type converter so that you could provide inline hashtables, would that resolve the problem?

vexx32 commented 4 years ago

we have been requiring new cmdlets to follow this pattern for some time, and the cmdlet generator explicitly follows this pattern (Hashtables instead of Dictionary types).

Glad to hear it! 💖

A type converter is one option. Another might be a transformation attribute which handles it just for the parameter.

Unless I'm mistaken, type converters typically affect the whole process/session, right? That might lead to unintended consequences down the road with completely unrelated things.

A PS-centric example/explanation of argument transformation attributes is in this blog post of mine, but it maps pretty 1:1 with C# design (apart from the specifics of the internal logic) for the same functionality. You can reuse the attribute for any other cmdlets which have this older pattern in their parameters as well, without affecting anything else in the user's PS session.

If you'd prefer C# examples, I can also point to the attributes used for PSWordCloud's parameter type transformations (they're quite similar though).