diff --git a/Changelog.md b/Changelog.md index 72674f0..714d4bb 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,16 +1,15 @@ # Change Log for PSTypeExtensionTools -## TODO - -+ `Export-PSTypeExtension` to allow appending to a file and to be able to store different types in the same file.([Issue #16](https://github.com/jdhitsolutions/PSTypeExtensionTools/issues/16)) - ## v1.6.0 + Re-organized module structure. -+ Added `New-PSPropertySet` ([Issue #15](https://github.com/jdhitsolutions/PSTypeExtensionTools/issues/15)) ++ Added command `New-PSPropertySet`to create a ps1xml file that defines a custom property set. ([Issue #15](https://github.com/jdhitsolutions/PSTypeExtensionTools/issues/15)) ++ Modified `Get-PSTypeExtension` to hide `CodeProperty` values by defaults. ([Issue #17](https://github.com/jdhitsolutions/PSTypeExtensionTools/issues/1)) ++ Modified `Get-PSTypeExtension` to display results sorted by member type and name. ## v1.5.1 + + Fixed error in exporting aliases. + Updated license file. + Very minor help corrections. diff --git a/README.md b/README.md index 982d3ee..d964ef8 100644 --- a/README.md +++ b/README.md @@ -84,15 +84,11 @@ In your PowerShell profile scrip,t you can then re-import the type extension def Import-PSTypeExtension -Path C:\work\int32-types.json ``` -## Create ps1xml Files - -The export command makes it easy to construct a ps1xml file. All you need to do is provide the type name and the extensions you want to export, and it will create a properly formatted ps1xml file that you can import into a session with `Update-TypeData` or distribute with a module. No more clunky XML copying, pasting, and hoping for the best. - ## PSTypeExtensionTools Cmdlets ### [Add-PSTypeExtension](docs/Add-PSTypeExtension.md) -Add a new type extension such as an Alias or ScriptProperty. +Add a new type extension such as an `Alias` or `ScriptProperty`. ### [Export-PSTypeExtension](docs/Export-PSTypeExtension.md) @@ -112,7 +108,52 @@ Import type extension definitions from a JSON file or XML. ### [New-PSPropertySet](docs/New-PSPropertySet.md) -TBD +In addition to custom properties, PowerShell also has the idea of a _propertyset_. This allows you to reference a group of properties with a single name. + +Let's say you have loaded the sample fileinfo type extensions from this module. + +```powershell +PS C:\> Import-PSTypeExtension -Path $PSTypeSamples\fileinfo-extensions.json +```powershell + +You could write a command like this: + +```powershell +dir c:\work -file | Select-Object Name,Size,LastWriteTime,Age +``` + +Or you could create a custom property set. These have to be defined in `ps1xml` files. The `New-PSPropertySet` simplifies this process. + +```powershell + New-PSPropertySet -Typename System.IO.FileInfo -Name FileAge -Properties Name,Size,LastWriteTime,Age -FilePath d:\temp\Fileinfo.types.ps1xml +``` + +I've included the file in the Samples folder. + +```powershell +PS C:\> Update-TypeData $PSTypeSamples\fileinfo.types.ps1xml +PS C:\> dir c:\work -file | Select-Object fileage + +Name Size LastWriteTime Age +---- ---- - ----------- --- +a.dat 42 2/12/2021 5:36:55 PM 23.17:27:21 +a.txt 14346 12/31/2020 9:10:15 AM 67.01:54:00 +a.xml 171394 12/31/2020 12:15:44 PM 66.22:48:32 +aa.ps1 28866 12/31/2020 9:13:16 AM 67.01:51:00 +aa.txt 28866 12/31/2020 9:11:18 AM 67.01:52:58 +about.json 16455 2/27/2021 10:11:03 AM 09.00:53:12 +about_ADReportingTools 1688 3/4/2021 7:37:01 PM 03.15:27:14 +b.csv 1273 11/13/2020 12:11:35 PM 114.22:52:40 +... +``` + +If your property set is using custom properties, you need to load them into your PowerShell session before you can use the property set. + +## Create ps1xml Files + +The export command makes it easy to construct a ps1xml file. All you need to do is provide the type name and the extensions you want to export, and it will create a properly formatted ps1xml file that you can import into a session with `Update-TypeData` or distribute with a module. No more clunky XML copying, pasting, and hoping for the best. + +Well, there is one reason you still might need to do some copying and pasting. Technically, you can define all custom properties, including property sets, in a single .ps1xml file. However, I don't have a simple command to export everything for a single type to a single file. For now, you can create a `.types.ps1xml` file for your custom extensions. Then manually merge the `Members` section from your property set .ps1xml file. This is only necessary if you have custom extensions **and** one or more property sets defined for a given type. ## I Want to Try @@ -167,4 +208,4 @@ There is also an about topic you can read: help about_PSTypeExtensionTools ``` -Last Updated 2019-09-21 06:15:09Z UTC +Last Updated 2021-03-08 21:19:40Z diff --git a/docs/Get-PSTypeExtension.md b/docs/Get-PSTypeExtension.md index ef3489f..7fc5dd9 100644 --- a/docs/Get-PSTypeExtension.md +++ b/docs/Get-PSTypeExtension.md @@ -14,13 +14,15 @@ Get selected type extensions. ## SYNTAX ```yaml -Get-PSTypeExtension [-TypeName] [-Members ] [] +Get-PSTypeExtension [-TypeName] [-Members ] [-CodeProperty] [] ``` ## DESCRIPTION Use this command to list defined type extensions. You can either select individual ones or all of them. Do not specify any members to retrieve all of them. This command is very similar to Get-TypeData, except that it makes it easier to see the extension value. +By default, CodeProperty members are not displayed because they can't be exported. + ## EXAMPLES ### EXAMPLE 1 @@ -58,7 +60,7 @@ Get the Size type extension for System.String. ### EXAMPLE 3 ```powershell -PS C:\> get-process | get-pstype | Get-PSTypeExtension +PS C:\> Get-Process | Get-PSType | Get-PSTypeExtension TypeName: System.Diagnostics.Process @@ -84,6 +86,32 @@ __NounName Noteproperty Process Discover type extensions for a given type of object. +### Example 4 + +```powershell +PS C:\> Get-PSTypeExtension system.io.fileinfo -CodeProperty | +Select-Object membername,membertype + +MemberName MemberType +---------- ---------- +Size AliasProperty +Modified AliasProperty +Created AliasProperty +Mode CodeProperty +ModeWithoutHardLink CodeProperty +Target CodeProperty +LinkType CodeProperty +NameString CodeProperty +LengthString CodeProperty +LastWriteTimeString CodeProperty +VersionInfo ScriptProperty +BaseName ScriptProperty +SizeKB ScriptProperty +SizeMB ScriptProperty +``` + +Display all extensions, including CodeProperty, and display the member name and type. + ## PARAMETERS ### -Members @@ -104,7 +132,7 @@ Accept wildcard characters: False ### -TypeName -Enter the name of type like System.IO.FileInfo. +Enter the name of a type like System.IO.FileInfo. ```yaml Type: String @@ -118,9 +146,25 @@ Accept pipeline input: True (ByPropertyName, ByValue) Accept wildcard characters: False ``` +### -CodeProperty + +Show CodeProperty custom properties + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### CommonParameters -This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). ## INPUTS @@ -128,7 +172,7 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## OUTPUTS -### System.Object +### PSTypeExtension ## NOTES @@ -137,4 +181,8 @@ http://jdhitsolutions.com/blog/essential-powershell-resources/ ## RELATED LINKS +[Get-PSType](Get-PSType.md) + +[Export-PSTypeExtension](Export-PSTypeExtension.md) + [Get-TypeData]() diff --git a/docs/New-PSPropertySet.md b/docs/New-PSPropertySet.md index 66aa0e7..d737cd2 100644 --- a/docs/New-PSPropertySet.md +++ b/docs/New-PSPropertySet.md @@ -1,7 +1,7 @@ --- external help file: PSTypeExtensionTools-help.xml Module Name: PSTypeExtensionTools -online version: +online version: https://github.com/jdhitsolutions/PSTypeExtensionTools/blob/master/docs/New-PSPropertySet.md schema: 2.0.0 --- @@ -31,15 +31,15 @@ PowerShell has a concept of property sets. A property set allows you to referenc Use Update-TypeData to append the file. If you import your file more than once in the same session, you might see a warning about existing property names. Existing entries won't be overwritten. -Property set updates are not persistant. You will need to import your ps1xml, ideally in your PowerShell profile script. +Property set updates are not persistent. You will need to import your ps1xml, ideally in your PowerShell profile script. ## EXAMPLES ### Example 1 ```powershell -PS C:\> New-PSPropertySet -typename System.IO.FileInfo -name info -properties Fullname,IsReadOnly,CreationTime,LastWriteTime -filepath c:\work\myfileinfo.type.ps1xml -PS C:\> Update-TypeData C:\work\myfileinfo.type.ps1xml +PS C:\> New-PSPropertySet -typename System.IO.FileInfo -name info -properties Fullname,IsReadOnly,CreationTime,LastWriteTime -filepath c:\work\myfileinfo.types.ps1xml +PS C:\> Update-TypeData C:\work\myfileinfo.types.ps1xml PS C:\> dir c:\work -file | select info FullName IsReadOnly CreationTime LastWriteTime @@ -92,7 +92,7 @@ Accept wildcard characters: False ### -FilePath -Enter the name of the .ps1xml file to create. +Enter the name of the .ps1xml file to create. It must have a .ps1xml file extension and ideally should take the format .types.ps1xml. ```yaml Type: String @@ -140,7 +140,7 @@ Accept wildcard characters: False ### -Properties -Enter the existing property names or aliases to belong to this property set. +Enter the existing property names or aliases to belong to this property set. If using aliases, they must be defined in your PowerShell session before you can use the custom property set. ```yaml Type: String[] @@ -207,3 +207,5 @@ http://jdhitsolutions.com/blog/essential-powershell-resources/ ## RELATED LINKS [Update-TypeData]() + +[Add-PSTypeExtension](Add-PSTypeExtension.md) diff --git a/docs/about_PSTypeExtensionTools.md b/docs/about_PSTypeExtensionTools.md index 495e073..abd9949 100644 --- a/docs/about_PSTypeExtensionTools.md +++ b/docs/about_PSTypeExtensionTools.md @@ -29,7 +29,7 @@ PS C:\> $x.SquareRoot 11.0905365064094 ``` -Once you know the type name you can add other type extensions. +Once you know the type name, you can add other type extensions. ```powershell Add-PSTypeExtension -TypeName system.int32 -MemberType ScriptProperty -MemberName Squared -value { $this*$this} @@ -90,7 +90,7 @@ You can also import a directory of type extensions with a single command. dir c:\scripts\mytypes | Import-PSTypeExtension ``` -A number of sample files with type extensions can be found in this modules Samples folder or in the GitHub repository at https://github.com/jdhitsolutions/PSTypeExtensionTools/tree/master/samples. When you have imported the module you can access the samples folder using the $PSTypeSamples variable. +A number of sample files with type extensions can be found in this module's Samples folder or GitHub repository at https://github.com/jdhitsolutions/PSTypeExtensionTools/tree/master/samples. When you have imported the module, you can access the samples folder using the `$PSTypeSamples` variable. ```powershell Import-PSTypeExtension $PSTypeSamples\measure-extensions.json diff --git a/en-us/PSTypeExtensionTools-help.xml b/en-us/PSTypeExtensionTools-help.xml index d11e65f..2b7b25c 100644 --- a/en-us/PSTypeExtensionTools-help.xml +++ b/en-us/PSTypeExtensionTools-help.xml @@ -10,16 +10,16 @@ - Use this command to easily define a new type extension for a given object type. Existing members with the same name will be overwritten so you can also use this as a "Set" command. + Use this command to easily define a new type extension for a given object type. Existing members with the same name will be overwritten, so you can also use this as a "Set" command. Add-PSTypeExtension TypeName - + Enter the name of a type like System.IO.FileInfo. - + String String @@ -29,9 +29,9 @@ MemberName - + The name of your type extension. - + String String @@ -41,9 +41,9 @@ MemberType - + The member type. You cannot use this command to define CodeMethods or CodeProperties. - + AliasProperty NoteProperty @@ -59,9 +59,9 @@ Value - + The value for your type extension. Remember to enclose scriptblocks in {} and use $this. - + Object Object @@ -71,9 +71,9 @@ Confirm - + Prompts you for confirmation before running the cmdlet. - + SwitchParameter @@ -82,9 +82,9 @@ WhatIf - + Shows what would happen if the cmdlet runs. The cmdlet is not run. - + SwitchParameter @@ -93,9 +93,9 @@ IncludeDeserialized - + Create the extension in the deserialized version of the specified type along with the specified type. - + SwitchParameter @@ -107,9 +107,9 @@ MemberName - + The name of your type extension. - + String String @@ -119,9 +119,9 @@ MemberType - + The member type. You cannot use this command to define CodeMethods or CodeProperties. - + String String @@ -131,9 +131,9 @@ TypeName - + Enter the name of a type like System.IO.FileInfo. - + String String @@ -143,9 +143,9 @@ Value - + The value for your type extension. Remember to enclose scriptblocks in {} and use $this. - + Object Object @@ -155,9 +155,9 @@ Confirm - + Prompts you for confirmation before running the cmdlet. - + SwitchParameter SwitchParameter @@ -167,9 +167,9 @@ WhatIf - + Shows what would happen if the cmdlet runs. The cmdlet is not run. - + SwitchParameter SwitchParameter @@ -179,9 +179,9 @@ IncludeDeserialized - + Create the extension in the deserialized version of the specified type along with the specified type. - + SwitchParameter SwitchParameter @@ -230,14 +230,14 @@ PS C:\> $s = "10.4.7.10" PS C:\> $s.IsIPAddress() True - Define an script property called IsIPAddress which will return True if the string matches the pattern for an IP address. + Define a script property called IsIPAddress which will return True if the string matches the pattern for an IP address. -------------------------- EXAMPLE 3 -------------------------- PS C:\ Add-PSTypeExtension -TypeName system.io.fileinfo -MemberType AliasProperty -MemberName Size -value Length -IncludeDeserialized - Create an alias called Size using the Length property on file objects. This expression will also create if for the deserialized version of the type so that you can use it with remoting results. + Create an alias called Size using the Length property on file objects. This expression will also create it for the deserialized version of the type so that you can use it with remoting results. @@ -262,16 +262,16 @@ True - This command can be used in 2 ways. First, you can export custom type information to a json or xml file to make it easier to recreate them in another PowerShell session. Or you can export the type extensions to a properly formatted ps1xml file which you can use with Update-TypeData. The command will create the appropriate file based on the extension in the specified path. + This command can be used in 2 ways. First, you can export custom type information to a JSON or XML file to make it easier to recreate them in another PowerShell session. Or you can export the type extensions to a properly formatted ps1xml file which you can use with Update-TypeData. The command will create the appropriate file based on the extension in the specified path. Export-PSTypeExtension TypeName - + The type name to export like System.IO.FileInfo. - + String String @@ -281,9 +281,9 @@ True MemberName - + The type extension name. - + String[] String[] @@ -293,9 +293,9 @@ True Path - + The name of the exported file. The extension must be .xml, .ps1xml or .json. - + String String @@ -305,9 +305,9 @@ True Confirm - + Prompts you for confirmation before running the cmdlet. - + SwitchParameter @@ -316,9 +316,9 @@ True WhatIf - + Shows what would happen if the cmdlet runs. The cmdlet is not run. - + SwitchParameter @@ -330,9 +330,9 @@ True Export-PSTypeExtension Path - + The name of the exported file. The extension must be .xml, .ps1xml or .json. - + String String @@ -342,9 +342,9 @@ True Confirm - + Prompts you for confirmation before running the cmdlet. - + SwitchParameter @@ -353,9 +353,9 @@ True WhatIf - + Shows what would happen if the cmdlet runs. The cmdlet is not run. - + SwitchParameter @@ -364,9 +364,9 @@ True InputObject - + This is typically the output of Get-PSSTypeExtension. - + Object Object @@ -379,9 +379,9 @@ True MemberName - + The type extension name. - + String[] String[] @@ -391,9 +391,9 @@ True Path - + The name of the exported file. The extension must be .xml, .ps1xml or .json. - + String String @@ -403,9 +403,9 @@ True TypeName - + The type name to export like System.IO.FileInfo. - + String String @@ -415,9 +415,9 @@ True Confirm - + Prompts you for confirmation before running the cmdlet. - + SwitchParameter SwitchParameter @@ -427,9 +427,9 @@ True WhatIf - + Shows what would happen if the cmdlet runs. The cmdlet is not run. - + SwitchParameter SwitchParameter @@ -439,9 +439,9 @@ True InputObject - + This is typically the output of Get-PSSTypeExtension. - + Object Object @@ -480,14 +480,14 @@ True -------------------------- EXAMPLE 1 -------------------------- PS C:\> Export-PSTypeExtension -TypeName system.string -Path c:\work\mystringtypes.json -MemberName Size,IsIPAddress - Export selected type extensions for System.String to a json file. + Export selected type extensions for System.String to a JSON file. -------------------------- EXAMPLE 2 -------------------------- PS C:\> Get-PSTypeExtension system.string | Export-PSTypeExtension -path c:\work\stringtypes.xml - Get all type extensions for System.String and export to an xml file. + Get all type extensions for System.String and export to an XML file. @@ -530,9 +530,9 @@ True Get-PSType Inputobject - + Any object from PowerShell. - + Object Object @@ -545,9 +545,9 @@ True Inputobject - + Any object from PowerShell. - + Object Object @@ -587,7 +587,7 @@ True PS C:\>123 | Get-PSType System.Int32 - Pipe an object and get it's type. + Pipe an object and get its type. @@ -611,16 +611,16 @@ PS C:\> get-vm | sort VMAge -descending | select Name,Creationtime,VMAge Name CreationTime VMAge ---- ------------ ----- -UbuntuDesk 8/7/2017 1:53:47 PM 94.20:26:57.4237225 -CentOS 8/7/2017 3:43:50 PM 94.18:36:54.3394091 -DOM1 9/28/2017 9:31:34 AM 43.00:49:10.4396803 -SRV1 9/28/2017 9:31:50 AM 43.00:48:54.3284313 -SRV2 9/28/2017 9:32:01 AM 43.00:48:43.2135084 -SRV3 9/28/2017 9:32:11 AM 43.00:48:33.4681374 -WIN10 9/28/2017 9:32:21 AM 43.00:48:23.1610914 -Win10Ent 10/16/2017 9:30:46 AM 25.00:49:58.1206825 +UbuntuDesk 8/7/2020 1:53:47 PM 94.20:26:57.4237225 +CentOS 8/7/2020 3:43:50 PM 94.18:36:54.3394091 +DOM1 9/28/2020 9:31:34 AM 43.00:49:10.4396803 +SRV1 9/28/2020 9:31:50 AM 43.00:48:54.3284313 +SRV2 9/28/2020 9:32:01 AM 43.00:48:43.2135084 +SRV3 9/28/2020 9:32:11 AM 43.00:48:33.4681374 +WIN10 9/28/2020 9:32:21 AM 43.00:48:23.1610914 +Win10Ent 10/16/2020 9:30:46 AM 25.00:49:58.1206825 - Get the type for a Hyper-V Virtual Machine and add a new script property which can then be used in a PowerShell expression. + Get the type for a Hyper-V Virtual Machine and add a new ScriptProperty, which can then be used in a PowerShell expression. @@ -653,16 +653,17 @@ Win10Ent 10/16/2017 9:30:46 AM 25.00:49:58.1206825 - Use this command to list defined type extensions. You can either select individual ones or all of them. Do not specify any members to retrieve all of them. This command is very similar to Get-TypeData except that it makes it easier to see the extension value. + Use this command to list defined type extensions. You can either select individual ones or all of them. Do not specify any members to retrieve all of them. This command is very similar to Get-TypeData, except that it makes it easier to see the extension value. + By default, CodeProperty members are not displayed because they can't be exported. Get-PSTypeExtension TypeName - - Enter the name of type like System.IO.FileInfo. - + + Enter the name of a type like System.IO.FileInfo. + String String @@ -672,9 +673,9 @@ Win10Ent 10/16/2017 9:30:46 AM 25.00:49:58.1206825 Members - - Enter a comma separated list of member names. - + + Enter a comma-separated list of member names. + String[] String[] @@ -682,14 +683,25 @@ Win10Ent 10/16/2017 9:30:46 AM 25.00:49:58.1206825 None + + CodeProperty + + Show CodeProperty custom properties + + + SwitchParameter + + + False + Members - - Enter a comma separated list of member names. - + + Enter a comma-separated list of member names. + String[] String[] @@ -699,9 +711,9 @@ Win10Ent 10/16/2017 9:30:46 AM 25.00:49:58.1206825 TypeName - - Enter the name of type like System.IO.FileInfo. - + + Enter the name of a type like System.IO.FileInfo. + String String @@ -709,6 +721,18 @@ Win10Ent 10/16/2017 9:30:46 AM 25.00:49:58.1206825 None + + CodeProperty + + Show CodeProperty custom properties + + SwitchParameter + + SwitchParameter + + + False + @@ -723,7 +747,7 @@ Win10Ent 10/16/2017 9:30:46 AM 25.00:49:58.1206825 - System.Object + PSTypeExtension @@ -768,7 +792,7 @@ Size AliasProperty Length -------------------------- EXAMPLE 3 -------------------------- - PS C:\> get-process | get-pstype | Get-PSTypeExtension + PS C:\> Get-Process | Get-PSType | Get-PSTypeExtension TypeName: System.Diagnostics.Process @@ -794,12 +818,45 @@ __NounName Noteproperty Process Discover type extensions for a given type of object. + + -------------------------- Example 4 -------------------------- + PS C:\> Get-PSTypeExtension system.io.fileinfo -CodeProperty | +Select-Object membername,membertype + +MemberName MemberType +---------- ---------- +Size AliasProperty +Modified AliasProperty +Created AliasProperty +Mode CodeProperty +ModeWithoutHardLink CodeProperty +Target CodeProperty +LinkType CodeProperty +NameString CodeProperty +LengthString CodeProperty +LastWriteTimeString CodeProperty +VersionInfo ScriptProperty +BaseName ScriptProperty +SizeKB ScriptProperty +SizeMB ScriptProperty + + Display all extensions, including CodeProperty, and display the member name and type. + + Online Version: http://bit.ly/30FkW2t + + Get-PSType + + + + Export-PSTypeExtension + + Get-TypeData @@ -816,16 +873,16 @@ __NounName Noteproperty Process - Use this command to import extended type definitions from a json or xml file that was created with Export-PSTypeExtension. + Use this command to import extended type definitions from a JSON or XML file that was created with Export-PSTypeExtension. Import-PSTypeExtension Path - + The name of the imported file. The extension must be .xml or .json. - + String String @@ -835,9 +892,9 @@ __NounName Noteproperty Process Confirm - + Prompts you for confirmation before running the cmdlet. - + SwitchParameter @@ -846,9 +903,9 @@ __NounName Noteproperty Process WhatIf - + Shows what would happen if the cmdlet runs. The cmdlet is not run. - + SwitchParameter @@ -860,9 +917,9 @@ __NounName Noteproperty Process Path - + The name of the imported file. The extension must be .xml or .json. - + String String @@ -872,9 +929,9 @@ __NounName Noteproperty Process Confirm - + Prompts you for confirmation before running the cmdlet. - + SwitchParameter SwitchParameter @@ -884,9 +941,9 @@ __NounName Noteproperty Process WhatIf - + Shows what would happen if the cmdlet runs. The cmdlet is not run. - + SwitchParameter SwitchParameter @@ -917,7 +974,7 @@ __NounName Noteproperty Process - Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ + Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ @@ -925,14 +982,14 @@ __NounName Noteproperty Process -------------------------- EXAMPLE 1 -------------------------- PS C:\> Import-PSTypeExtension -Path C:\work\stringtypes.json - Import definitions from a json file. + Import definitions from a JSON file. -------------------------- EXAMPLE 2 -------------------------- PS C:\> dir c:\scripts\mytypes | Import-PSTypeExtension - Import definitions from files in C:\Scripts\MyTypes. Presumably, these are xml or json files created with Export-PSTypeExtension. + Import definitions from files in C:\Scripts\MyTypes. Presumably, these are XML or JSON files created with Export-PSTypeExtension. @@ -955,4 +1012,348 @@ __NounName Noteproperty Process + + + New-PSPropertySet + New + PSPropertySet + + Create a new property set ps1xml file. + + + + PowerShell has a concept of property sets. A property set allows you to reference a collection of properties with a single name. Property set definitions have to be stored in a .ps1xml file. This command will create the file for you. You also have the option to append to an existing file. + Use Update-TypeData to append the file. If you import your file more than once in the same session, you might see a warning about existing property names. Existing entries won't be overwritten. + Property set updates are not persistent. You will need to import your ps1xml, ideally in your PowerShell profile script. + + + + New-PSPropertySet + + Typename + + Enter the object typename. This is the value you would see in Get-Member. + + String + + String + + + None + + + Append + + Append to an existing file. + + + SwitchParameter + + + False + + + Confirm + + Prompts you for confirmation before running the cmdlet. + + + SwitchParameter + + + False + + + FilePath + + Enter the name of the .ps1xml file to create. It must have a .ps1xml file extension and ideally should take the format <typename>.types.ps1xml. + + String + + String + + + None + + + Name + + Enter the new property set name. It should be alphanumeric. + + String + + String + + + None + + + Properties + + Enter the existing property names or aliases to belong to this property set. If using aliases, they must be defined in your PowerShell session before you can use the custom property set. + + String[] + + String[] + + + None + + + WhatIf + + Shows what would happen if the cmdlet runs. The cmdlet is not run. + + + SwitchParameter + + + False + + + + New-PSPropertySet + + Typename + + Enter the object typename. This is the value you would see in Get-Member. + + String + + String + + + None + + + Confirm + + Prompts you for confirmation before running the cmdlet. + + + SwitchParameter + + + False + + + FilePath + + Enter the name of the .ps1xml file to create. It must have a .ps1xml file extension and ideally should take the format <typename>.types.ps1xml. + + String + + String + + + None + + + Name + + Enter the new property set name. It should be alphanumeric. + + String + + String + + + None + + + NoClobber + + Don't overwrite an existing file. + + + SwitchParameter + + + False + + + Properties + + Enter the existing property names or aliases to belong to this property set. If using aliases, they must be defined in your PowerShell session before you can use the custom property set. + + String[] + + String[] + + + None + + + WhatIf + + Shows what would happen if the cmdlet runs. The cmdlet is not run. + + + SwitchParameter + + + False + + + + + + Append + + Append to an existing file. + + SwitchParameter + + SwitchParameter + + + False + + + Confirm + + Prompts you for confirmation before running the cmdlet. + + SwitchParameter + + SwitchParameter + + + False + + + FilePath + + Enter the name of the .ps1xml file to create. It must have a .ps1xml file extension and ideally should take the format <typename>.types.ps1xml. + + String + + String + + + None + + + Name + + Enter the new property set name. It should be alphanumeric. + + String + + String + + + None + + + NoClobber + + Don't overwrite an existing file. + + SwitchParameter + + SwitchParameter + + + False + + + Properties + + Enter the existing property names or aliases to belong to this property set. If using aliases, they must be defined in your PowerShell session before you can use the custom property set. + + String[] + + String[] + + + None + + + Typename + + Enter the object typename. This is the value you would see in Get-Member. + + String + + String + + + None + + + WhatIf + + Shows what would happen if the cmdlet runs. The cmdlet is not run. + + SwitchParameter + + SwitchParameter + + + False + + + + + + None + + + + + + + + + + System.IO.FileInfo + + + + + + + + + Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/ + + + + + -------------------------- Example 1 -------------------------- + PS C:\> New-PSPropertySet -typename System.IO.FileInfo -name info -properties Fullname,IsReadOnly,CreationTime,LastWriteTime -filepath c:\work\myfileinfo.types.ps1xml +PS C:\> Update-TypeData C:\work\myfileinfo.types.ps1xml +PS C:\> dir c:\work -file | select info + +FullName IsReadOnly CreationTime LastWriteTime +-------- ---------- ------------ ------------- +C:\work\a.csv False 12/1/2020 11:30:55 AM 12/1/2020 11:30:55 AM +C:\work\a.dat False 2/12/2021 5:36:55 PM 2/12/2021 5:36:55 PM +C:\work\a.md False 11/6/2020 9:50:19 AM 12/1/2020 12:40:03 PM +C:\work\a.txt False 12/31/2020 9:10:15 AM 12/31/2020 9:10:15 AM +C:\work\a.xml False 12/31/2020 12:15:44 PM 12/31/2020 12:15:44 PM +C:\work\aa.ps1 False 12/31/2020 9:13:16 AM 12/31/2020 9:13:16 AM +C:\work\aa.txt False 12/31/2020 9:11:18 AM 12/31/2020 9:11:18 AM +... + + The first command creates the property set definition file. The second command loads it into PowerShell. The last command uses the custom property set. + + + + + + Online Version: + https://github.com/jdhitsolutions/PSTypeExtensionTools/blob/master/docs/New-PSPropertySet.md + + + Update-TypeData + + + + Add-PSTypeExtension + + + + \ No newline at end of file diff --git a/en-us/about_PSTypeExtensionTools.help.txt b/en-us/about_PSTypeExtensionTools.help.txt new file mode 100644 index 0000000..db39d4c --- /dev/null +++ b/en-us/about_PSTypeExtensionTools.help.txt @@ -0,0 +1,123 @@ +TOPIC + about_PSTypeExtensionTools + +SHORT DESCRIPTION + This PowerShell module contains commands that make it easier to work with + type extensions. Many of these commands are wrappers for built-in tools like + Get-TypeData or Update-TypeData. The commands in this module simplify + the process of finding, creating, exporting, and importing type extensions. + +LONG DESCRIPTION + Let's say you want to update a number object, but you have no idea what the + type name is. Once you have read help for the commands in this module you + could run a PowerShell command like this: + + PS C:\> 123 | Get-PSType | + Add-PSTypeExtension -MemberType ScriptProperty -MemberName SquareRoot + -Value { [math]::Sqrt($this)} + + Use $this to reference the object instead of $_. Now you can get the new + property. + + PS C:\> $x = 123 + PS C:\> $x.SquareRoot + 11.0905365064094 + + Once you know the type name, you can add other type extensions. + + Add-PSTypeExtension -TypeName system.int32 -MemberType ScriptProperty -MemberName Squared -value { $this*$this} + Add-PSTypeExtension -TypeName system.int32 -MemberType ScriptProperty -MemberName Cubed -value { [math]::Pow($this,3)} + Add-PSTypeExtension -TypeName system.int32 -MemberType ScriptProperty -MemberName Value -value { $this} + Add-PSTypeExtension -TypeName system.int32 -MemberType ScriptMethod -MemberName GetPercent -value {Param([int32]$Total,[int32]$Round=2) [math]::Round(($this/$total)*100,$round)} + + Here's how it might look: + + PS C:\> $x = 38 + PS C:\> $x | select * + + SquareRoot Squared Cubed Value + ---------- ------- ----- ----- + 6.16441400296898 1444 54872 38 + + PS C:\> $x.GetPercent(50) + 76 + PS C:\> $x.GetPercent(100) + 38 + PS C:\> $x.GetPercent(110,4) + 34.5455 + + To see what has been defined, you can use Get-PSTypeExtension. You can + choose to see all extensions or selected ones by member name. + + PS C:\> Get-PSTypeExtension system.int32 + + TypeName: System.Int32 + + Name Type Value + ---- ---- ----- + SquareRoot ScriptProperty [math]::Sqrt($this) + Squared ScriptProperty $this*$this + Cubed ScriptProperty [math]::Pow($this,3) + Value ScriptProperty $this + GetPercent ScriptMethod Param([int32]$Total,[int32]$Round=2) [math]::Round(($this/$total)*100,$round) + + If you always want these extensions, you would have to put the commands into + your PowerShell profile script. Or you can export the extensions to a JSON + or XML file. You can either export all members or selected ones which is + helpful if you are extending a type that already has type extensions from + PowerShell. + + PS C:\> Get-PSTypeExtension system.int32 -all | Export-PSTypeExtension -TypeName system.int32 -Path c:\work\int32-types.json + + In your PowerShell profile script, you can then re-import the type extension + definitions. + + Import-PSTypeExtension -Path C:\work\int32-types.json + + You can also import a directory of type extensions with a single command. + + dir c:\scripts\mytypes | Import-PSTypeExtension + + A number of sample files with type extensions can be found in this module's + Samples folder or GitHub repository at + https://github.com/jdhitsolutions/PSTypeExtensionTools/tree/master/samples. + When you have imported the module, you can access the samples folder using + the $PSTypeSamples variable. + + Import-PSTypeExtension $PSTypeSamples\measure-extensions.json + + CREATING PS1XML FILES + The Export-PSTypeExtension command will also export extensions to a + properly formatted .ps1xml file. This can be useful when building type + extension files for a module where you want to use the traditional ps1xml + form. You can also import these types of files with Update-TypeData with the + -AppendPath or -PrependPath parameters. + +NOTE + PowerShell type extensions only last for the duration of your PowerShell + session. If you make a mistake that is causing problems, restart PowerShell + or use the Remove-TypeData cmdlet. + +TROUBLESHOOTING NOTE + Don't try to append or manually update an export file. If you have changes, + re-run the export command and generate the file anew. + Remember to use $this to reference the object and NOT $_. + Remember to enclose scriptblocks in {}. + +SEE ALSO + + Add-PSTypeExtension + + Export-PSTypeExtension + + Get-PSType + + Get-PSTypeExtension + + Import-PSTypeExtension + + Update-TypeData + + New-PSPropertySet + + This project was first described at + http://jdhitsolutions.com/blog/powershell/5777/a-powershell-module-for-your-type-extensions + +KEYWORDS +- typedata +- typeextension +- propertyset + diff --git a/functions/public.ps1 b/functions/public.ps1 index 25785dd..52907f0 100644 --- a/functions/public.ps1 +++ b/functions/public.ps1 @@ -1,6 +1,7 @@ Function Get-PSTypeExtension { [cmdletbinding()] + [outputtype("PSTypeExtension")] Param( [Parameter( Position = 0, @@ -28,7 +29,9 @@ Function Get-PSTypeExtension { HelpMessage = "Enter a comma separated list of member names", ParameterSetName = "members" )] - [string[]]$Members + [string[]]$Members, + [Parameter(HelpMessage = "Show CodeProperty custom properties")] + [switch]$CodeProperty ) Begin { @@ -42,8 +45,9 @@ Function Get-PSTypeExtension { } #process End { $typedata = $typedata | Select-Object -Unique - if ($typedata) { + if ($typedata) { + $out = [System.Collections.Generic.List[object]]::new() if (-Not $Members) { Write-Verbose "Getting all member names" $Members = $typedata.members.keys @@ -59,6 +63,7 @@ Function Get-PSTypeExtension { Switch ($datatype) { "AliasPropertyData" { $def = [pscustomobject]@{ + PSTypename = 'PSTypeExtension' MemberType = "AliasProperty" MemberName = $member.name Value = $member.ReferencedMemberName @@ -72,6 +77,7 @@ Function Get-PSTypeExtension { $code = $member.SetScriptBlock.ToString() } $def = [pscustomobject]@{ + PSTypename = 'PSTypeExtension' MemberType = "ScriptProperty" MemberName = $member.name Value = $code @@ -79,6 +85,7 @@ Function Get-PSTypeExtension { } #scriptproperty "ScriptMethodData" { $def = [pscustomobject]@{ + PSTypename = 'PSTypeExtension' MemberType = "ScriptMethod" MemberName = $member.name Value = $member.script.ToString().trim() @@ -86,39 +93,45 @@ Function Get-PSTypeExtension { } #scriptmethod "NotePropertyData" { $def = [pscustomobject]@{ + PSTypename = 'PSTypeExtension' MemberType = "Noteproperty" MemberName = $member.name Value = $member.Value } } #noteproperty "CodePropertyData" { - if ($member.GetCodeReference) { - $code = $member.GetCodeReference.ToString() + #only show these if requested with -CodeProperty + if ($CodeProperty) { + if ($member.GetCodeReference) { + $code = $member.GetCodeReference.ToString() + } + else { + $code = $member.SetCodeReference.ToString() + } + $def = [pscustomobject]@{ + PSTypename = 'PSTypeExtension' + MemberType = "CodeProperty" + MemberName = $member.name + Value = $code + } } else { - $code = $member.SetCodeReference.ToString() - } - $def = [pscustomobject]@{ - MemberType = "CodeProperty" - MemberName = $member.name - Value = $code + $def = $False } } #codeproperty Default { Write-Warning "Cannot process $datatype type for $($typedata.typename)." $def = [pscustomobject]@{ + PSTypename = 'PSTypeExtension' MemberType = $datatype MemberName = $member.name Value = $member.Value } } } - - $def | Add-Member -MemberType NoteProperty -Name TypeName -Value $typedata.typename - #insert a typename - $def.psobject.typenames.insert(0, 'PSTypeExtension') - #write the definition to the pipeline - Write-Output $def + if ($def) { + $out.Add($def) + } } Catch { @@ -127,7 +140,8 @@ Function Get-PSTypeExtension { } } #foreach - + #write sorted results + $out | Sort-Object -Property MemberType, Name } else { Write-Warning "Failed to find any type extensions for [$Typename]." @@ -139,6 +153,7 @@ Function Get-PSTypeExtension { Function Get-PSType { [cmdletbinding()] + [outputtype("System.String")] Param( [Parameter( Position = 0, @@ -187,101 +202,120 @@ Function Export-PSTypeExtension { )] [ValidatePattern("\.(xml|json|ps1xml)$")] [string]$Path, + [Parameter(ParameterSetName = "object", ValueFromPipeline)] [object]$InputObject ) Begin { Write-Verbose "Starting: $($MyInvocation.Mycommand)" - $data = @() - } - Process { - if ($Inputobject) { - Write-Verbose "Processing input type: $($InputObject.TypeName)" - $data += $Inputobject + + $PathParent = Split-Path -Path $Path + if (Test-Path -Path $PathParent) { + $validPath = $true } else { - Write-Verbose "Processing type: $TypeName" - foreach ($member in $membername) { - $data += Get-PSTypeExtension -TypeName $Typename -Members $Member - } + Write-Warning "Can't find parent path $pathParent" + $validPath = $False } + #initialize a list of objects + $data = [System.Collections.Generic.list[object]]::new() + #@() + } + Process { + #test if parent path exists + If ($validPath) { + if ($Inputobject) { + Write-Verbose "Processing input type: $($InputObject.TypeName)" + $data.Add($InputObject) + } + else { + Write-Verbose "Processing type: $TypeName" + foreach ($member in $membername) { + $typemember = Get-PSTypeExtension -TypeName $Typename -Members $Member + $data.Add($typemember) + } + } + } #test path parent } End { - if ($Path -match "\.ps1xml$") { - Write-Verbose "Saving as PS1XML" - #create a placeholder file so that I can later convert the path - New-Item -Path $path -Force | Out-Null - [xml]$Doc = New-Object System.Xml.XmlDocument + if ($validPath) { + Write-Verbose "Exporting data to $path" - #create declaration - $dec = $Doc.CreateXmlDeclaration("1.0", "UTF-8", $null) - #append to document - $doc.AppendChild($dec) | Out-Null + if ($Path -match "\.ps1xml$") { + Write-Verbose "Saving as PS1XML" + #create a placeholder file so that I can later convert the path + New-Item -Path $path -Force | Out-Null + [xml]$Doc = New-Object System.Xml.XmlDocument - #create a comment and append it in one line - $text = @" + #create declaration + $dec = $Doc.CreateXmlDeclaration("1.0", "UTF-8", $null) + #append to document + $doc.AppendChild($dec) | Out-Null + + #create a comment and append it in one line + $text = @" Custom type extensions generated by $($env:username) $(Get-Date) "@ - $doc.AppendChild($doc.CreateComment($text)) | Out-Null - - #create root Node - $root = $doc.CreateNode("element", "Types", $null) - $main = $doc.CreateNode("element", "Type", $null) - $name = $doc.CreateElement("Name") - $name.innerText = $data[0].TypeName - $main.AppendChild($name) | Out-Null - $member = $doc.CreateNode("element", "Members", $null) - foreach ($extension in $data) { - Write-Verbose "Exporting $($extension.membername)" - $membertype = $doc.createNode("element", $extension.memberType, $null) - $membernameEL = $doc.CreateElement("Name") - - $membernameEL.innertext = $extension.memberName - $membertype.AppendChild($membernameEL) | Out-Null - - Switch ($extension.Membertype) { - "ScriptMethod" { - $memberdef = $doc.createelement("Script") - } - "ScriptProperty" { - $memberdef = $doc.createelement("GetScriptBlock") - } - "AliasProperty" { - $memberdef = $doc.createelement("ReferencedMemberName") - } - "NoteProperty" { - $memberdef = $doc.createelement("Value") - } - Default { - Throw "Can't process a type of $($extension.MemberType)" + $doc.AppendChild($doc.CreateComment($text)) | Out-Null + + #create root Node + $root = $doc.CreateNode("element", "Types", $null) + $main = $doc.CreateNode("element", "Type", $null) + $name = $doc.CreateElement("Name") + $name.innerText = $data[0].TypeName + $main.AppendChild($name) | Out-Null + $member = $doc.CreateNode("element", "Members", $null) + foreach ($extension in $data) { + Write-Verbose "Exporting $($extension.membername)" + $membertype = $doc.createNode("element", $extension.memberType, $null) + $membernameEL = $doc.CreateElement("Name") + + $membernameEL.innertext = $extension.memberName + $membertype.AppendChild($membernameEL) | Out-Null + + Switch ($extension.Membertype) { + "ScriptMethod" { + $memberdef = $doc.createelement("Script") + } + "ScriptProperty" { + $memberdef = $doc.createelement("GetScriptBlock") + } + "AliasProperty" { + $memberdef = $doc.createelement("ReferencedMemberName") + } + "NoteProperty" { + $memberdef = $doc.createelement("Value") + } + Default { + Throw "Can't process a type of $($extension.MemberType)" + } } - } - $memberdef.InnerText = $extension.value - $membertype.AppendChild($memberdef) | Out-Null - $member.AppendChild($membertype) | Out-Null - - } #foreach - $main.AppendChild($member) | Out-Null - $root.AppendChild($main) | Out-Null - $doc.AppendChild($root) | Out-Null - $out = Convert-Path $path - if ($PSCmdlet.ShouldProcess($out)) { - $doc.save($out) - } #end Whatif - } - elseif ($path -match "\.xml$") { - Write-Verbose "Saving as XML" - $data | Export-Clixml -Path $path - } - else { - Write-Verbose "Saving as JSON" - $data | ConvertTo-Json | Set-Content -Path $Path + $memberdef.InnerText = $extension.value + $membertype.AppendChild($memberdef) | Out-Null + $member.AppendChild($membertype) | Out-Null + + } #foreach + $main.AppendChild($member) | Out-Null + $root.AppendChild($main) | Out-Null + $doc.AppendChild($root) | Out-Null + $out = Convert-Path $path + if ($PSCmdlet.ShouldProcess($out)) { + $doc.save($out) + } #end Whatif + } + elseif ($path -match "\.xml$") { + Write-Verbose "Saving as XML" + $data | Export-Clixml -Path $path + } + else { + Write-Verbose "Saving as JSON" + $data | ConvertTo-Json | Set-Content -Path $Path + } } - Write-Verbose "Exporting data to $path" Write-Verbose "Ending: $($MyInvocation.Mycommand)" } diff --git a/samples/fileage-type.ps1xml b/samples/fileage-type.ps1xml deleted file mode 100644 index 57aaada..0000000 --- a/samples/fileage-type.ps1xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - System.IO.FileInfo - - - FileAge - - Name - Size - LastWritetime - Age - - - - - \ No newline at end of file diff --git a/samples/fileinfo.types.ps1xml b/samples/fileinfo.types.ps1xml new file mode 100644 index 0000000..a77b6b3 --- /dev/null +++ b/samples/fileinfo.types.ps1xml @@ -0,0 +1,17 @@ + + + + System.IO.FileInfo + + + FileAge + + Name + Size + LastWritetime + Age + + + + + \ No newline at end of file