Determine possible values for an attribute - powershell

I'm struggling with getting the possible values for an attribute.
I want to generate a report of DTCs (Distributed Transaction Coordinators). With the help I found the cmdlet Get-DtcAdvancedSetting.
With this Get-DtcAdvancedSetting cmdlet it's possible to read the properties. The command looks like this:
$AccountName = Get-DtcAdvancedSetting -Name "AccountName" -DtcName "Local" -Subkey "Security"
This works perfectly. But to read the other properties I have to find out what Names they have.
How can I find out the possible Values for the -Name attribute of the cmdlet Get-DtcAdvancedSetting with the help of PowerShell?
I tried like this:
Get-DtcAdvancedSetting -Name "AccountName" -DtcName "Local" -Subkey "Security" |
Select Name -First 1 |
Get-Member
[Enum]::GetNames('System.String.Name')
I also tried like this:
Get-Command Get-DtcAdvancedSetting |
%{$_.Parameters.Values} |
fl name, ParameterType
[Enum]::GetNames('Microsoft.System.String')
Both ways just give me failures like:
Cannot convert argument "enumType", with value:
Is it possible the get this Values? And if yes how?

The Get-DtcAdvancedSetting cmdlet allows you to query the registry.
So in your case you are probably searching for
Get-ChildItem HKLM:\SOFTWARE\Microsoft\MSDTC | Select -ExpandProperty Property

Related

PowerShell custom output #{n=;e=}

I'm not very clear on how the #{n=;e=} construct works in PowerShell.
Does this type of thing have a name that I can find examples from?
For example, I find examples like this that works great:
gwmi win32_logicaldisk | Format-Table DeviceId, VolumeName, #{n="Size(GB)";e={[math]::Round($_.Size/1GB,2)}},#{n="Free(GB)";e={[math]::Round($_.FreeSpace/1GB,2)}}
When I try to do something like that, I can never get it to work. This works fine:
Get-Command -Module Microsoft.Powershell.Utility | Where CommandType -eq Function | Select Name,Version,CommandType
So I thought I would try and add the definition of that function to a new column using cat function:\$_.Name
Get-Command -Module Microsoft.Powershell.Utility | Where CommandType -eq Function | Select Name,Version,CommandType,#{n="Contents"; e={cat function:\$_.Name}}
But I just get an empty Contents column :(
Can someone give me some pointers on how the #{n=;e=} construct works?
Also, what do the n and e stand for?
#{n='';e={}} syntax is called a calculated property. n stands for Name and e stands for expression. You can even specify Name instead of n and Expression instead of e.
Calculated properties allow you to create new properties or change existing ones. This is done by passing a special hashtable to the Property parameter rather than a static property name. This is a useful feature where you create new properties using custom expression in a script block and use existing properties.
Not for only Select-Object this work for also Format-Table, Format-List cmdlets. These don't work outside this cmdlets.
Calculated properties are a quick way to manipulate command output to return just about anything you like. These save your time and reduce code length.
Sidenote: The last code in your question dosent work because you need to join two path using Join-Path. Calculated properties are innocent here. Even you can join path like this: cat "Function:\$($_.Name)" as #MathiasR.Jessen pointed.
#{} is a hashtable. {} is a scriptblock inside the hashtable set equal to e. The hashtable is used in a custom way for select-object.
$scriptblock = { $_ }
$hashtable = #{ name = 'number'
expression = $scriptblock
}
1..3 | select-object -property $hashtable
number
------
1
2
3

Add a derived property to powershell command pipe

