{"id":74205,"date":"2015-02-05T00:01:00","date_gmt":"2015-02-05T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2015\/02\/05\/registry-cmdlets-complete-the-registry-cdxml-module\/"},"modified":"2019-02-18T10:30:46","modified_gmt":"2019-02-18T17:30:46","slug":"registry-cmdlets-complete-the-registry-cdxml-module","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/registry-cmdlets-complete-the-registry-cdxml-module\/","title":{"rendered":"Registry Cmdlets: Complete the Registry CDXML Module"},"content":{"rendered":"<p><b style=\"font-size:12px\">Summary<\/b><span style=\"font-size:12px\">: Richard Siddaway shows how to complete the registry CDXML module.<\/span>\nHonorary Scripting Guy, Richard Siddaway, here today filling in for my good friend, The Scripting Guy. This is the final 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<li><a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2015\/02\/04\/registry-cmdlets-advanced-cdxml.aspx\" target=\"_blank\">Registry Cmdlets: Advanced CDXML<\/a><\/li>\n<\/ul>\n<p>So far, you&rsquo;ve seen how to create a CDXML module with a single cmdlet based on the <b>GetStringValue<\/b> method of the <b>StdRegProv<\/b> CIM class. In this post, I&rsquo;ll show you how to add the other methods that are available in the class to create a complete module of easy-to-use cmdlets for working with the registry. I&rsquo;ll also show you how to work with some of the more awkward registry data types.\nThe complete module consists of these cmdlets:<\/p>\n<p style=\"margin-left:30px\">Get-RegistryBinary<\/p>\n<p style=\"margin-left:30px\">Get-RegistryDWORD<\/p>\n<p style=\"margin-left:30px\">Get-RegistryExpandSTRING<\/p>\n<p style=\"margin-left:30px\">Get-RegistryKey<\/p>\n<p style=\"margin-left:30px\">Get-RegistryMultiSTRING<\/p>\n<p style=\"margin-left:30px\">Get-RegistryQWORD<\/p>\n<p style=\"margin-left:30px\">Get-RegistrySTRING<\/p>\n<p style=\"margin-left:30px\">Get-RegistryValue<\/p>\n<p style=\"margin-left:30px\">New-RegistryKey<\/p>\n<p style=\"margin-left:30px\">Remove-RegistryKey<\/p>\n<p style=\"margin-left:30px\">Remove-RegistryValue<\/p>\n<p style=\"margin-left:30px\">Set-RegistryBinary<\/p>\n<p style=\"margin-left:30px\">Set-RegistryDWORD<\/p>\n<p style=\"margin-left:30px\">Set-RegistryExpandSTRING<\/p>\n<p style=\"margin-left:30px\">Set-RegistryMultiSTRING<\/p>\n<p style=\"margin-left:30px\">Set-RegistryQWORD<\/p>\n<p style=\"margin-left:30px\">Set-RegistrySTRING\nThese cmdlets provide the ability to get and set values for each of the registry data types, get lists of registry keys and values, create new keys, and delete keys and values.\nReading data from the registry is very useful, but you also need to be able to write to the registry. You can use the <b>SetStringValue<\/b> method as an example:<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Cmdlet&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletMetadata Verb=&#8221;Set&#8221; Noun=&#8221;RegistrySTRING&#8221; ConfirmImpact=&#8221;Low&#8221;\/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Method MethodName=&#8221;SetSTRINGvalue&#8221;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ReturnValue&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type PSType=&#8221;System.UInt32&#8243;\/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletOutputMetadata&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/CmdletOutputMetadata&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/ReturnValue&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Parameters&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Parameter ParameterName=&#8221;hDefKey&#8221; &gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type PSType=&#8221;RSPSNA.Registry.Hive&#8221; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletParameterMetadata IsMandatory=&#8221;true&#8221; PSName=&#8221;Hive&#8221;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/CmdletParameterMetadata&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameter&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Parameter ParameterName=&#8221;sSubKeyName&#8221; &gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type PSType=&#8221;System.String&#8221; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletParameterMetadata PSName=&#8221;SubKey&#8221;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ValidateNotNullOrEmpty \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/CmdletParameterMetadata&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameter&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Parameter ParameterName=&#8221;sValueName&#8221; &gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type PSType=&#8221;System.String&#8221; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletParameterMetadata PSName=&#8221;ValueName&#8221;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ValidateNotNullOrEmpty \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/CmdletParameterMetadata&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameter&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Parameter ParameterName=&#8221;sValue&#8221;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type PSType=&#8221;System.String&#8221;&nbsp; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletParameterMetadata PSName=&#8221;Value&#8221;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ValidateNotNullOrEmpty \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/CmdletParameterMetadata&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameter&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameters&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Method&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Cmdlet&gt;\nIn this case, you have to provide the hive, subkey, and value with the data to insert into that value. I&rsquo;ve used <b>ValueName<\/b> and <b>Value<\/b> for the registry value and data respectively:<\/p>\n<p style=\"margin-left:30px\">Set-RegistryString -Hive HKLM -SubKey SOFTWAREModuleTest -ValueName svalue -Value &#8216;Summit2014&#8217;\nThe cmdlet will create the registry value if it doesn&rsquo;t exist but the key needs to be present already. You can create registry keys as follows:<\/p>\n<p style=\"margin-left:30px\">New-RegistryKey -Hive HKLM -SubKey softwaremoduletest\nOther registry data types include:<\/p>\n<ul>\n<li>Binary<\/li>\n<li>DWORD &ndash; 32-bit number<\/li>\n<li>QWORD &ndash; 64-bit number<\/li>\n<li>Multistting = array of strings<\/li>\n<li>Expanding string (usually used with environment variables)<\/li>\n<\/ul>\n<p>When you look at registry values by using the <b>EnumValues<\/b> method, the output isn&rsquo;t very easy to work with:<\/p>\n<p style=\"margin-left:30px\">&pound;&gt; [uint32]$hklm = 2147483650<\/p>\n<p style=\"margin-left:30px\">&pound;&gt; $key = &#8216;softwaremoduletest&#8217;<\/p>\n<p style=\"margin-left:30px\">&pound;&gt; Invoke-CimMethod -ClassName StdRegProv -MethodName EnumValues -Arguments @{hDefKey = $hklm; sSubKeyName = $key}<\/p>\n<p style=\"margin-left:30px\">ReturnValue&nbsp;&nbsp;&nbsp; : 0<\/p>\n<p style=\"margin-left:30px\">sNames&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : {dvalue, qvalue, svalue, mstring&#8230;}<\/p>\n<p style=\"margin-left:30px\">Types&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : {4, 11, 1, 7&#8230;}<\/p>\n<p style=\"margin-left:30px\">PSComputerName :\nYou get an array of value names in <b>sNames <\/b>plus an array of data types in <b>Types<\/b>. The data types (as occurs so often in CIM) are coded as integer values. Ideally, you would want to see the data types output in a friendlier manner.\nYou can apply a similar technique to the way the numeric values for registry hives were dealt with. Start by creating an enumeration:<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; &lt;Enum EnumName=&#8221;RSPSNA.Registry.Type&#8221; UnderlyingType=&#8221;System.UInt32&#8243;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Value Name=&#8221;String&#8221; Value=&#8221;1&#8243; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Value Name=&#8221;ExpandingString&#8221; Value=&#8221;2&#8243; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Value Name=&#8221;Binary&#8221; Value=&#8221;3&#8243; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Value Name=&#8221;Dword&#8221; Value=&#8221;4&#8243; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Value Name=&#8221;MultiString&#8221; Value=&#8221;7&#8243; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Value Name=&#8221;Qword&#8221; Value=&#8221;11&#8243; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; &lt;\/Enum&gt;\nRemember that the name part of the enumeration cannot contain spaces. If you need to break words, use capital letters to designate the start of words or use a delimiter (such as a hyphen).\nThe CDXML definition for the cmdlet created from the <b>EnumValues<\/b> method looks like this:<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Cmdlet&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletMetadata Verb=&#8221;Get&#8221; Noun=&#8221;RegistryValue&#8221; ConfirmImpact=&#8221;Low&#8221;\/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Method MethodName=&#8221;EnumValues&#8221;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ReturnValue&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type PSType=&#8221;System.UInt32&#8243;\/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletOutputMetadata&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/CmdletOutputMetadata&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/ReturnValue&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Parameters&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Parameter ParameterName=&#8221;hDefKey&#8221; &gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type PSType=&#8221;RSPSNA.Registry.Hive&#8221; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletParameterMetadata IsMandatory=&#8221;true&#8221; PSName=&#8221;Hive&#8221;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/CmdletParameterMetadata&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameter&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Parameter ParameterName=&#8221;sSubKeyName&#8221; &gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type PSType=&#8221;System.String&#8221; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletParameterMetadata PSName=&#8221;SubKey&#8221;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ValidateNotNullOrEmpty \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/CmdletParameterMetadata&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameter&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!&#8211; Two output arrays &#8211;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!&#8211;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8211;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&lt;Parameter ParameterName=&#8221;sNames&#8221;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type PSType=&#8221;System.String[]&#8221;&nbsp; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletOutputMetadata \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameter&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Parameter ParameterName=&#8221;Types&#8221;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type PSType=&#8221;RSPSNA.Registry.Type[]&#8221; \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletOutputMetadata \/&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameter&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameters&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Method&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Cmdlet&gt;\nYou have two output arguments. The first is <b>sNames<\/b>, which is an array of strings that contain the value names. The second is an array that is created with the RSPSNA.Registry.Type enumeration supplying the values. You still have the issue of two output arrays, when ideally, you want one set of output objects. Unfortunately, CDXML can&rsquo;t solve this issue, but a little bit of Windows PowerShell magic gives you the answer.\nUsing the cmdlet as-is results in this output:<\/p>\n<p style=\"margin-left:30px\">&pound;&gt; Get-RegistryValue -Hive HKLM -SubKey softwaremoduletest<\/p>\n<p style=\"margin-left:30px\">sNames&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : {dvalue, qvalue, svalue, mstring&#8230;}<\/p>\n<p style=\"margin-left:30px\">Types&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : {Dword, Qword, String, MultiString&#8230;}<\/p>\n<p style=\"margin-left:30px\">ReturnValue : 0\nYou can see that <b>Types<\/b> now contains the data type names rather than the numeric values. This would be usable for a registry key with only a handful of values, but ideally, you want something easier to read:<\/p>\n<p style=\"margin-left:30px\">&pound;&gt; $values = Get-RegistryValue -Hive HKLM -SubKey softwaremoduletest<\/p>\n<p style=\"margin-left:30px\">&pound;&gt; 0..$($values.sNames.Length-1) | foreach {New-Object -TypeName psobject -Property @{&#8216;Name&#8217;=$values.sNames[$psitem]; &#8216;Type&#8217;=$values.Types[$psitem]}} | ft -a<\/p>\n<p style=\"margin-left:30px\">Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Type<\/p>\n<p style=\"margin-left:30px\">&#8212;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;-<\/p>\n<p style=\"margin-left:30px\">dvalue&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dword<\/p>\n<p style=\"margin-left:30px\">qvalue&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;Qword<\/p>\n<p style=\"margin-left:30px\">svalue&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String<\/p>\n<p style=\"margin-left:30px\">mstring&nbsp;&nbsp;&nbsp;&nbsp; MultiString<\/p>\n<p style=\"margin-left:30px\">SZvalue ExpandingString<\/p>\n<p style=\"margin-left:30px\">Bvalue&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Binary\nIf you store the output from <b>Get-RegistryValue<\/b> in a variable, you can access each array individually. Pipe numeric values that match the array indices &ndash; 0 to $values.sNames.Length-1 into <b>Foreach-Object<\/b>. Within the <b>Foreach<\/b>, use <b>New-Object<\/b> to create a <b>PSObject<\/b> that combines the matching name and data type. Output and use <b>Format-Table<\/b> to display, if you prefer.\nBy the way, don&rsquo;t go looking for a SoftwareModuleTest key in the HKLM hive on your system. It&rsquo;s something I created for demonstration purposes.\nWorking with the integer data types, DWORD and QWORD, is similar to working with strings. The only change is that the output (or value input) property becomes a System.UInt32 or System.UInt64 respectively, and the name changes to <b>uValue<\/b>.\nThe <b>MultiString<\/b> data type holds an array of strings rather than a single string. The parameters working with the data are defined as an array, for instance:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Parameter ParameterName=&#8221;sValue&#8221;&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type PSType=&#8221;System.String[]&#8221;&nbsp; \/&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletOutputMetadata \/&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameter&gt;\nThe remaining CDXML code is very similar to that for dealing with single string values. You can use the standard Windows PowerShell array handling techniques to work with the data.\nTo read the data:<\/p>\n<p style=\"margin-left:30px\">$data = Get-RegistryMultiSTRING -Hive HKLM -SubKey SOFTWAREModuleTest -ValueName mstring&nbsp; | select -ExpandProperty svalue\nTo remove a value from the array and write back:<\/p>\n<p style=\"margin-left:30px\">$data = $data | where {$psitem -ne &#8216;Value2&#8217;}<\/p>\n<p style=\"margin-left:30px\">Set-RegistryMultiSTRING -Hive HKLM -SubKey SOFTWAREModuleTest -ValueName mstring&nbsp; -Value $data<\/p>\n<p style=\"margin-left:30px\">Get-RegistryMultiSTRING -Hive HKLM -SubKey SOFTWAREModuleTest -ValueName mstring\nTo add another value into the array and write back:<\/p>\n<p style=\"margin-left:30px\">$data += &#8216;Value6&#8217;<\/p>\n<p style=\"margin-left:30px\">Set-RegistryMultiSTRING -Hive HKLM -SubKey SOFTWAREModuleTest -ValueName mstring&nbsp; -Value $data<\/p>\n<p style=\"margin-left:30px\">Get-RegistryMultiSTRING -Hive HKLM -SubKey SOFTWAREModuleTest -ValueName mstring\nTo reset the whole array:<\/p>\n<p style=\"margin-left:30px\">$data = &#8216;Value1&#8217;, &#8216;Value2&#8217;, &#8216;Value3&#8217;<\/p>\n<p style=\"margin-left:30px\">Set-RegistryMultiSTRING -Hive HKLM -SubKey SOFTWAREModuleTest -ValueName mstring&nbsp; -Value $data\nEnvironment variables are some of those background pieces of functionality that no one really notices until they go wrong. They can be used in the registry. The data type is known as an expanding string (sounds like something from astrophysics), and you can use the cmdlets from your registry module like this:<\/p>\n<p style=\"margin-left:30px\">Get-RegistryExpandSTRING -Hive HKLM -SubKey softwaremoduletest -ValueName SZvalue<\/p>\n<p style=\"margin-left:30px\">Set-RegistryExpandSTRING -Hive HKLM -SubKey softwaremoduletest -ValueName SZvalue -Value &#8216;%TEMP%mynewfolder&#8217;\nReading is just like reading a simple string value, but the result looks like this:<\/p>\n<p style=\"margin-left:30px\">sValue<\/p>\n<p style=\"margin-left:30px\">&#8212;&#8212;<\/p>\n<p style=\"margin-left:30px\">C:windowsTEMPmyfolder\nNotice that the result is automatically expanded for you. If you want to modify or create a registry value by using an environment variable, you code it like this:<\/p>\n<p style=\"margin-left:30px\">&#8216;%TEMP%mynewfolder&#8217;\nThe registry stores the data in that format until it&rsquo;s accessed, at which point, the accessing routine should perform the expansion.\nThe last registry data type is the <b>Binary<\/b> type. I don&rsquo;t like modifying these because bad things can happen if you get it wrong. But if you have to make changes, the safest way is to use the <b>Set-RegistryBinary<\/b> cmdlet from your module.&nbsp;&nbsp;\nCIM treats the binary data as an array of unsigned 8-bit integers. You need to convert this to a byte array for Windows PowerShell (.NET). The output argument when working with the <b>GetBinaryValue<\/b> method is coded like this:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameter&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Parameter ParameterName=&#8221;uValue&#8221;&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Type PSType=&#8221;System.Byte[]&#8221;&nbsp; \/&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;CmdletOutputMetadata \/&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;\/Parameter&gt;\nReading data from binary registry values can be accomplished like this:<\/p>\n<p style=\"margin-left:30px\">&pound;&gt; $values = Get-RegistryBinary -Hive HKLM -SubKey softwaremoduletest -ValueName Bvalue&nbsp; | select -ExpandProperty uvalu<\/p>\n<p style=\"margin-left:30px\">e<\/p>\n<p style=\"margin-left:30px\">&pound;&gt; $values<\/p>\n<p style=\"margin-left:30px\">0<\/p>\n<p style=\"margin-left:30px\">1<\/p>\n<p style=\"margin-left:30px\">2<\/p>\n<p style=\"margin-left:30px\">3<\/p>\n<p style=\"margin-left:30px\">4<\/p>\n<p style=\"margin-left:30px\">5<\/p>\n<p style=\"margin-left:30px\">6<\/p>\n<p style=\"margin-left:30px\">12\nModifying binary data can be accomplished by changing the array and writing back:<\/p>\n<p style=\"margin-left:30px\">&pound;&gt; $values += [byte]14<\/p>\n<p style=\"margin-left:30px\">&pound;&gt; Set-RegistryBinary -Hive HKLM -SubKey softwaremoduletest -ValueName Bvalue -Value $values<\/p>\n<p style=\"margin-left:30px\">0\nA return code of 0 indicates success.\nUsing CDXML isn&rsquo;t a technique for everyone. One issue is that there aren&rsquo;t any good tools to make it easier to work with. The XML is relatively simple, but you need to be careful and precise in your coding. There are many modules in the later versions of Windows that are created by using CDXML.\nYou can use the technique to create similar modules on earlier versions of Windows by using existing CIM classes. For instance, the Win32_NetworkAdapter and Win32_NetworkAdapterConfiguration classes could be used to duplicate the <b>NetAdapter<\/b> and <b>NetTCPIP<\/b> modules respectively. If you have those modules installed on your down-level systems, and you use the same cmdlet names, you could manage all of your systems from what appears to be the same set of cmdlets.\nThis concludes my series about registry cmdlets. If you are interested in learning more about CDXML, my talk on this topic is available. Please see the <a href=\"https:\/\/www.youtube.com\/playlist?list=PLfeA8kIs7CoeDFBKqLcPz5eU1B2_F9MgM\" target=\"_blank\">PowerShell Summit North America 2014<\/a> site on YouTube.&nbsp;<span style=\"font-size:12px\">To download the slides, demo scripts, and code for each stage of module development (including the final version of the module), see my <\/span><a href=\"https:\/\/www.dropbox.com\/s\/x3g4jes09e46n2k\/PowerShellSummit2014_Speaker_Slides.zip\" target=\"_blank\" style=\"font-size:12px\">Dropbox<\/a><span style=\"font-size:12px\"> site.<\/span>\nBye for now.<\/p>\n<p style=\"margin-left:30px\"><strong>Biography<\/strong><\/p>\n<p style=\"margin-left:30px\">Richard Siddaway is based out of the UK. He spends his time automating anything and everything, for Kelway, Ltd. A 7-year Windows PowerShell MVP, Richard is a prolific blogger, mainly about Windows PowerShell (see <a href=\"http:\/\/msmvps.com\/blogs\/richardsiddaway\/default.aspx\" target=\"_blank\">Richard Siddaway&#8217;s Blog<\/a>). Richard has been a director at PowerShell.org since the inception of that organization, and he is a frequent speaker at Windows PowerShell user groups and conferences. He has written a number of books: PowerShell in Practice, PowerShell and WMI, PowerShell in Depth (co-author), PowerShell Dive (co-editor), and Learn Active Directory Management in a Month of Lunches, which features lots of Windows PowerShell. All of the books are available from <a href=\"http:\/\/www.manning.com\/\" target=\"_blank\">Manning Publications<\/a>.\nWe invite you to follow The Scripting Guys on&nbsp;<a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a>&nbsp;and&nbsp;<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&nbsp;<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,&nbsp;<\/b>Windows PowerShell MVP and Honorary Scripting Guy<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Richard Siddaway shows how to complete the registry CDXML module. Honorary Scripting Guy, Richard Siddaway, here today filling in for my good friend, The Scripting Guy. This is the final post in a series. To catch up, read: Registry Cmdlets: Working with the Registry Registry Cmdlets: First Steps with CDXML Registry Cmdlets: Advanced CDXML [&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-74205","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 how to complete the registry CDXML module. Honorary Scripting Guy, Richard Siddaway, here today filling in for my good friend, The Scripting Guy. This is the final post in a series. To catch up, read: Registry Cmdlets: Working with the Registry Registry Cmdlets: First Steps with CDXML Registry Cmdlets: Advanced CDXML [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/74205","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=74205"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/74205\/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=74205"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=74205"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=74205"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}