{"id":213,"date":"2007-11-21T22:48:21","date_gmt":"2007-11-21T22:48:21","guid":{"rendered":"http:\/\/dalelane.co.uk\/blog\/?p=213"},"modified":"2007-11-21T22:53:54","modified_gmt":"2007-11-21T22:53:54","slug":"displaying-constant-names-rather-than-values-in-powershell-cmdlets","status":"publish","type":"post","link":"https:\/\/dalelane.co.uk\/blog\/?p=213","title":{"rendered":"Displaying constant names (rather than values) in PowerShell cmdlets"},"content":{"rendered":"<p>I&#8217;ve <a href=\"http:\/\/dalelane.co.uk\/blog\/?p=185\">mentioned before that I&#8217;m working on some PowerShell cmdlets for WebSphere MQ<\/a>. I thought I&#8217;d pass on a few tips that I picked up this week on improving the usability of the information displayed by <code>Get-<\/code> cmdlets in PowerShell.<\/p>\n<p>The easiest way to explain it is to demonstrate with an example:<\/p>\n<p><!--more--><strong>Before<\/strong><\/p>\n<p>Consider one of my cmdlets before:<\/p>\n<pre style=\"background-color: #16166b; color: white; border: thin solid black; padding: 1em;\"><code>PS C:\\> Get-WMQQueue SYSTEM.DEFAULT.LOCAL.QUEUE DALE\r\n\r\nInhibitGet                : 1\r\nProcessName               :\r\nMaximumDepth              : 5000\r\nMaximumMessageLength      : 4194304\r\nBackoutThreshold          : 0\r\nBackoutRequeueName        :\r\nShareability              : 1\r\nDefaultInputOpenOption    : 2\r\nHardenGetBackout          : 1\r\nMessageDeliverySequence   : 0\r\nRetentionInterval         : 999999999\r\nDefinitionType            : 1\r\nUsage                     : 0\r\nOpenInputCount            : 0\r\nOpenOutputCount           : 0\r\nCurrentDepth              : 0\r\nCreationDateTime          : 10\/11\/2007 15:17:38\r\nInitiationQueueName       :\r\nTriggerControl            : 0\r\nTriggerType               : 1\r\nTriggerMessagePriority    : 0\r\nTriggerDepth              : 1\r\nTriggerData               :\r\nScope                     : 1\r\nDepthHighEvent            : 0\r\nDepthHighLimit            : 80\r\nDepthLowEvent             : 0\r\nDepthLowLimit             : 20\r\nDepthMaximumEvent         : 1\r\nServiceInterval           : 999999999\r\nServiceIntervalEvent      : 0\r\nClusterName               :\r\nClusterNamelist           :\r\nDefaultBind               : 0\r\nClusterWorkLoadRank       : 0\r\nClusterWorkLoadPriority   : 0\r\nClusterWorkLoadUseQ       : -3\r\nTPIPE                     :\r\nQueueAccounting           : -3\r\nQueueMonitoring           : -3\r\nQueueStatistics           : -3\r\nNonPersistentMessageClass : 0\r\nPagesetId                 : 0\r\nQueueManager              : IBM.WMQ.MQQueueManager\r\nName                      : SYSTEM.DEFAULT.LOCAL.QUEUE\r\nQueueType                 : 1\r\nDescription               :\r\nInhibitPut                : 0\r\nDefaultMessagePriority    : 0\r\nDefaultMessagePersistence : 0\r\nAlterationDateTime        : 21\/11\/2007 11:46:23<\/code><\/pre>\n<p><strong>After<\/strong><\/p>\n<p>Now take a look at what it looks like:<\/p>\n<pre style=\"background-color: #16166b; color: white; border: thin solid black; padding: 1em;\"><code>PS C:\\> Get-WMQQueue SYSTEM.DEFAULT.LOCAL.QUEUE DALE\r\n\r\nInhibitGet                : Inhibited\r\nProcessName               :\r\nMaximumDepth              : 5000\r\nMaximumMessageLength      : 4194304\r\nBackoutThreshold          : 0\r\nBackoutRequeueName        :\r\nShareability              : Shareable\r\nDefaultInputOpenOption    : Shared\r\nHardenGetBackout          : Hardened\r\nMessageDeliverySequence   : 0\r\nRetentionInterval         : 999999999\r\nDefinitionType            : Predefined\r\nUsage                     : Normal\r\nOpenInputCount            : 0\r\nOpenOutputCount           : 0\r\nCurrentDepth              : 0\r\nCreationDateTime          : 10\/11\/2007 15:17:38\r\nInitiationQueueName       :\r\nTriggerControl            : Off\r\nTriggerType               : First\r\nTriggerMessagePriority    : 0\r\nTriggerDepth              : 1\r\nTriggerData               :\r\nScope                     : Qmgr\r\nDepthHighEvent            : 0\r\nDepthHighLimit            : 80\r\nDepthLowEvent             : 0\r\nDepthLowLimit             : 20\r\nDepthMaximumEvent         : 1\r\nServiceInterval           : 999999999\r\nServiceIntervalEvent      : None\r\nClusterName               :\r\nClusterNamelist           :\r\nDefaultBind               : OnOpen\r\nClusterWorkLoadRank       : 0\r\nClusterWorkLoadPriority   : 0\r\nClusterWorkLoadUseQ       : UseAsQmgr\r\nTPIPE                     :\r\nQueueAccounting           : Qmgr\r\nQueueMonitoring           : Qmgr\r\nQueueStatistics           : Qmgr\r\nNonPersistentMessageClass : Normal\r\nPagesetId                 : 0\r\nQueueManager              : IBM.WMQ.MQQueueManager\r\nName                      : SYSTEM.DEFAULT.LOCAL.QUEUE\r\nQueueType                 : Local\r\nDescription               :\r\nInhibitPut                : Allowed\r\nDefaultMessagePriority    : 0\r\nDefaultMessagePersistence : NotPersistent\r\nAlterationDateTime        : 21\/11\/2007 11:46:23<\/code><\/pre>\n<p>What do you think? More readable, right?<\/p>\n<p><strong>What is going on?<\/strong><\/p>\n<p>The <code>Get-WMQQueue<\/code> cmdlet writes &#8216;WebSphere MQ queue&#8217; objects to the pipeline. The queue&#8217;s properties were stored as int&#8217;s, strings, and DateTime objects. Some of the ints were used to store a choice between constants.<\/p>\n<p>For example, <code>QueueType<\/code> contained a value chosen from:<\/p>\n<pre><code>    public const int MQQT_ALL = 1001;\r\n    public const int MQQT_LOCAL = 1;\r\n    public const int MQQT_MODEL = 2;\r\n    public const int MQQT_ALIAS = 3;\r\n    public const int MQQT_REMOTE = 6;\r\n    public const int MQQT_CLUSTER = 7;<\/code><\/pre>\n<p>These are the integers being displayed in the <code>Get-<\/code> cmdlet shown above.<\/p>\n<p>It was the same in the <code>Set-<\/code> cmdlets when you want to make a change:<\/p>\n<pre style=\"background-color: #16166b; overflow-x: scroll; color: white; width: 140%; border: thin solid black; padding: 1em;\"><code>PS C:\\> Get-WMQQueue SYSTEM.DEFAULT.LOCAL.QUEUE DALE | Set-WMQQueue -InhibitPut 1 \r\nPS C:\\> Get-WMQQueue SYSTEM.DEFAULT.LOCAL.QUEUE DALE | Select Name, InhibitPut \r\n\r\nName                                                InhibitPut \r\n----                                                ---------- \r\nSYSTEM.DEFAULT.LOCAL.QUEUE                                   1 <\/code><\/pre>\n<p>You could always use the constant names in commands&#8230;<\/p>\n<pre style=\"background-color: #16166b; overflow-x: scroll; color: white; width: 140%; border: thin solid black; padding: 1em;\"><code>PS C:\\> Get-WMQQueue SYSTEM.DEFAULT.LOCAL.QUEUE DALE | Set-WMQQueue -InhibitPut ([IBM.WMQ.MQC]::MQQA_PUT_INHIBITED) \r\nPS C:\\> Get-WMQQueue SYSTEM.DEFAULT.LOCAL.QUEUE DALE | Select Name, InhibitPut \r\n\r\nName                                                InhibitPut \r\n----                                                ---------- \r\nSYSTEM.DEFAULT.LOCAL.QUEUE                                   1 <\/code><\/pre>\n<p>but it still outputs the int in <code>Get-<\/code> commands, and the constants would be a pain to memorise for commands.<\/p>\n<p><strong>Improving &#8211; using enums<\/strong><\/p>\n<p>Instead of storing QueueType as an int, and store a collection of constant ints for the possible values, I can use an <code>enum<\/code>.<\/p>\n<pre><code>    public enum QueueTypes\r\n    {\r\n        All = 1001,\r\n        Local = 1,\r\n        Model = 2,\r\n        Alias = 3,\r\n        Remote = 6,\r\n        Cluster = 7\r\n    };<\/code><\/pre>\n<p>When you do this, by default PowerShell will display the enum value name rather than underlying value &#8211; producing the more readable <code>Get-WMQQueue<\/code> output you can see above.<\/p>\n<p><strong>Self-documenting commands&#8230; using enums<\/strong><\/p>\n<p>Unlike using ints, the use of enums also makes it much easier for users to find out what the valid values are for each property. <\/p>\n<p>For example, if you can see that <code>InhibitGet<\/code> is set to &#8216;Allowed&#8217;, how do you know what is the right value for &#8216;not allowed&#8217;? <\/p>\n<pre style=\"background-color: #16166b; overflow-x: scroll; color: white; width: 140%; border: thin solid black; padding: 1em;\"><code>PS C:\\> Get-WMQQueue SYSTEM.DEFAULT.LOCAL.QUEUE DALE | Get-Member InhibitGet \r\n\r\n   TypeName: WebSphereMQ.MQLocalQueue \r\n\r\nName       MemberType Definition \r\n----       ---------- ---------- \r\nInhibitGet Property   WebSphereMQ.MQC+InhibitGetTypes InhibitGet {get;set;}<\/code><\/pre>\n<p>The &#8216;+&#8217; symbol in the type definition tells you that the type is an enum called InhibitGetTypes in the WebSphereMQ.MQC class. <\/p>\n<p>And to find out the valid values:<\/p>\n<pre style=\"background-color: #16166b; overflow-x: scroll; color: white; width: 140%; border: thin solid black; padding: 1em;\"><code>PS C:\\> Get-EnumValues([WebSphereMQ.MQC+InhibitGetTypes]) \r\n\r\n     Name Value \r\n     ---- ----- \r\n  Allowed     0 \r\nInhibited     1 <\/code><\/pre>\n<p>To use this, you can just use the enum value &#8211; without having to identify the full class name:<\/p>\n<pre style=\"background-color: #16166b; overflow-x: scroll; color: white; width: 140%; border: thin solid black; padding: 1em;\"><code>PS C:\\> Get-WMQQueue SYSTEM.DEFAULT.LOCAL.QUEUE * | Set-WMQQueue -InhibitGet Inhibited \r\nPS C:\\> Get-WMQQueue SYSTEM.DEFAULT.LOCAL.QUEUE * | Select Name, InhibitGet \r\n\r\nName                                                InhibitGet \r\n----                                                ---------- \r\nSYSTEM.DEFAULT.LOCAL.QUEUE                           Inhibited <\/code><\/pre>\n<p>Alternatively, you could always be lazy and make an intentional error &#8211; using the error message feedback to guide you&#8230; <\/p>\n<pre style=\"background-color: #16166b; overflow-x: scroll; color: white; width: 140%; border: thin solid black; padding: 1em;\"><code>PS C:\\> Get-WMQQueue SYSTEM.DEFAULT.LOCAL.QUEUE * | Set-WMQQueue -InhibitGet THIS_DEFINITELY_SHOULDNT_WORK \r\n<font style=\"background-color: black; color: red;\">Set-WMQQueue : Cannot bind parameter 'InhibitGet'.  \r\nCannot convert value \"THIS_DEFINITELY_SHOULDNT_WORK\" to type \"WebSphereMQ.MQC+InhibitGetTypes\" due to invalid enumeration values.  \r\nSpecify one of the following enumeration values and try again.  \r\nThe possible enumeration values are \"Allowed, Inhibited\". <\/font><\/code><\/pre>\n<p>That said, by using the same int values in the enum, it means the full constants would still work for those users familiar with them:<\/p>\n<pre style=\"background-color: #16166b; overflow-x: scroll; color: white; width: 140%; border: thin solid black; padding: 1em;\"><code>PS C:\\> Get-WMQQueue SYSTEM.DEFAULT.LOCAL.QUEUE DALE | Set-WMQQueue -InhibitGet ([IBM.WMQ.MQC]::MQQA_GET_INHIBITED) \r\nPS C:\\> Get-WMQQueue SYSTEM.DEFAULT.LOCAL.QUEUE DALE | Select Name, InhibitGet \r\n\r\nName                                                InhibitGet \r\n----                                                ---------- \r\nSYSTEM.DEFAULT.LOCAL.QUEUE                           Inhibited <\/code><\/pre>\n<p>PowerShell handles enums really well &#8211; and it all helps improve the usability of your sysadmin cmdlets if you use them properly. <\/p>\n<p>Thanks to <a href=\"http:\/\/www.powershellcommunity.org\/\" target=\"_blank\">Don Jones<\/a> for helping to point me in the right direction, and <a href=\"http:\/\/scriptolog.blogspot.com\/2007\/10\/listing-enumeration-type-values.html\" target=\"_blank\">$cript Fanatic<\/a> for the <code>Get-EnumValues<\/code> function. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve mentioned before that I&#8217;m working on some PowerShell cmdlets for WebSphere MQ. I thought I&#8217;d pass on a few tips that I picked up this week on improving the usability of the information displayed by Get- cmdlets in PowerShell. The easiest way to explain it is to demonstrate with an example:<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[36,37,34,35],"class_list":["post-213","post","type-post","status-publish","format-standard","hentry","category-code","tag-c","tag-enum","tag-powershell","tag-webspheremq"],"_links":{"self":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/213","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=213"}],"version-history":[{"count":0,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/213\/revisions"}],"wp:attachment":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=213"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=213"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=213"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}