<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Crescendo Archives - LucD notes</title>
	<atom:link href="https://www.lucd.info/tag/crescendo/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.lucd.info/tag/crescendo/</link>
	<description>My PowerShell ramblings</description>
	<lastBuildDate>Thu, 10 Dec 2020 15:05:22 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>

<image>
	<url>https://www.lucd.info/wp-content/uploads/2018/12/cropped-120px-Tibetan_Dharmacakra-32x32.png</url>
	<title>Crescendo Archives - LucD notes</title>
	<link>https://www.lucd.info/tag/crescendo/</link>
	<width>32</width>
	<height>32</height>
</image> 
<atom:link rel="hub" href="https://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="https://pubsubhubbub.superfeedr.com"/><atom:link rel="hub" href="https://websubhub.com/hub"/>	<item>
		<title>Crescendo ma non troppo</title>
		<link>https://www.lucd.info/2020/12/10/crescendo-module-preview-1/</link>
					<comments>https://www.lucd.info/2020/12/10/crescendo-module-preview-1/#respond</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Thu, 10 Dec 2020 12:53:27 +0000</pubDate>
				<category><![CDATA[Crescendo]]></category>
		<category><![CDATA[Module]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[VMware Tools]]></category>
		<category><![CDATA[Preview]]></category>
		<guid isPermaLink="false">https://www.lucd.info/?p=7328</guid>

					<description><![CDATA[No, this is not a post about music. This post will be about [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>No, this is not a post about music.</p>
<p>This post will be about my first experiences with the <a href="https://www.powershellgallery.com/packages/Microsoft.PowerShell.Crescendo/0.4.0" target="_blank" rel="noopener">PowerShell Crescendo</a> module, which was just released in <a href="https://devblogs.microsoft.com/powershell/announcing-powershell-crescendo-preview-1/" target="_blank" rel="noopener">Preview 1</a>.</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img fetchpriority="high" decoding="async" width="285" height="223" src="https://www.lucd.info/wp-content/uploads/2020/12/vmw-crescendo-2.png" alt="" class="wp-image-7331"/></figure></div>



<p>Now, why would I care to write a post about a preview of a module?</p>



<p>The reason is quite simple. This module is, in my opinion, covering something that was missing in PowerShell. Namely the possibility to use <strong>native commands</strong>, and present the results as <strong>objects</strong>.</p>
<p>The blog post by <a href="https://twitter.com/theJasonHelmick" target="_blank" rel="noopener">Jason Helmick</a> I linked to earlier explains this all in more detail.</p>



<p>What follows are my first, admittedly simple, trials using the <a href="https://www.powershellgallery.com/packages/Microsoft.PowerShell.Crescendo/0.4.0" target="_blank" rel="noopener">Crescendo module</a>. If you don&#8217;t want to copy code from this post, I created the <a class="" href="https://github.com/lucdekens/VMW-Crescendo" data-pjax="#js-repo-pjax-container">VMW-Crescendo</a> repository that contains all the files.</p>



<span id="more-7328"></span>



<h2 class="wp-block-heading">An Example</h2>



<p>The first example I tackled is the DOS command <a href="https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/tasklist" target="_blank" rel="noopener">tasklist</a>, which displays a list of the running processes.&nbsp;</p>



<p>Not to complicate things at the start, I decided to only implement the module for running <strong>tasklist</strong> on the <strong>local computer</strong>.</p>
<p>And needless to say, since this is a DOS command, it will <strong>not run</strong> on other platforms besides Windows.</p>



<p>The idea behind the <strong>Crescendo module</strong> is that you write in <a href="https://en.wikipedia.org/wiki/JSON" target="_blank" rel="noopener">JSON</a>, how the cmdlet(s) you will create use the native command. This not only includes specifying which <strong>parameters</strong> are used but also how the returned <strong>output</strong> will be converted to an <strong>object</strong>.</p>



<p>Since PowerShell contains cmdlets to convert to and from JSON, I decided to try and write those <strong>definitions in PowerShell</strong>. And then convert that code to JSON format, which I could then feed to the Crescendo cmdlet.</p>



<h3 class="wp-block-heading">The Code</h3>



<pre class="lang:ps decode:true  ">#Requires -Version 7.0

#region An example

$taskConfig = @{
  '$schema' = './Microsoft.PowerShell.Crescendo.Schema.json'
  'Verb' = 'Get'
  'Noun' = 'TaskList'
  'OriginalName' = 'tasklist'
  'OriginalCommandElements' = @("/V")
  'OutputHandlers' = @(
        @{
            'ParameterSetName' = 'Default'
            'Handler' = {
              $labels = $args&#91;0]&#91;1]
              $index = 0
              $fieldInfo = $args&#91;0]&#91;2].Split(' ') | ForEach-Object -Process {
                @{
                  start = $index
                  length = $_.Length
                }
                $index += $_.Length + 1
              }
              $args&#91;0] | Select-Object -skip 3 -PipelineVariable row | ForEach-Object -Process {
                $obj = &#91;ordered]@{}
                $fieldInfo | ForEach-Object -Process {
                  $obj.Add($labels.SubString($_.start,$_.length).Trim(' '),$row.SubString($_.start,$_.length).Trim(' '))
                }
                New-Object -TypeName PSObject -Property $obj
              }
            }
        }
  )
}

$taskConfig | ConvertTo-Json | Set-Content -Path "$PSScriptRoot\tasklist.json"

Export-CrescendoModule -ConfigurationFile "$PSScriptRoot\tasklist.json" -ModuleName "$PSScriptRoot\TaskList.psm1" -Force -Confirm:$false

#endregion
</code></pre>



<h3 class="wp-block-heading">Annotations</h3>



<p><strong>Line 1</strong>: Although the blog post mentions that a module generated with Crescendo can be used on PowerShell 5.1 and 7, I noticed that since the generated code uses the ternary operator, this not really the case. Hence the requirement to run this on PowerShell v7.</p>



<p><strong>Line 5-35</strong>: As I mentioned earlier, I created the definition of the cmdlets to be created in PowerShell.</p>



<p><strong>Line 10</strong>: By default, the tasklist command is started with the <strong>/V</strong> (for verbose) parameter.</p>



<p><strong>Line 11-33</strong>: The <strong>OutputHandler</strong> is where you define how the output of the native command will be converted to an object. I did have to use some &#8216;trickery&#8217; to avoid having to use hard-coded offset. Luckily the one can use the underlining to determine the start and length of each column.</p>



<p><strong>Line 37</strong>: The Powershell object is converted to JSON code, and saved to a file.</p>



<p><strong>Line 39</strong>: The Export-CrescendoModule cmdlet takes the JSON file and generates the module.</p>





<h3 class="wp-block-heading">Sample Run</h3>



<p>The generated modules, at least in this Preview 1, only generate a <strong>.psm1</strong> file. You can use the <strong>Import-Module</strong> pointing to that .psm1 file.</p>



<p>The module contains the <strong>Get-TaskList</strong> cmdlet, that requires no further parameters and returns a series of objects, containing the results.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="823" height="535" src="https://www.lucd.info/wp-content/uploads/2020/12/gettasklist.png" alt="" class="wp-image-7337" srcset="https://www.lucd.info/wp-content/uploads/2020/12/gettasklist.png 823w, https://www.lucd.info/wp-content/uploads/2020/12/gettasklist-300x195.png 300w, https://www.lucd.info/wp-content/uploads/2020/12/gettasklist-768x499.png 768w, https://www.lucd.info/wp-content/uploads/2020/12/gettasklist-720x468.png 720w" sizes="(max-width: 823px) 100vw, 823px" /></figure>



<p>Since the Get-TaskList cmdlet returns objects, we can now easily use other PowerShell cmdlets to further handle the returned data. For example:</p>



<pre class="lang:ps decode:true  ">
Get-TaskList | Export-Csv -Path .\TaskList.Csv -NoTypeInformation -UseCulture
</code></pre>



<p>The resulting CSV file contains all the data.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="894" height="295" src="https://www.lucd.info/wp-content/uploads/2020/12/tasklist-csv.png" alt="" class="wp-image-7340" srcset="https://www.lucd.info/wp-content/uploads/2020/12/tasklist-csv.png 894w, https://www.lucd.info/wp-content/uploads/2020/12/tasklist-csv-300x99.png 300w, https://www.lucd.info/wp-content/uploads/2020/12/tasklist-csv-768x253.png 768w, https://www.lucd.info/wp-content/uploads/2020/12/tasklist-csv-720x238.png 720w" sizes="(max-width: 894px) 100vw, 894px" /></figure>



<h2 class="wp-block-heading">VMware Tools Debug Levels</h2>



<p>The second example I concocted, uses one of the native commands that come with the installation of the VMware Tools. The <a href="https://docs.vmware.com/en/VMware-Tools/10.2.0/com.vmware.vsphere.vmwaretools.doc/GUID-009A09B7-60F0-4B38-8908-C7D712E7E63E.html" target="_blank" rel="noopener">VMwareToolboxCmd.exe</a> has the option to <strong>get</strong> and <strong>set</strong> the <a href="https://kb.vmware.com/s/article/1007873" target="_blank" rel="noopener">debug levels</a> on the VMware Tools services.&nbsp;</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="790" height="233" src="https://www.lucd.info/wp-content/uploads/2020/12/dos-cmd.png" alt="" class="wp-image-7344" srcset="https://www.lucd.info/wp-content/uploads/2020/12/dos-cmd.png 790w, https://www.lucd.info/wp-content/uploads/2020/12/dos-cmd-300x88.png 300w, https://www.lucd.info/wp-content/uploads/2020/12/dos-cmd-768x227.png 768w, https://www.lucd.info/wp-content/uploads/2020/12/dos-cmd-720x212.png 720w" sizes="auto, (max-width: 790px) 100vw, 790px" /></figure>



<p>Note that you need to run this command in <strong>Administrator mode</strong>.</p>



<h3 class="wp-block-heading">The Code</h3>



<pre class="lang:ps decode:true  ">
#Requires -Version 7.0

#region VMware Tools debug levels

$getDebugConfig = @{
  '$schema' = './Microsoft.PowerShell.Crescendo.Schema.json'
  'Verb' = 'Get'
  'Noun' = 'ToolsDebugSetting'
  'OriginalName' = "$($env:ProgramFiles)\VMware\VMware Tools\VMwareToolboxCmd.exe"
  'Description' = 'Retrieve the debug levels for VMware Tools'
  'OriginalCommandElements' = 'logging','level','get'
  'Parameters' = @(
    @{
      'Name' = 'Svc'
      'OriginalName' = 'vmsvc'
      'ParameterType' = 'switch'
      'Description' = 'Primary VMware Tools service'
    },
    @{
      'Name' = 'Vss'
      'OriginalName' = 'vmvss'
      'ParameterType' = 'switch'
      'Description' = 'Volume Shadow Copy service'
    },
    @{
      'Name' = 'Resolution'
      'OriginalName' = 'vmresset'
      'ParameterType' = 'switch'
      'Description' = 'Resolution Set Tool'
    },
    @{
      'Name' = 'Tray'
      'OriginalName' = 'vmtray'
      'ParameterType' = 'switch'
      'Description' = 'The Tray icon in Windows'
    },
    @{
      'Name' = 'User'
      'OriginalName' = 'vmusr'
      'ParameterType' = 'switch'
      'Description' = 'The VMware Tools user service'
    },
    @{
      'Name' = 'Toolbox'
      'OriginalName' = 'toolbox'
      'ParameterType' = 'switch'
      'Description' = 'Toolbox UI'
    },
    @{
      'Name' = 'ToolBoxCmd'
      'OriginalName' = 'toolboxcmd'
      'ParameterType' = 'switch'
      'Description' = 'Toolbox command line'
    }
  )
  'OutputHandlers' = @(
        @{
            'ParameterSetName' = 'Default'
            'Handler' = {
              $service,$level = $args[0].Split('=')
              New-Object -TypeName PSObject -Property @{
                "$($service -replace '.level','')" = $level.Trim(' ')
              }
            }
        }
  )
}
$getDebugConfig | ConvertTo-Json | Set-Content -Path "$PSScriptRoot\getdebug.json"

$setDebugConfig = @{
  '$schema' = './Microsoft.PowerShell.Crescendo.Schema.json'
  'Verb' = 'Set'
  'Noun' = 'ToolsDebugSetting'
  'OriginalName' = "$($env:ProgramFiles)\VMware\VMware Tools\VMwareToolboxCmd.exe"
  'Description' = 'Retrieve the debug levels for VMware Tools'
  'OriginalCommandElements' = 'logging', 'level', 'set'
  'Parameters' = @(
    @{
      'Name' = 'Svc'
      'OriginalName' = 'vmsvc'
      'ParameterType' = 'switch'
      'Description' = 'Primary VMware Tools service'
    },
    @{
      'Name' = 'Vss'
      'OriginalName' = 'vmvss'
      'ParameterType' = 'switch'
      'Description' = 'Volume Shadow Copy service'
    },
    @{
      'Name' = 'Resolution'
      'OriginalName' = 'vmresset'
      'ParameterType' = 'switch'
      'Description' = 'Resolution Set Tool'
    },
    @{
      'Name' = 'Tray'
      'OriginalName' = 'vmtray'
      'ParameterType' = 'switch'
      'Description' = 'The Tray icon in Windows'
    },
    @{
      'Name' = 'User'
      'OriginalName' = 'vmusr'
      'ParameterType' = 'switch'
      'Description' = 'The VMware Tools user service'
    },
    @{
      'Name' = 'Toolbox'
      'OriginalName' = 'toolbox'
      'ParameterType' = 'switch'
      'Description' = 'Toolbox UI'
    },
    @{
      'Name' = 'ToolBoxCmd'
      'OriginalName' = 'toolboxcmd'
      'ParameterType' = 'switch'
      'Description' = 'Toolbox command line'
    },
    @{
      'Name' = 'Level'
      'OriginalName' = ''
      'ParameterType' = 'string'
      'Mandatory' = $true
      'Description' = 'New debug level'
    }
    )
    }
$setDebugConfig | ConvertTo-Json | Set-Content -Path "$PSScriptRoot\setdebug.json"

$sCrecendo = @{
  ConfigurationFile = "$($PSScriptRoot)\getdebug.json", "$($PSScriptRoot)\setdebug.json"
  ModuleName = "$($PSScriptRoot)\ToolsDebug.psm1"
  Force = $true
  Confirm = $false
  Verbose = $true
}
Export-CrescendoModule @sCrecendo
#endregion
</code></pre>



<h3 class="wp-block-heading">Annotations</h3>



<p><strong>Line 1</strong>: Although the blog post mentions that a module generated with Crescendo can be used on PowerShell 5.1 and 7, I noticed that since the generated code uses the ternary operator, this not really the case. Hence the requirement to run this on PowerShell v7.</p>



<p><strong>Line 5-66</strong>: This part is the definition for the <strong>Get-ToolsDebugSettings</strong> cmdlet.</p>



<p><strong>Line 11</strong>: With the <strong>OriginalCommandElements</strong> property we define which parameters shall be always added to the native command.</p>



<p><strong>Line 12-55</strong>: Each possible service is defined as a Switch parameter. Each entry also has the cmdlet parameter name (<strong>Name</strong>) and how it shall be translated to a native command parameter (<strong>OriginalName</strong>).</p>



<p><strong>Line 59-63</strong>: The Output Handler takes the line that is returned and converts it into an object.</p>



<p><strong>Line 68</strong>: The PowerShell object is converted into JSON and save to a file.</p>



<p><strong>Line 70-128</strong>: This part is the definition for the <strong>Set-ToolsDebugSettings</strong> cmdlet.</p>



<p><strong>Line 120-126</strong>: The Set cmdlet will have an additional parameter (<strong>Level</strong>) that indicates which new debug level shall be set for the selected service. Note that the debuglevel is added as-is, no parameter on the native command.</p>



<h3 class="wp-block-heading">Sample Run</h3>



<p>The cmdlets from the generated module need to be called from an <strong>elevated prompt</strong> (same as the native command).</p>



<pre class="lang:ps decode:true  ">
#Requires -Version 7.0

Import-Module "$PSScriptRoot\ToolsDebug.psm1" -Force

Get-ToolsDebugSetting -Vss
Set-ToolsDebugSetting -Vss -Level debug
Get-ToolsDebugSetting -Vss
</code></pre>



<p>And just as with the native command we can query and set the debug levels.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="904" height="354" src="https://www.lucd.info/wp-content/uploads/2020/12/tools-debug.png" alt="" class="wp-image-7353" srcset="https://www.lucd.info/wp-content/uploads/2020/12/tools-debug.png 904w, https://www.lucd.info/wp-content/uploads/2020/12/tools-debug-300x117.png 300w, https://www.lucd.info/wp-content/uploads/2020/12/tools-debug-768x301.png 768w, https://www.lucd.info/wp-content/uploads/2020/12/tools-debug-720x282.png 720w" sizes="auto, (max-width: 904px) 100vw, 904px" /></figure>



<h2 class="wp-block-heading">In Conclusion</h2>



<p>Is this new <strong>Crescendo</strong> module something that you should be using immediately?</p>
<p>Definitely not, this is a module, based on an interesting concept, that only just entered <strong>Preview 1</strong>.</p>
<p>But it is surely a concept that is interesting.<br />I&#8217;ll be watching where this goes, and what can be done with it.</p>
<p>Enjoy!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/2020/12/10/crescendo-module-preview-1/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
