{"id":74207,"date":"2015-02-04T00:01:00","date_gmt":"2015-02-04T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2015\/02\/04\/registry-cmdlets-advanced-cdxml\/"},"modified":"2019-02-18T10:30:47","modified_gmt":"2019-02-18T17:30:47","slug":"registry-cmdlets-advanced-cdxml","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/registry-cmdlets-advanced-cdxml\/","title":{"rendered":"Registry Cmdlets: Advanced CDXML"},"content":{"rendered":"<p><b style=\"font-size:12px\">Summary<\/b><span style=\"font-size:12px\">: Richard Siddaway shows some advanced features in CDXML.<\/span>\nHonorary Scripting Guy, Richard Siddaway, here today filling in for my good friend, The Scripting Guy. This is the third post in a series. To catch up, read:<\/p>\n<ul>\n<li><a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2015\/02\/02\/registry-cmdlets-manage-the-registry.aspx\" target=\"_blank\">Registry Cmdlets: Working with the Registry<\/a><\/li>\n<li><a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2015\/02\/03\/registry-cmdlets-first-steps-with-cdxml.aspx\" target=\"_blank\">Registry Cmdlets: First Steps with CDXML<\/a><\/li>\n<\/ul>\n<p>Yesterday, you saw that you can create a Windows PowerShell cmdlet from the <b>StdRegProv<\/b> CIM class by using CDXML, which enables you to read a string value from the registry. Today, I want to show you some of the advanced features of CDXML. These enable you to make your CDXML cmdlet act like any other Windows PowerShell cmdlet. For instance, you can make parameters mandatory and validate the values that are input to parameters.\nBefore that though, I want to show something that makes working with the registry so much easier. One of the biggest pain points when working with the CIM Registry provider, <b>StdRegProv<\/b>, is those awful numbers you have to remember&mdash;the numbers that define the hives:<\/p>\n<p style=\"margin-left:30px\">HKEY_CLASSES_ROOT = 2147483648 (0x80000000)<\/p>\n<p style=\"margin-left:30px\">HKEY_CURRENT_USER = 2147483649 (0x80000001)<\/p>\n<p style=\"margin-left:30px\">HKEY_LOCAL_MACHINE = 2147483650 (0x80000002)<\/p>\n<p style=\"margin-left:30px\">HKEY_USERS = 2147483651 (0x80000003)<\/p>\n<p style=\"margin-left:30px\">HKEY_CURRENT_CONFIG = 2147483653 (0x80000005)<\/p>\n<p style=\"margin-left:30px\">HKEY_DYN_DATA = 2147483654 (0x80000006)\nThey are required when using the cmdlet we created yesterday:<\/p>\n<p style=\"margin-left:30px\">[uint32]$hklm = 2147483650<\/p>\n<p style=\"margin-left:30px\">$subkey = &#8220;SOFTWAREMicrosoftInternet Explorer&#8221;<\/p>\n<p style=\"margin-left:30px\">$value = &#8220;Version&#8221;<\/p>\n<p style=\"margin-left:30px\">Get-RegistrySTRING -Hive $hklm -SubKey $subkey -ValueName $value\nBut wouldn&rsquo;t it be great if you could provide a friendly value for the hive&mdash;something like this:<\/p>\n<p style=\"margin-left:30px\">Get-RegistrySTRING -Hive HKLM -SubKey $subkey -ValueName $value\nThere is a simple way to achieve this. The first step is to change the end of your CDXML file from this:<\/p>\n<p style=\"margin-left:30px\">&nbsp; &lt;\/Class&gt;<\/p>\n<p style=\"margin-left:30px\">&lt;\/PowerShellMetadata&gt;\n&#8230;to this:<\/p>\n<p style=\"margin-left:30px\">&nbsp; &lt;\/Class&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp; &lt;Enums&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; &lt;Enum EnumName=&#8221;RSPSNA.Registry.Hive&#8221; UnderlyingType=&#8221;System.UInt32&#8243;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Value Name=&#8221;HKCR&#8221; Value=&#8221;2147483648&#8243; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Value Name=&#8221;HKCU&#8221; Value=&#8221;2147483649&#8243; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Value Name=&#8221;HKLM&#8221; Value=&#8221;2147483650&#8243; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Value Name=&#8221;HKUS&#8221; Value=&#8221;2147483651&#8243; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Value Name=&#8221;HKLocalMachine&#8221; Value=&#8221;2147483650&#8243; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Value Name=&#8221;HKCC&#8221; Value=&#8221;2147483653&#8243; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; &lt;\/Enum&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp; &lt;\/Enums&gt;<\/p>\n<p style=\"margin-left:30px\">&lt;\/PowerShellMetadata&gt;\nYou are adding an enumeration definition to the CDXML file. It has a name (in this case, EnumName=&#8221;RSPSNA.Registry.Hive&#8221;) and an underlying type (- UnderlyingType=&#8221;System.UInt32&#8243;). You then need to define the values in the enumeration:<\/p>\n<p style=\"margin-left:30px\">&lt;Value Name=&#8221;HKCR&#8221; Value=&#8221;2147483648&#8243; \/&gt;\nEach value has a name-value pair as shown. It is possible to define multiple names for the same value:<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Value Name=&#8221;HKLM&#8221; Value=&#8221;2147483650&#8243; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Value Name=&#8221;HKLocalMachine&#8221; Value=&#8221;2147483650&#8243; \/&gt;\nThis means that you can provide your users with a number of different ways of defining the hive key, and they can use whichever fits their style. I prefer the 4-letter acronyms&mdash;it&rsquo;s less typing!\nYou also have to change the parameter definitions. Yesterday, you saw this command to define the hive parameter:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Parameter ParameterName=&#8221;hDefKey&#8221; &gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type PSType=&#8221;System.UInt32&#8243; \/&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletParameterMetadata PSName=&#8221;Hive&#8221;&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/CmdletParameterMetadata&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameter&gt;\nYou need to change it to use the enumeration:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Parameter ParameterName=&#8221;hDefKey&#8221; &gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type PSType=&#8221;RSPSNA.Registry.Hive&#8221; \/&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletParameterMetadata PSName=&#8221;Hive&#8221;&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/CmdletParameterMetadata&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameter&gt;\nThe only change is on the <b>Type<\/b> line where the type is changed to match the name of the enumeration. The name of the type, and therefore the enumeration, is arbitrary and under your control. I recommend that you create a naming scheme for enumerations in your organization.\nIn my testing, I named this version of the module registry2.cdxml. You import the module and set the values for the subkey and value you want to read:<\/p>\n<p style=\"margin-left:30px\">Import-Module .registry2.cdxml -Force<\/p>\n<p style=\"margin-left:30px\">$subkey = &#8220;SOFTWAREMicrosoftInternet Explorer&#8221;<\/p>\n<p style=\"margin-left:30px\">$value = &#8220;Version&#8221;\nAnd then use the cmdlet like this:<\/p>\n<p style=\"margin-left:30px\">Get-RegistrySTRING -Hive HKLM -SubKey $subkey -ValueName $value\nThe act of defining an enumeration automatically forces validation of the input:<\/p>\n<p style=\"margin-left:30px\">Get-RegistrySTRING -Hive HKLL -SubKey $subkey -ValueName $value<\/p>\n<p style=\"margin-left:30px\">Get-RegistrySTRING : Cannot process argument transformation on parameter &#8216;Hive&#8217;. Cannot convert value &#8220;HKLL&#8221; to type<\/p>\n<p style=\"margin-left:30px\">&#8220;Microsoft.PowerShell.Cmdletization.GeneratedTypes.RSPSNA.Registry.Hive&#8221;. Error: &#8220;Unable to match the identifier name<\/p>\n<p style=\"margin-left:30px\">HKLL to a valid enumerator name.&nbsp; Specify one of the following enumerator names and try again: HKCR, HKCU, HKLM,HKLocalMachine, HKUS, HKCC&#8221;<\/p>\n<p style=\"margin-left:30px\">At line:1 char:26<\/p>\n<p style=\"margin-left:30px\">+ Get-RegistrySTRING -Hive HKLL -SubKey $subkey -ValueName $value<\/p>\n<p style=\"margin-left:30px\">+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ~~~~<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; + CategoryInfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : InvalidData: (:) [Get-RegistrySTRING], ParameterBindingArgumentTransformationException<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; + FullyQualifiedErrorId : ParameterArgumentTransformationError,Get-RegistrySTRING\nAs with other Windows PowerShell cmdlets, you even get a helpful hint as to the accepted values. As a side note, Tab completion works on the enumeration, so type:<\/p>\n<p style=\"margin-left:30px\">Get-RegistrySTRING &ndash;Hive\n&#8230;and then use the Tab key to cycle through the allowed values.\nThe hive defaults to HKLM, so you can do this:<\/p>\n<p style=\"margin-left:30px\">Get-RegistrySTRING -SubKey $subkey -ValueName $value\nThis is not a practice I recommend, though. If you explicitly state the registry hive you want to access, it makes troubleshooting easier.\nYou can add other validation to the cmdlet parameters in a similar manner to advanced functions. The simplest change is to make a parameter mandatory. Add the <b>IsMandatory=&#8221;true&#8221;<\/b> element to the <b>CmdletParameterMetadata<\/b> node, and you now have a mandatory parameter:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Parameter ParameterName=&#8221;hDefKey&#8221; &gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type PSType=&#8221;RSPSNA.Registry.Hive&#8221; \/&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletParameterMetadata IsMandatory=&#8221;true&#8221; PSName=&#8221;Hive&#8221;&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/CmdletParameterMetadata&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameter&gt;\nLike with an existing cmdlet or an advanced function, if you don&rsquo;t specify the value of a mandatory parameter you will be prompted.\nThis works as you would expect:<\/p>\n<p style=\"margin-left:30px\">Import-Module .registry3.cdxml -Force<\/p>\n<p style=\"margin-left:30px\">Get-RegistrySTRING -Hive HKLM -SubKey &#8220;SOFTWAREMicrosoftInternet Explorer&#8221; -ValueName Version\nRegistry3.cdxml is the version where I added the mandatory parameter. If you don&rsquo;t specify the <b>&ndash;Hive<\/b> parameter, you will be prompted:<\/p>\n<p style=\"margin-left:30px\">&pound;&gt; Get-RegistrySTRING -SubKey &#8220;SOFTWAREMicrosoftInternet Explorer&#8221; -ValueName Version<\/p>\n<p style=\"margin-left:30px\">cmdlet Get-RegistrySTRING at command pipeline position 1\nNow, supply values for the parameters&mdash;you won&rsquo;t be allowed to specify the parameter without a value:<\/p>\n<p style=\"margin-left:30px\">&pound;&gt; Get-RegistrySTRING -Hive&nbsp; -SubKey &#8220;SOFTWAREMicrosoftInternet Explorer&#8221; -ValueName Version<\/p>\n<p style=\"margin-left:30px\">Get-RegistrySTRING : Missing an argument for parameter &#8216;Hive&#8217;. Specify a parameter of type<\/p>\n<p style=\"margin-left:30px\">&#8216;Microsoft.PowerShell.Cmdletization.GeneratedTypes.RSPSNA.Registry.Hive&#8217; and try again.<\/p>\n<p style=\"margin-left:30px\">At line:1 char:20<\/p>\n<p style=\"margin-left:30px\">+ Get-RegistrySTRING -Hive&nbsp; -SubKey &#8220;SOFTWAREMicrosoftInternet Explorer&#8221; -ValueN &#8230;<\/p>\n<p style=\"margin-left:30px\">+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ~~~~~<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; + CategoryInfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : InvalidArgument: (:) [Get-RegistrySTRING], ParameterBindingException<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; + FullyQualifiedErrorId : MissingArgument,Get-RegistrySTRING\nThere are a set of tags for setting validation on parameter input; for instance, to validate that the input isn&rsquo;t null or empty:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Parameter ParameterName=&#8221;sValueName&#8221; &gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type PSType=&#8221;System.String&#8221; \/&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletParameterMetadata PSName=&#8221;ValueName&#8221;&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ValidateNotNullOrEmpty \/&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/CmdletParameterMetadata&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameter&gt;\nAfter importing the changed module, you can use it as before:<\/p>\n<p style=\"margin-left:30px\">Get-RegistrySTRING -Hive HKLM -SubKey &#8220;SOFTWAREMicrosoftInternet Explorer&#8221; -ValueName Version\nIf you don&rsquo;t specify the <b>Subkey<\/b> value, you will receive an error message:<\/p>\n<p style=\"margin-left:30px\">&pound;&gt; Get-RegistrySTRING -Hive HKLM -SubKey -ValueName Version<\/p>\n<p style=\"margin-left:30px\">Get-RegistrySTRING : Missing an argument for parameter &#8216;SubKey&#8217;. Specify a parameter of type &#8216;System.String&#8217; and try again.<\/p>\n<p style=\"margin-left:30px\">At line:1 char:31<\/p>\n<p style=\"margin-left:30px\">+ Get-RegistrySTRING -Hive HKLM -SubKey -ValueName Version<\/p>\n<p style=\"margin-left:30px\">+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ~~~~~~~<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; + CategoryInfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : InvalidArgument: (:) [Get-RegistrySTRING], ParameterBindingException<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; + FullyQualifiedErrorId : MissingArgument,Get-RegistrySTRING\nIf you don&rsquo;t specify the parameter at all, you get a different error message:<\/p>\n<p style=\"margin-left:30px\">&pound;&gt; Get-RegistrySTRING -Hive HKLM&nbsp; -ValueName Version<\/p>\n<p style=\"margin-left:30px\">Get-RegistrySTRING : Invalid parameter<\/p>\n<p style=\"margin-left:30px\">At line:1 char:1<\/p>\n<p style=\"margin-left:30px\">+ Get-RegistrySTRING -Hive HKLM&nbsp; -ValueName Version<\/p>\n<p style=\"margin-left:30px\">+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; + CategoryInfo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : InvalidArgument: (StdRegProv:rootcimv2StdRegProv) [Get-RegistrySTRING], CimException<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; + FullyQualifiedErrorId : HRESULT 0x80041008,Get-RegistrySTRING\nIf you specify the <b>SubKey<\/b> but not the value you&rsquo;ll get an error:<\/p>\n<p style=\"margin-left:30px\">Get-RegistrySTRING -Hive HKLM&nbsp; -SubKey &#8220;SOFTWAREMicrosoftInternet Explorer&#8221;<\/p>\n<p style=\"margin-left:30px\">sValue ReturnValue<\/p>\n<p style=\"margin-left:30px\">&#8212;&#8212; &nbsp;&nbsp;&nbsp;&nbsp;&#8212;&#8212;&#8212;&#8211;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1\nRemember that a non-zero return code from a CIM method means that there has been an error.\nA good way to discover examples of validation in CDXML modules is to view the files on a system running Windows 8 or Windows Server 2012 (or later versions). You&rsquo;ll find the examples in the subfolders of C:WindowsSystem32WindowsPowerShellv1.0modules.\nThere are a lot of modules in these systems, and over 60% are created using CDXML. Here is a quick way to search for interesting examples:<\/p>\n<p style=\"margin-left:30px\">Get-ChildItem -Path $pshomemodules -Filter *.cdxml -File -Recurse | Select-String -Pattern &#8216;*validate*&#8217; -SimpleMatch&nbsp;\nHere are some examples of using validation in CDXML that I discovered in this way:\n<b>&lt;ValidateNotNull \/&gt;<\/b> is similar to <b>&lt;ValidateNotNullOrEmpty \/&gt;<\/b>, which &nbsp;you&rsquo;ve seen already. I prefer to use <b>&lt;ValidateNotNullOrEmpty \/&gt;<\/b>.\nTo validate on a set of values:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ValidateSet&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;AllowedValue&gt;Both&lt;\/AllowedValue&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;AllowedValue&gt;Incoming&lt;\/AllowedValue&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;AllowedValue&gt;Outcoming&lt;\/AllowedValue&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/ValidateSet&gt;\nThis is taken from C:WindowsSystem32WindowsPowerShellv1.0modulesDefenderMSFT_MpPreference.cdxml.\nYou can also validate on a range as shown in C:WindowsSystem32WindowsPowerShellv1.0modulesMMAgentps_mmagent_v1.0.cdxml:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ValidateRange Min=&#8221;1&#8243; Max=&#8221;8192&#8243; \/&gt;\nYou might also find examples of other validation options, such as:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ValidateCount Min=&#8221;1&#8243; Max=&#8221;10&#8243; \/&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ValidateLength Min=&#8221;1&#8243; Max=&#8221;10&#8243; \/&gt;\n<b>ValidatePattern<\/b> and <b>ValidateScript<\/b> from advanced functions are not allowed in CDXML. You can have multiple validations on the same parameter, but remember that once one fails, that&rsquo;s it&mdash;your input is rejected.\nIf you require them, you also have some options to allow specific scenarios:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;AllowEmptyCollection \/&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;AllowEmptyString \/&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;AllowNull \/&gt;\nThat&rsquo;s it for today. Tomorrow I&rsquo;ll finish this short series with a look at some of the issues that arise when you start working with registry data types other than strings.\nBye for now.\nWe invite you to follow The Scripting Guys on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a>. If you have any questions, send an email to The Scripting Guys at <a href=\"http:\/\/blogs.technet.commailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. Until then, remember eat your cmdlets every day with a dash of creativity.\n<b>Richard Siddaway, <\/b>Windows PowerShell MVP and Honorary Scripting Guy<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Richard Siddaway shows some advanced features in CDXML. Honorary Scripting Guy, Richard Siddaway, here today filling in for my good friend, The Scripting Guy. This is the third post in a series. To catch up, read: Registry Cmdlets: Working with the Registry Registry Cmdlets: First Steps with CDXML Yesterday, you saw that you can [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[385,26,189,45],"class_list":["post-74207","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-cim","tag-registry","tag-richard-siddaway","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Richard Siddaway shows some advanced features in CDXML. Honorary Scripting Guy, Richard Siddaway, here today filling in for my good friend, The Scripting Guy. This is the third post in a series. To catch up, read: Registry Cmdlets: Working with the Registry Registry Cmdlets: First Steps with CDXML Yesterday, you saw that you can [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/74207","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=74207"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/74207\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=74207"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=74207"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=74207"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}