<?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>Dives Archives - LucD notes</title>
	<atom:link href="https://www.lucd.info/knowledge-base/category/kb-dives/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.lucd.info/knowledge-base/category/kb-dives/</link>
	<description>My PowerShell ramblings</description>
	<lastBuildDate>Mon, 22 Jun 2020 09:55:33 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.9</generator>

<image>
	<url>https://www.lucd.info/wp-content/uploads/2018/12/cropped-120px-Tibetan_Dharmacakra-32x32.png</url>
	<title>Dives Archives - LucD notes</title>
	<link>https://www.lucd.info/knowledge-base/category/kb-dives/</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>Find allowed HW versions</title>
		<link>https://www.lucd.info/knowledge-base/find-allowed-hw-versions/</link>
					<comments>https://www.lucd.info/knowledge-base/find-allowed-hw-versions/#respond</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Mon, 22 Jun 2020 09:55:28 +0000</pubDate>
				<guid isPermaLink="false">https://www.lucd.info/?post_type=epkb_post_type_1&#038;p=7296</guid>

					<description><![CDATA[The importance of using the correct HW version for your VMs is documented [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>The importance of using the correct HW version for your VMs is documented in many KBs.</p>
<p>But which HW versions can you use in your environment? </p>



<p>It seems there is no enumeration available listing all the valid HW versions. But we can use the a REST API call to query the vCenter.</p>



<pre class="wp-block-code"><code>$vcName = 'vcsa.fqdn'
$hwService = 'com.vmware.vcenter.vm.hardware'

try{
    Connect-CisServer -Server $vcName -ErrorAction Stop
}
catch{
    throw "Connection to the $vcName vSphere Automation SDK server failed."
}


$hw = Get-CisService | where{$_.Name -eq $hwService}
$validHWVersion = $hw.Help.upgrade.version.Element.CreateExample().Split(':')&#91;1].TrimEnd('.').Replace(' ','').Split(',')

Disconnect-CisServer -Server $vcName -Confirm:$false
</code></pre>



<p>In the array <strong>$validHWVersion</strong> you will now have the permitted HW versions for your environment.</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="437" height="288" src="https://www.lucd.info/wp-content/uploads/2020/06/hw.png" alt="" class="wp-image-7297" srcset="https://www.lucd.info/wp-content/uploads/2020/06/hw.png 437w, https://www.lucd.info/wp-content/uploads/2020/06/hw-300x198.png 300w" sizes="(max-width: 437px) 100vw, 437px" /></figure>



<p>On a side note, use the <strong>HardwareVersion</strong> parameter on the <a href="https://vdc-repo.vmware.com/vmwb-repository/dcr-public/6bd6daa3-08a8-4660-9159-23265b9d6c00/4d533cf0-f009-4fa0-8679-8d505fbe846b/doc/Set-VM.html" target="_blank" rel="noopener noreferrer">Set-VM</a> cmdlet to configure the HW version for a VM. The <strong>Version</strong> parameter is deprecated.</p>



<pre class="wp-block-code"><code>Get-VM -Name MyVM | Set-VM -HardwareVersion vmx-17</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/knowledge-base/find-allowed-hw-versions/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>A VM memory dump</title>
		<link>https://www.lucd.info/knowledge-base/a-vm-memory-dump/</link>
					<comments>https://www.lucd.info/knowledge-base/a-vm-memory-dump/#respond</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Sun, 26 Apr 2020 10:58:45 +0000</pubDate>
				<guid isPermaLink="false">https://www.lucd.info/?post_type=epkb_post_type_1&#038;p=7264</guid>

					<description><![CDATA[There are occasions when you need to take a memory dump of a [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>There are occasions when you need to take a <strong>memory dump</strong> of a problematic VM.<br>A <strong>Snapshot</strong> taken with the <strong>Memory</strong> option is all that is required.</p>
<p>The following script shows you can automate this for 1 or more VMs.</p>



<pre class="wp-block-code"><code>$data = @'
vCenter,VM
vcsa1,vm1
vcsa2,vm2
'@

$dumpLocation = 'C:\MemeoryDumps'
$dumpItem = Get-Item -Path $dumpLocation

ConvertFrom-Csv -InputObject $data -UseCulture -PipelineVariable row |
ForEach-Object -Process {
    Connect-VIServer -Server $row.vCenter

    $vm = Get-VM -Name $row.VM
    $snap = New-Snapshot -VM $vm -Name "Memory dump" -Memory -Confirm:$false
    if($snap){
        $vm.ExtensionData.UpdateViewData('Layout.Snapshot')
        $snapObj = $vm.ExtensionData.LayoutEx.Snapshot | where{$_.Key -eq $snap.Id}
        if($snapObj){
            Get-Item -Path "$dumpLocation\$($row.VM)" | Remove-Item -Recurse -Confirm:$false
            $tgtDir = New-Item -Path $dumpLocation -Name "$($row.VM)" -ItemType Directory
            $files = @()
            $files += $vm.ExtensionData.LayoutEx.File | where{$_.Key -eq $snapObj.MemoryKey} | select -ExpandProperty Name
            $files += $vm.ExtensionData.LayoutEx.File | where{$_.Key -eq $snapObj.DataKey} | select -ExpandProperty Name
            $files | ForEach-Object -Process {
                $dsName,$filePath = $_.Split(' ')
                $ds = Get-Datastore -Name $dsName.Trim('&#91;]')
                New-PSDrive -Location $ds -Name DS -PSProvider VimDatastore -Root "\" | Out-Null
                Copy-DatastoreItem -Item "DS:$filePath" -Destination $tgtDir -Confirm:$false
                Remove-PSDrive -Name DS -Confirm:$false 
            }
        }
        else{
            Write-Output "Failed to retrieve snapshot info for $($row.VM)"
        }
        Remove-Snapshot -Snapshot $snap -Confirm:$false | Out-Null
    }
    else{
        Write-Output "Snapshot failed for $($row.VM)"
    }

    Disconnect-VIServer -Server $row.vCenter -Confirm:$false
}</code></pre>



<p>The script uses a here-string and the ConvertFrom-Csv cmdlet to get the names of the vCenters and the VMs, but you can easily change this to any source for providing the information.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/knowledge-base/a-vm-memory-dump/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Passing an array to background jobs</title>
		<link>https://www.lucd.info/knowledge-base/passing-an-array-to-background-jobs/</link>
					<comments>https://www.lucd.info/knowledge-base/passing-an-array-to-background-jobs/#respond</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Thu, 09 Jan 2020 09:37:17 +0000</pubDate>
				<guid isPermaLink="false">http://www.lucd.info/?post_type=epkb_post_type_1&#038;p=7111</guid>

					<description><![CDATA[One issue you might encounter when using background jobs is how to pass [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>One issue you might encounter when using background jobs is how to pass parameters to these jobs. And more specifically arrays.</p>



<p>The issue is that all values on ArgumentList are passed as one array to the code block of the Start-Job cmdlet. The trick is to to present your array as one value to the background job. This can be done through the array notation with <strong>(,$myArray)</strong>.</p>



<p>An example</p>



<pre class="lang:ps decode:true ">$job = {
    param(
        [PSObject[]]$Array
    )

    $Array | ForEach-Object -Process {
        $_
    }
}

$arrP = 1..4 | ForEach-Object -Process {
    New-Object -TypeName PSObject -Property @{
        Field1 = $_
        Field2 = $_ * 2
    }
}

Start-Job -ScriptBlock $job -ArgumentList (,$arrP) |
Wait-Job | Receive-Job -Keep</pre>



<p>If you need to pass multiple arguments, you can add these on the <strong>ArgumentList</strong> parameter. Like this.</p>



<pre class="lang:ps decode:true ">$job = {
    param(
        [string]$String1,
        [PSObject[]]$Array,
        [string]$String2
    )

    $String1
    $String2
    $Array | ForEach-Object -Process {
        $_
    }
}

$arrP = 1..4 | ForEach-Object -Process {
    New-Object -TypeName PSObject -Property @{
        Field1 = $_
        Field2 = $_ * 2
    }
}

Start-Job -ScriptBlock $job -ArgumentList 'Test1',(,$arrP),'Test2' |
Wait-Job | Receive-Job -Keep</pre>



<p>This also works when you need to pass <strong>multiple arrays</strong> to the background job.</p>



<pre class="lang:ps decode:true ">$job = {
    param(
        [string]$String1,
        [PSObject[]]$Array1,
        [string]$String2,
        [PSObject[]]$Array2,
        [string]$String3
    )

    $String1
    $Array1 | %{$_}
    $String2
    $Array2 | %{$_}
    $String3
}

$arr1 = 1..4 | ForEach-Object -Process {
    New-Object -TypeName PSObject -Property @{
        Field1 = $_
        Field2 = $_ * 2
    }
}
$arr2 = 1..2| ForEach-Object -Process {
    New-Object -TypeName PSObject -Property @{
        Field3 = $_
        Field4 = $_ * 3
    }
}

Start-Job -ScriptBlock $job -ArgumentList 'Test1',(,$arr1),'Test2',(,$arr2),'Test3' |
Wait-Job | Receive-Job -Keep</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/knowledge-base/passing-an-array-to-background-jobs/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>VSC and PowerCLI&#8217;s VimInventory and VimDatastore providers.</title>
		<link>https://www.lucd.info/knowledge-base/vsc-and-powerclis-viminventory-and-vimdatastore-providers/</link>
					<comments>https://www.lucd.info/knowledge-base/vsc-and-powerclis-viminventory-and-vimdatastore-providers/#comments</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Thu, 12 Sep 2019 08:38:56 +0000</pubDate>
				<guid isPermaLink="false">http://www.lucd.info/?post_type=epkb_post_type_1&#038;p=6427</guid>

					<description><![CDATA[Currently Visual Studio Code is the de facto preferred editor for PowerShell and [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Currently <a href="https://code.visualstudio.com/" target="_blank" rel="noopener noreferrer">Visual Studio Code</a> is the de facto preferred editor for PowerShell and PowerCLI scripts.<br>But there is a tiny problem when you try to mount a datastore as a PSDrive in the PowerShell Integrated Console.</p>



<p>Due to the way PowerCLI is written, it is not possible to use the <strong>VimInventory</strong> and <strong>VimDatastore</strong> providers, that come with PowerCLI, from the PowerShell Integrated Console.</p>



<p>Note that this is the console that shows the following.</p>



<figure class="wp-block-image"><img decoding="async" width="894" height="280" src="https://www.lucd.info/wp-content/uploads/2019/09/host.png" alt="" class="wp-image-6429" srcset="https://www.lucd.info/wp-content/uploads/2019/09/host.png 894w, https://www.lucd.info/wp-content/uploads/2019/09/host-300x94.png 300w, https://www.lucd.info/wp-content/uploads/2019/09/host-768x241.png 768w, https://www.lucd.info/wp-content/uploads/2019/09/host-720x226.png 720w" sizes="(max-width: 894px) 100vw, 894px" /></figure>



<p>You will see the following error when you try to set up a drive with one of these providers.</p>



<figure class="wp-block-image"><img decoding="async" width="952" height="157" src="https://www.lucd.info/wp-content/uploads/2019/09/psprovider.png" alt="" class="wp-image-6428" srcset="https://www.lucd.info/wp-content/uploads/2019/09/psprovider.png 952w, https://www.lucd.info/wp-content/uploads/2019/09/psprovider-300x49.png 300w, https://www.lucd.info/wp-content/uploads/2019/09/psprovider-768x127.png 768w, https://www.lucd.info/wp-content/uploads/2019/09/psprovider-720x119.png 720w" sizes="(max-width: 952px) 100vw, 952px" /></figure>



<p>This is a known problem and mentioned in <a href="https://github.com/PowerShell/PowerShellEditorServices/issues/543" target="_blank" rel="noopener noreferrer">PowerShell/PowerShellEditorServices Issue #543</a> and also in the VMTN thread <a href="https://communities.vmware.com/message/2853575#2853575" name="&amp;lpos=apps_scodevmw : 83">Microsoft Visual Studio Code (VS Code) can not access vi and vis, vmstore and vmstores. Get-PSDrive and New-PSDrive -PSProvider VimDatastore dont work as expected</a></p>



<p>A couple of workarounds are available:</p>



<ul class="wp-block-list"><li>Disable the PSScriptAnalyzer in VSC</li><li>Don&#8217;t hover over PowerCLI cmdlets in the editor.</li><li>Load the PowerCLI modules before hovering over a PowerCLI cmdlet in the editor</li></ul>



<p>Of course, the preferred solution is option 3 from that list. And since VSC has it&#8217;s own profile, it is quite easy to implement.</p>



<p>Create/modify the VSC PowerShell profile, with</p>



<pre class="wp-block-code"><code>notepad $profile</code></pre>



<p>In the profile file, add the following line</p>



<pre class="wp-block-code"><code>Import-Module -Name VMware.PowerCLI 6> $null</code></pre>



<p>The redirection of <strong>stream 6</strong> is intended to suppress the <strong>Write-Host</strong> output from loading the VMware.PowerCLI module. This will only work in <strong>PowerShell v5</strong>, and higher.</p>



<p>If you find the output produced by loading the VMware.PowerCLI module annoying, there is a <a href="https://powercli.ideas.aha.io/ideas/PCLI-I-164" target="_blank" rel="noreferrer noopener" aria-label="PowerCLI Idea (opens in a new tab)">PowerCLI Idea</a> that asks to suppress this &#8220;feature&#8221;. Please upvote the issue if you also would like to see this removed.</p>


]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/knowledge-base/vsc-and-powerclis-viminventory-and-vimdatastore-providers/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Find VM based on MAC</title>
		<link>https://www.lucd.info/knowledge-base/find-vm-based-on-mac/</link>
					<comments>https://www.lucd.info/knowledge-base/find-vm-based-on-mac/#respond</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Sat, 18 May 2019 05:20:06 +0000</pubDate>
				<guid isPermaLink="false">http://www.lucd.info/?post_type=epkb_post_type_1&#038;p=6369</guid>

					<description><![CDATA[This sample query shows one way of finding a VM which has a [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>This sample query shows one way of finding a VM which has a vNIC with a specific MAC address.</p>
<p>The following might seem a bit cryptic at first, but it turns out to be the <strong>fastest method</strong> I came up with till now.</p>
<p>It uses the <strong>where-method</strong> instead of the <strong>Where-Object</strong> cmdlet. See also <a href="https://www.lucd.info/knowledge-base/use-the-faster-methods/" target="_blank" rel="noopener noreferrer">Use the ‘faster’ methods</a>.</p>
<p>&nbsp;</p>



<pre class="wp-block-code"><code>$mac = '12:34:56:78:90:12'
$sView = @{
    ViewType = 'VirtualMachine'
    Property = 'Name','Config.Hardware.Device'
}
(Get-View @sView).Where{$_.Config.Hardware.Device.Where{$_ -is [VMware.Vim.VirtualEthernetCard] -and $_.MacAddress.Equals($mac)}} |
Select-Object Name</code></pre>



<p>If you need to look for a number of MAC addresses, you can do</p>



<pre class="wp-block-code"><code>$macs = '12:34:56:78:90:12','12:34:56:78:90:34','12:34:56:78:90:56'

$sView = @{
    ViewType = 'VirtualMachine'
    Property = 'Name','Config.Hardware.Device'
}
(Get-View @sView).Where{$_.Config.Hardware.Device.Where{$_ -is [VMware.Vim.VirtualEthernetCard] -and $macs -contains $_.MacAddress}} |
Select-Object Name</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/knowledge-base/find-vm-based-on-mac/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Running a background job</title>
		<link>https://www.lucd.info/knowledge-base/running-a-background-job/</link>
					<comments>https://www.lucd.info/knowledge-base/running-a-background-job/#comments</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Wed, 17 Apr 2019 09:14:29 +0000</pubDate>
				<guid isPermaLink="false">http://www.lucd.info/?post_type=epkb_post_type_1&#038;p=6356</guid>

					<description><![CDATA[PowerShell has a nifty feature that allows you to run code in the [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>PowerShell has a nifty feature that allows you to run code in the background. This is done through the <a rel="noreferrer noopener" aria-label="Start-Job (opens in a new tab)" href="https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/start-job?view=powershell-6" target="_blank">Start-Job</a> cmdlet.</p>



<p>When you want to run PowerCLI code in the background, there are a number of conditions to take care of.</p>



<ul class="wp-block-list"><li>Your existing connection to a vSphere Server (vCenter or ESXi) is not inherited by the background job. You will have to establish the connection in the background job. With the SessionId parameter, you can reuse an existing connection.</li><li>A background job shouldn&#8217;t rely on any interactivity. For that reason you want to disable all warning messages any of the PowerCLI cmdlets might generate</li><li>A background job normally has no access to the variables defined in the calling code. You can pass values through the ArgumentList parameter on the Start-Job cmdlet.</li><li> You do not need to include any Import-Module cmdlets in your background job., when<ul><li> you are using a PowerShell version (v3 and above) that supports the module autoloading feature</li><li>you have the PowerCLI modules installed in one of the folders listed in <strong>$env:PSMOdulePath</strong>,</li><li>you haven&#8217;t used  the  <strong>$PSModuleAutoLoadingPreference</strong> variable to change the default behaviour</li></ul></li></ul>



<p>The following is a minimal example of such a background job. It will call the Get-VM cmdlet for a specific VM&#8217;s name.</p>



<pre class="wp-block-code"><code>$code = {
    param(
        [string]$Server,
        [string]$SessionId,
        [string]$VMName
    )

    Set-PowerCLIConfiguration -DisplayDeprecationWarnings $false -Confirm:$false | Out-Null
    Connect-VIServer -Server $Server -Session $SessionId
    Get-VM -Name $VMName
}

$vmName = 'TestVM'
$sJOb = @{
    ScriptBlock = $code
    ArgumentList = $global:DefaultVIServer.Name, $global:DefaultVIServer.SessionId, $vmName
}
Start-Job @sJob</code></pre>



<p>Once a job is started in the background, you can wait for its completion and &#8216;receive&#8217; the output. For example like this.</p>



<pre class="wp-block-code"><code>$j = Start-Job @sJob

Receive-Job -Job $j -Wait</code></pre>



<p>Get acquainted with all the Job related cmdlet to use background jobs at their fullest potential. </p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/knowledge-base/running-a-background-job/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Here string and variable substitution</title>
		<link>https://www.lucd.info/knowledge-base/here-string-and-variable-substitution/</link>
					<comments>https://www.lucd.info/knowledge-base/here-string-and-variable-substitution/#comments</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Thu, 15 Nov 2018 10:49:52 +0000</pubDate>
				<guid isPermaLink="false">http://www.lucd.info/?post_type=epkb_post_type_1&#038;p=6127</guid>

					<description><![CDATA[As mentioned in another Dive (see Here strings and the ExpandString method) Here [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>As mentioned in another Dive (see <a href="https://www.lucd.info/knowledge-base/here-strings-and-the-expandstring-method/" target="_blank" rel="noreferrer noopener" aria-label="As mentioned in another Dive (see Here strings and the ExpandString method) (opens in a new tab)">Here strings and the ExpandString method</a>) Here strings are a convenient way to prepare scripts you are submitting through <a href="https://vdc-repo.vmware.com/vmwb-repository/dcr-public/7837e367-fe26-4d85-bd03-84d88261642c/bd07bd63-ee2b-4bf8-bc0c-e7f99d4bfd17/doc/Invoke-VMScript.html" target="_blank" rel="noreferrer noopener" aria-label="As mentioned in another Dive (see Here strings and the ExpandString method) Here strings are a convenient way to prepare scripts you are submitting through Invoke-VMScript or Invoke-VMScriptPlus. (opens in a new tab)">Invoke-VMScript</a> or <a href="https://www.lucd.info/2018/08/05/invoke-vmscriptplus-v2/" target="_blank" rel="noreferrer noopener" aria-label="As mentioned in another Dive (see Here strings and the ExpandString method) Here strings are a convenient way to prepare scripts you are submitting through Invoke-VMScript or Invoke-VMScriptPlus. (opens in a new tab)">Invoke-VMScriptPlus</a>.</p>



<p>But there are some caveats you should be aware off. Most of these are how the variable substitution will work when you call the ExpandString method.</p>



<ul class="wp-block-list">
<li>For variables you don&#8217;t want to be substituted, you need to escape the dollar sign with a back-tick. Note that this is also true for the Booleans $true and $false.</li>
</ul>
<pre class="lang:ps decode:true ">$data = @'
<code>$var1 = $val1
</code>$var2 = <code>$true
'@

$val1 = 1

$ExecutionContext.InvokeCommand.ExpandString($data)
</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-6130" src="https://www.lucd.info/wp-content/uploads/2018/11/sub1.jpg" alt="" width="252" height="44" /></p>
<ul>
<li>Put strings in quotes, otherwise PowerShell will try to interpret them as cmdlets or functions.</li>
</ul>
<pre class="lang:ps decode:true ">$data = @'
</code>$var1 = '$str1' 
'@

$str1 = 'A string'

$ExecutionContext.InvokeCommand.ExpandString($data)</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-6131" src="https://www.lucd.info/wp-content/uploads/2018/11/sub2.jpg" alt="" width="266" height="34" srcset="https://www.lucd.info/wp-content/uploads/2018/11/sub2.jpg 266w, https://www.lucd.info/wp-content/uploads/2018/11/sub2-265x34.jpg 265w" sizes="auto, (max-width: 266px) 100vw, 266px" /></p>
<ul>
<li>When referencing properties from an object, use the correct notation.</li>
</ul>
<pre class="lang:ps decode:true ">$data = @'
`$var1 = '$($obj.Field1)\Temp' 
'@

$obj = New-Object PSObject -Property @{
    Field1 = 'C:'
}

$ExecutionContext.InvokeCommand.ExpandString($data)</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-6132" src="https://www.lucd.info/wp-content/uploads/2018/11/sub3.jpg" alt="" width="237" height="35" /></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/knowledge-base/here-string-and-variable-substitution/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Table vs List</title>
		<link>https://www.lucd.info/knowledge-base/table-vs-list/</link>
					<comments>https://www.lucd.info/knowledge-base/table-vs-list/#respond</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Mon, 12 Nov 2018 08:25:23 +0000</pubDate>
				<guid isPermaLink="false">http://www.lucd.info/?post_type=epkb_post_type_1&#038;p=6097</guid>

					<description><![CDATA[When you are using the Select-Object cmdlet, you might have noticed that the [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>When you are using the <strong>Select-Object</strong> cmdlet, you might have noticed that the results are sometimes displayed as a <strong>table</strong> and sometimes as a <strong>list</strong>. It is handy to understand what the logic behind this is.</p>



<p>The basic rule is quite simple, if you display less than <strong>5 properties</strong>, the PowerShell output engine will display the results as a table.</p>
<pre class="lang:ps decode:true ">Get-VM -Name TS? | Select Name,PowerState,NumCpu,MemoryGB</pre>
<p>Results in</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-6100" src="https://www.lucd.info/wp-content/uploads/2018/11/select1.jpg" alt="" width="276" height="102" /></p>
<p>

</p>
<p>When there are 5 or more properties, the output will be displayed as a list.</p>
<pre class="lang:ps decode:true ">Get-VM -Name TS? | Select Name,PowerState,NumCpu,MemoryGB,UsedSpaceGB</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-medium wp-image-6101" src="https://www.lucd.info/wp-content/uploads/2018/11/select2-300x274.jpg" alt="" width="300" height="274" srcset="https://www.lucd.info/wp-content/uploads/2018/11/select2-300x274.jpg 300w, https://www.lucd.info/wp-content/uploads/2018/11/select2.jpg 377w" sizes="auto, (max-width: 300px) 100vw, 300px" /></p>
<p>

</p>
<p>Another rule worth knowing, is that the first Select-Object output determines how the other Select-Object outputs in your script will be displayed.</p>
<p>

</p>
<p>The 1st one shows 5 properties, so it will be displayed as a list. But also the 2nd one, which only displays 3 properties, will also be displayed as a list.</p>
<pre class="lang:ps decode:true ">Get-VM -Name TS? | Select Name,PowerState,NumCpu,MemoryGB,UsedSpaceGB
Get-VM -Name TS? | Select Name,PowerState,NumCpu,MemoryGB
</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-medium wp-image-6102" src="https://www.lucd.info/wp-content/uploads/2018/11/select3-181x300.jpg" alt="" width="181" height="300" srcset="https://www.lucd.info/wp-content/uploads/2018/11/select3-181x300.jpg 181w, https://www.lucd.info/wp-content/uploads/2018/11/select3.jpg 367w" sizes="auto, (max-width: 181px) 100vw, 181px" /></p>
<p>When you do the reverse, you will notice that the output is in table format, but the 5th property will not be shown.</p>
<pre class="lang:ps decode:true ">Get-VM -Name TS? | Select Name,PowerState,NumCpu,MemoryGB
Get-VM -Name TS? | Select Name,PowerState,NumCpu,MemoryGB,UsedSpaceGB
</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-6103" src="https://www.lucd.info/wp-content/uploads/2018/11/select4.jpg" alt="" width="260" height="159" /></p>
<p>One way to avoid that the 1st Select-Object determines how the others in your script behave, is to use the <strong>Out-Default</strong> cmdlet.<br />This cmdlet kind of &#8220;resets&#8221; the output, and so the 5-properties rules will be applied as if it was the first Select-Object.</p>
<pre class="lang:ps decode:true ">Get-VM -Name TS? | Select Name,PowerState,NumCpu,MemoryGB | Out-Default
Get-VM -Name TS? | Select Name,PowerState,NumCpu,MemoryGB,UsedSpaceGB
</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-medium wp-image-6104" src="https://www.lucd.info/wp-content/uploads/2018/11/select5-235x300.jpg" alt="" width="235" height="300" srcset="https://www.lucd.info/wp-content/uploads/2018/11/select5-235x300.jpg 235w, https://www.lucd.info/wp-content/uploads/2018/11/select5.jpg 375w" sizes="auto, (max-width: 235px) 100vw, 235px" /></p>
<p></p>]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/knowledge-base/table-vs-list/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Here strings and the ExpandString method</title>
		<link>https://www.lucd.info/knowledge-base/here-strings-and-the-expandstring-method/</link>
					<comments>https://www.lucd.info/knowledge-base/here-strings-and-the-expandstring-method/#respond</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Sun, 11 Nov 2018 20:19:34 +0000</pubDate>
				<guid isPermaLink="false">http://www.lucd.info/?post_type=epkb_post_type_1&#038;p=6073</guid>

					<description><![CDATA[A here string is a handy method to specify text, like for example [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>A here string is a handy method to specify text, like for example a command.<br />But when you want to use that command in a loop, and need to change a parameter on the command for each iteration it is handy to know about the <strong>ExpandString</strong> method.</p>
<pre class="lang:ps decode:true ">$cmd = @'
vmkping -c 5 $ip
'@

$ipTargets = '192.168.1.1','192.168.1.2'

$session = New-SSHSession -ComputerName $esx.Name -Credential $cred –AcceptKey

foreach($ip in $ipTargets){
    $cmdSub = $ExecutionContext.InvokeCommand.ExpandString($cmd) 
    $result = Invoke-SSHCommand -SSHSession $session -Command $cmdSub 
}

Remove-SSHSession -SSHSession $session | Out-Null 
</pre>
<p>Note that we have single quotes on the here string, so there will be no variable substitution.</p>
<p>In the foreach loop we populate the $ip variable with the different target IPs. Then we force variable substitution with the ExpandString method.</p>
<p>In case you have your data in an object, you will have to use the normal conventions for variable substitution in a string.</p>
<pre class="lang:ps decode:true ">$cmd = @'
vmkping -c 5 $($obj.ip)
'@

$ipTargets = (New-Object PSObject -Property @{IP = '192.168.1.1'}),
            (New-Object PSObject -Property @{IP = '192.168.1.2'})

$session = New-SSHSession -ComputerName $esx.Name -Credential $cred –AcceptKey

foreach($obj in $ipTargets){
    $cmdSub = $ExecutionContext.InvokeCommand.ExpandString($cmd) 
    $result = Invoke-SSHCommand -SSHSession $session -Command $cmdSub 
}

Remove-SSHSession -SSHSession $session | Out-Null </pre>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/knowledge-base/here-strings-and-the-expandstring-method/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Use Posh-SSH instead of PuTTY</title>
		<link>https://www.lucd.info/knowledge-base/use-posh-ssh-instead-of-putty/</link>
					<comments>https://www.lucd.info/knowledge-base/use-posh-ssh-instead-of-putty/#comments</comments>
		
		<dc:creator><![CDATA[LucD]]></dc:creator>
		<pubDate>Sun, 11 Nov 2018 20:15:06 +0000</pubDate>
				<guid isPermaLink="false">http://www.lucd.info/?post_type=epkb_post_type_1&#038;p=6070</guid>

					<description><![CDATA[During the pre-Posh-SSH module times we often used the PuTTY Suite to run [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>During the pre-Posh-SSH module times we often used the PuTTY Suite to run commands on our ESXi nodes.</p>



<p>With the arrival of the Posh-SSH module, there is no more need to use any of the PuTTY EXE.</p>



<p>Running a command on an ESXi node, provided SSH is running, is now as simple as:</p>
<pre class="lang:ps decode:true ">$session = New-SSHSession -ComputerName $esx.Name -Credential $cred –AcceptKey

$result = Invoke-SSHCommand -SSHSession $session -Command $cmdSub 

Remove-SSHSession -SSHSession $session | Out-Null 
</pre>
<p>&nbsp;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.lucd.info/knowledge-base/use-posh-ssh-instead-of-putty/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
	</channel>
</rss>