If e.g. Get-NetTCPConnection command returns OwningProcess ID is it possible to create a one-liner which adds another columns which expands the ID to ProcessName as returned by Get-Process -Id?
Yes, using calculated expressions. See example 10 on the Select-Object documentation
Get-NetTCPConnection | select OwningProcess,#{n="ProcessName";e={Get-Process -Id $_.OwningProcess | select -ExpandProperty ProcessName}}
Edit
Is there a way to tell Select-Object to keep all properties without explicitly listing them so that the calculated expression appears in addition to what is printed by default?
Yes but it's a a lot more convoluted than it should be. The crux of it is (as you may already know) "all properties" and "printed by default" are two different things. You can see this by comparing Get-NetTCPConnection to Get-NetTCPConnection | select *
So to get all properties + the calculated property it would be:
Get-NetTCPConnection | select *,#{n="ProcessName";e={Get-Process -Id $_.OwningProcess | select -Expand ProcessName}}
To get the default properties + the calculated property (*sigh*):
# this is from Get-NetTCPConnection | Get-Member
$typeName = 'Microsoft.Management.Infrastructure.CimInstance#ROOT/StandardCimv2/MSFT_NetTCPConnection'
# export format data for this type
Get-FormatData -TypeName $typeName | Export-FormatData -IncludeScriptBlock -Path $env:TEMP\formatdata.ps1xml
# open the ps1xml in editor of choice C:\Users\<user>\AppData\Local\Temp\formatdata.ps1xml
# Add under TableHeaders
<TableColumnHeader>
<Width>14</Width>
</TableColumnHeader>
# Add under TableColumnItems
<TableColumnItem>
<ScriptBlock>
Get-Process -Id $_.OwningProcess | select -ExpandProperty ProcessName
</ScriptBlock>
</TableColumnItem>
# save ps1xml
# update format data
Update-FormatData -PrependPath $env:TEMP\formatdata.ps1xml
The above is limited to the current session. You can add Update-FormatData to your profile so it's done every time you start a session. Or use the scorched Earth approach and modify the source format file (not recommended, I didn't try it) located at C:\Windows\system32\WindowsPowerShell\v1.0\Modules\NetTCPIP\Tcpip.Format.ps1xml.
How to find this location:
Get-Command Get-NetTCPConnection | select -Expand Module | select -Expand ExportedFormatFiles
Related: Using the PowerShell formatting system to your advantage, about_format.ps1xml, Loading and Exporting Formatting Data, Get-FormatData, Update-FormatData

Powershell, Using the results of a Invoke-SQLcmd as a variable in a file path [duplicate]

