Skip to content

Commit

Permalink
Migrating Add-CTypeData and Test-CTypeDataMember from Carbon.
Browse files Browse the repository at this point in the history
  • Loading branch information
splatteredbits committed Jul 26, 2022
1 parent 9c6eef2 commit e220496
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 3 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@

# 1.1.0

Added `Test-CTypeDataMember` and `Add-CTypeData` functions for testing if a type has any defined custom type data and
adding custom type data, respectively. Defining type data with .ps1xml files can result in errors importing the same
module multiple times: PowerShell complains that the type data is already defined. Using `Add-CTypeData` prevents these
this error as it only adds members that don't already exist.


# 1.0.0

## Upgrade Instructions
Expand All @@ -23,7 +31,7 @@ a string, and pass that string to the `Command` parameter. This will base64 enco
PowerShell's -EncodedCommand property.
* The `Invoke-CPowerShell` function no longer has `FilePath`, `OutputFormat`, `ExecutionPolicy`, `NonInteractive`,
or `Runtime` parameters. Instead, pass these as arguments to the `ArgumentList` parameter, e.g.
`-ArgumentList @('-NonInteractive', '-ExecutionPolicy', 'Bypasss'). You are now responsible for passing all PowerShell
`-ArgumentList @('-NonInteractive', '-ExecutionPolicy', 'Bypasss')`. You are now responsible for passing all PowerShell
arguments via the `ArgumentList` parameter.
* The `Invoke-CPowerShell` function no longer supports running PowerShell 2 under .NET 4.
* Remove the `-Encode` switch. `Invoke-CPowerShell` now always base64 encodes the value of the `Command` parameter.
Expand Down
6 changes: 4 additions & 2 deletions Carbon.Core/Carbon.Core.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
RootModule = 'Carbon.Core.psm1'

# Version number of this module.
ModuleVersion = '1.0.0'
ModuleVersion = '1.1.0'

# ID used to uniquely identify this module
GUID = '20DA9F42-23C4-4917-8597-DCFD7EE4AD00'
Expand Down Expand Up @@ -76,12 +76,14 @@

# Functions to export from this module. Only list public function here.
FunctionsToExport = @(
'Add-CTypeData',
'ConvertTo-CBase64',
'Get-CPowerShellPath',
'Invoke-CPowerShell',
'Start-CPowerShellProcess',
'Test-COperatingSystem',
'Test-CPowerShell'
'Test-CPowerShell',
'Test-CTypeDataMember'
)

# Cmdlets to export from this module. By default, you get a script module, so there are no cmdlets.
Expand Down
115 changes: 115 additions & 0 deletions Carbon.Core/Functions/Add-CTypeData.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
function Add-CTypeData
{
<#
.SYNOPSIS
Adds type data to a type only if the type data doesn't already exist.
.DESCRIPTION
The `Add-CTypeData` function uses PowerShell's `Update-TypeData` cmdlet to add type data to a type, but only if the
given type data doesn't already exist. Pass the type to the `Type` parameter or the type name to the `TypeName`
parameter, the new type data member type to the `MemberType` parameter (e.g. `AliasProperty`, `NoteProperty`,
`ScriptProperty`, or `ScriptMethod`), the member name to the `MemberName` parameter, and the member's
value/implementation to the `Value` parameter.
Note that the `Type` parameter should be the bare name of the type, e.g. `Diagnostics.Process`, *without* square
brackets.
If the type already has an equivalent member with the name given by the `MemberName` parameter, nothing happens, and
the function returns.
.EXAMPLE
Add-CTypeData -Type Diagnostics.Process -MemberType ScriptProperty -MemberName 'ParentID' -Value $scriptBlock
Demonstrates how to create a script property on a type. In this example, the `System.Diagnostics.Process` type will
be given a `ParentID` property that runs the code in the script block in the `$scriptBlock` variable.
.EXAMPLE
Add-CTypeData -Type Diagnostics.Process -MemberType ScriptMethod -MemberName 'GetParentID()' -Value $scriptBlock
Demonstrates how to create a script method on a type. In this example, the `System.Diagnostics.Process` type will
be given a `GetParentID()` method that runs the code in the script block in the `$scriptBlock` variable.
.EXAMPLE
Add-CTypeData -Type Diagnostics.Process -MemberType AliasProperty -MemberName 'ProcessId' -Value 'Id'
Demonstrates how to create an alias script property on a type. In this example, the `System.Diagnostics.Process`
type will be given a `ProcessId` property that is an alias to the 'Id' property.
.EXAMPLE
Add-CTypeData -Type Diagnostics.Process -MemberType NoteProperty -MemberName 'ParentID' -Value $parentPid
Demonstrates how to create a ntoe property on a type. In this example, the `System.Diagnostics.Process` type will
be given a `ParentID` property that returns the value in the `$parentPid` variable.
#>
[CmdletBinding()]
param(
# The type on which to add the type data. This should be the bare type name, e.g. Diagnostics.Process, *not*
# the type surrounded by square brackets, e.g. `[Diagnostics.Process]`.
[Parameter(Mandatory, ParameterSetName='ByType')]
[Type] $Type,

# The name of the type on which to add the type data.
[Parameter(Mandatory, ParameterSetName='ByTypeName')]
[String] $TypeName,

# The member type of the new type data. Only `AliasProperty`, `NoteProperty`, `ScriptProperty`, `ScriptMethod`
# are supported.
[Parameter(Mandatory)]
[ValidateSet('AliasProperty', 'NoteProperty', 'ScriptProperty', 'ScriptMethod')]
[Management.Automation.PSMemberTypes] $MemberType,

# The type data's member name.
[Parameter(Mandatory)]
[String] $MemberName,

# The value for the member. If `MemberName` is:
#
# * `AliasProperty`, this should be the name of the target property.
# * `NoteProperty`, the literal value of the property.
# * `ScriptProperty`, a script block that return's the property value.
# * `ScriptMethod`, a script block that implements the method logic.
[Parameter(Mandatory)]
[Object] $Value
)

Set-StrictMode -Version 'Latest'
Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState

$memberTypeMsg = '{0,-14}' -f $MemberType

if( -not $TypeName )
{
$TypeName = $Type.FullName
}

if( $Type )
{
if( $MemberType -like '*Property' )
{
if( ($Type.GetProperties() | Where-Object Name -EQ $MemberName) )
{
Write-Debug ("Type $($memberTypeMsg) [$($TypeName)] $($MemberName)")
return
}
}
elseif( $MemberType -like '*Method')
{
if( ($Type.GetMethods() | Where-Object Name -EQ $MemberName) )
{
Write-Debug ("Type $($memberTypeMsg) [$($TypeName)] $($MemberName)")
return
}
}
}

$typeData = Get-TypeData -TypeName $TypeName
if( $typeData -and $typeData.Members.ContainsKey($MemberName) )
{
Write-Debug ("TypeData $($memberTypeMsg) [$($TypeName)] $($MemberName)")
return
}

Write-Debug ("TypeData + $($memberTypeMsg) [$($TypeName)] $($MemberName)")
Update-TypeData -TypeName $TypeName -MemberType $MemberType -MemberName $MemberName -Value $Value
}

44 changes: 44 additions & 0 deletions Carbon.Core/Functions/Test-CTypeDataMember.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

function Test-CTypeDataMember
{
<#
.SYNOPSIS
Tests if a type has an extended type member defined.
.DESCRIPTION
`Test-CTypeDataMember` tests if a type has an extended type member defined. If the type isn't found, you'll get an
error.
Returns `$true` if the type is found and the member is defined. Otherwise, returns `$false`.
.EXAMPLE
Test-CTypeDataMember -TypeName 'Microsoft.Web.Administration.Site' -MemberName 'PhysicalPath'
Tests if the `Microsoft.Web.Administration.Site` type has a `PhysicalPath` extended type member defined.
#>
[CmdletBinding()]
[OutputType([bool])]
param(
# The type name to check.
[Parameter(Mandatory)]
[String] $TypeName,

# The name of the member to check.
[Parameter(Mandatory)]
[String] $MemberName
)

Set-StrictMode -Version 'Latest'
Use-CallerPreference -Cmdlet $PSCmdlet -Session $ExecutionContext.SessionState

$typeData = Get-TypeData -TypeName $TypeName
if( -not $typeData )
{
# The type isn't defined or there is no extended type data on it.
return $false
}

return $typeData.Members.ContainsKey( $MemberName )
}


0 comments on commit e220496

Please sign in to comment.