I have a script that creates several jobs and stores two simple values in the jobs.
Start-Job -ScriptBlock {param ([string]$compip) tnc $compip | select RemoteAddress,PingSucceeded -WarningAction SilentlyContinue} -ArgumentList $compip
This works fine. What I would like to know is how can I store the following code into a variable?
Get-Job | Receive-Job | sort RemoteAddress | FT
I have tried this, but it does not work as I thought it would:
$pcs = Get-Job | Receive-Job | sort RemoteAddress | FT
$pcs.RemoteAddress
Am I going at this the wrong way? I would like to store the data from the get-job command above to use the values later in the script. I assumed it would work because the output looks correct:
Command:
Get-Job | Receive-Job | sort RemoteAddress | FT
Output:
RemoteAddress PingSucceeded
------------- -------------
192.168.0.163 True
192.168.0.101 False
192.168.0.2 False
192.168.0.251 True
Problem with Format-cmdlets
The issue here is your use of FT which is an alias for Format-Table. These Format- cmdlets are designed for console/screen output only. There are many things you can do with them to tailor that output but in every case PowerShell needs to massage the data in order to be able to do so. This includes breaking down to the passed objects into groups of different objects...
Microsoft.PowerShell.Commands.Internal.Format.FormatEndData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.FormatStartData
Microsoft.PowerShell.Commands.Internal.Format.GroupEndData
Microsoft.PowerShell.Commands.Internal.Format.GroupStartData
The above data types were extract from running this code.
Get-ChildItem c:\temp | Format-Table | Get-Member
So you no longer have the System.IO.FileInfo and System.IO.DirectoryInfo objects that you would normally get from Get-ChildItem
Another large issue comes from Format-cmdlets nature to truncated data, like arrays with a large numbers of elements or long strings, to make as much fit on screen. In the case of arrays, this is due to the preference variable $FormatEnumerationLimit which is commonly defaulted to 4.
Ten Numbers
-----------
{1, 2, 3, 4...}
These, and other, limitations can all be mitigated with cmdlet switches like -AutoSize and -HideTableHeaders, out-string -width, etc. That does not matter however because...
Solution
Good news is the solution is very simple. Stop using them for anything other than console output. Using my earlier example:
Saving results in a variable?: $result = Get-ChildItem C:\temp
Exporting Data: Get-ChildItem C:\temp | Export-CSV $path -NoTypeInformation. Other Export-cmdlets could be preferred here like Export-CLIXml for complex objects when you want to store them for use elsewhere. If you are just looking for something pretty to include in your output then consider ConvertTo-HTML instead.
Extracting individual properties?: Just use Select-Object. $result | Select prop1, prop2. You can also expand your property selection to just get the strings or string array with -ExpandProperty: $result | Select -ExpandProperty prop1
Performing inline calculations with said properties?: Use calculated expression just as you would with the Format-Cmdlets. $result | Select prop1, #{Name="prop2";Expression={$_.prop2 * 3}
Potential Acceptable Use
Some prefer the output for use in emails and for recording statistics. While it is integral to keep data in its more easily used format for later use. However if you really need that data keep in mind that you are not working with the object your originally had anymore.
So if you needed your data in a table format but stored as a string then consider Out-String
$body = Get-ChildItem c:\temp | Format-Table | Out-String
but remember that Format-Table will play with object output in order to get it to display on screen (truncated array properties and long strings). Really.. if you wanted it nice and formatted then you should just use ConvertTo-HTML.
Point is you almost never need to keep the data from Format-Table. There is almost always a better way.

Why it is not called select-property in powershell?

An example
get-process | select-object vm, cpu,id | out-gridview
Here select-object actually is selecting PROPERTIES of the OBJECTS in the COLLECTION stored in memory.
Anyone knows why this cmdlet is not called select-property ?
Maybe I m asking a noob quesiton......
When you call Select-Object Blah, Blah1, Blah2, you are using the Property parameter via positional binding
Notice that the help describes a lot more than just the -Property parameter you are using:
Get-Help Select-Object -Full
<#
...
The Select-Object cmdlet selects specified properties of an object or set
of objects. It can also select unique objects, a specified number of
objects, or objects in a specified position in an array.
To select objects from a collection, use the First, Last, Unique, Skip, and
Index parameters. To select object properties, use the Property parameter.
When you select properties, Select-Object returns new objects that have
only the specified properties.
#>
Spend some time using the built in help system, there is a trove of information in there!
#Get the full help details
Get-Help Select-Object -Full
#If available, look online for help
Get-Help Select-Object -Online
#List conceptual topics
Get-Help about_*
#Read about regular expressions
Get-Help about_Regular_Expressions
Lastly, if you're talking semantics, the noun in a PowerShell command name refers to what your verb is acting upon: objects.
Cheers!

Referencing variables that are not strings

I want to reference properties selected from a cmdlet and then use them later on in my script as $mailboxarray.totalitemsize and $mailboxarray.totalitemsize
This is breaking later on in my script as I assume it doesn't like the type of object it is. How can I make anything I pull into the references a string? At the moment I am getting "No mapping exists from object type System.Management.Automation.PsObject to a known managed provider type". My code at the moment: the first command works fine but I can't use expandproperty when there are multiple entries like line two?
$recipienttype = Get-mailbox -identity $recordset.PrimarySmtpAddress | Select -expandproperty RecipientTypeDetails
$mailboxarray = Get-Mailbox -identity $recordset.PrimarySmtpAddress | Get-MailboxStatistics | Select-object totalitemsize, lastlogontime