diff --git a/PSModuleDevelopment/PSModuleDevelopment.psd1 b/PSModuleDevelopment/PSModuleDevelopment.psd1 index 8cfb0c9..1e440c0 100644 --- a/PSModuleDevelopment/PSModuleDevelopment.psd1 +++ b/PSModuleDevelopment/PSModuleDevelopment.psd1 @@ -5,7 +5,7 @@ # Version number of this module. - ModuleVersion = '2.2.11.168' + ModuleVersion = '2.2.12.171' # ID used to uniquely identify this module GUID = '37dd5fce-e7b5-4d57-ac37-832055ce49d6' @@ -28,7 +28,7 @@ # Modules that must be imported into the global environment prior to importing # this module RequiredModules = @( - @{ ModuleName = 'PSFramework'; ModuleVersion = '1.7.270' } + @{ ModuleName = 'PSFramework'; ModuleVersion = '1.12.346' } @{ ModuleName = 'string'; ModuleVersion = '1.1.3' } ) diff --git a/PSModuleDevelopment/bin/PSModuleDevelopment.dll b/PSModuleDevelopment/bin/PSModuleDevelopment.dll index 57ef0fa..7b367b5 100644 Binary files a/PSModuleDevelopment/bin/PSModuleDevelopment.dll and b/PSModuleDevelopment/bin/PSModuleDevelopment.dll differ diff --git a/PSModuleDevelopment/bin/PSModuleDevelopment.pdb b/PSModuleDevelopment/bin/PSModuleDevelopment.pdb index c0a219a..405490d 100644 Binary files a/PSModuleDevelopment/bin/PSModuleDevelopment.pdb and b/PSModuleDevelopment/bin/PSModuleDevelopment.pdb differ diff --git a/PSModuleDevelopment/bin/PSModuleDevelopment.xml b/PSModuleDevelopment/bin/PSModuleDevelopment.xml index 8fb47fb..dd9f075 100644 --- a/PSModuleDevelopment/bin/PSModuleDevelopment.xml +++ b/PSModuleDevelopment/bin/PSModuleDevelopment.xml @@ -449,6 +449,12 @@ The name of the parameter. This is used to insert it into individual files or file names. + + + Creates a prefilled parameter script. Usually used in fixing serialization the hard way. + + The deserialized ParameterScript item + Class containing information relating to where templates are stored @@ -551,6 +557,23 @@ A TemplateInfo object describing this template. + + + Create a blank template object + + + + + Create a template object based on a deserialized template object + + The deserialized tample object to restore + If anything at all is not as it should be. + + + + Static helpers for the template system + + Class containing meta information about a template @@ -823,6 +846,29 @@ The actual value found The original input object offered to the command. + + + Extends the PSObject with C# convenience + + + + + Get the value! + + The type of the value + The object to extend + The name of the property that has the value + The value + + + + Get a hashtable value! + + The type of the values in hashtable + The object to extend + The name of the property that has the hashtable + The hashtable! + What a text can be aligned to diff --git a/PSModuleDevelopment/changelog.md b/PSModuleDevelopment/changelog.md index f48423b..57a505d 100644 --- a/PSModuleDevelopment/changelog.md +++ b/PSModuleDevelopment/changelog.md @@ -1,5 +1,11 @@ # Changelog +## 2.2.12.171 (2024-10-04) + ++ Upd: Raised PSFramework dependency due to critical security update ++ Fix: Invoke-PSMDTemplate - fails on non-Windows ++ Fix: Invoke-PSMDTemplate - fails with latest PSFramework version + ## 2.2.11.168 (2024-05-31) + Upd: Template AzureFunction - added config option to override http Endpoint methods (#198) diff --git a/PSModuleDevelopment/functions/templating/New-PSMDTemplate.ps1 b/PSModuleDevelopment/functions/templating/New-PSMDTemplate.ps1 index 61d9133..2960b9c 100644 --- a/PSModuleDevelopment/functions/templating/New-PSMDTemplate.ps1 +++ b/PSModuleDevelopment/functions/templating/New-PSMDTemplate.ps1 @@ -552,7 +552,7 @@ $template.CreatedOn = (Get-Date).Date - $template | Export-Clixml -Path (Join-Path $exportFolder $fileName) - $template.ToTemplateInfo() | Export-Clixml -Path (Join-Path $exportFolder $infoFileName) + $template | Export-PSFClixml -Path (Join-Path $exportFolder $fileName) -Depth 99 + $template.ToTemplateInfo() | Export-PSFClixml -Path (Join-Path $exportFolder $infoFileName) } } \ No newline at end of file diff --git a/build/vsts-build-library.ps1 b/build/vsts-build-library.ps1 new file mode 100644 index 0000000..88ae099 --- /dev/null +++ b/build/vsts-build-library.ps1 @@ -0,0 +1,38 @@ +<# +.SYNOPSIS + Builds the PSFramework binary library from source. + +.DESCRIPTION + Builds the PSFramework binary library from source. + +.PARAMETER WorkingDirectory + Path where the project root is. + Defaults to the parent folder this file is in. + +.EXAMPLE + PS C:\> .\vsts-build-library.ps1 + + Builds the PSFramework binary library from source. +#> +[CmdletBinding()] +param ( + $WorkingDirectory +) + +#region Handle Working Directory Defaults +if (-not $WorkingDirectory) +{ + if ($env:RELEASE_PRIMARYARTIFACTSOURCEALIAS) + { + $WorkingDirectory = Join-Path -Path $env:SYSTEM_DEFAULTWORKINGDIRECTORY -ChildPath $env:RELEASE_PRIMARYARTIFACTSOURCEALIAS + } + else { $WorkingDirectory = $env:SYSTEM_DEFAULTWORKINGDIRECTORY } +} +if (-not $WorkingDirectory) { $WorkingDirectory = Split-Path $PSScriptRoot } +#endregion Handle Working Directory Defaults + +# Build Library +dotnet build "$WorkingDirectory\library\PSModuleDevelopment\PSModuleDevelopment.sln" +if ($LASTEXITCODE -ne 0) { + throw "Failed to build PSModuleDevelopment.dll!" +} \ No newline at end of file diff --git a/dev/launch.ps1 b/dev/launch.ps1 new file mode 100644 index 0000000..121e286 --- /dev/null +++ b/dev/launch.ps1 @@ -0,0 +1,111 @@ +[CmdletBinding()] +param ( + [switch] + $Local, + + [switch] + $Build, + + [ValidateSet('Desktop', 'Core')] + [string] + $PSVersion +) + +#region Launch in new cponsole +if (-not $Local) { + $application = (Get-Process -id $PID).Path + if ($PSVersion -and $PSVersionTable.Edition -ne $PSVersion) { + $application = 'pwsh.exe' + if ($PSVersion -eq 'Desktop') { $application = 'powershell.exe'} + } + + $arguments = @('-NoExit', '-NoProfile', '-File', "$PSScriptRoot\launch.ps1", '-Local') + if ($Build) { $arguments += '-Build' } + + Start-Process $application -ArgumentList $arguments + return +} +#endregion Launch in new cponsole + +$ErrorActionPreference = 'Stop' +trap { + Write-Warning "Script failed: $_" + throw $_ +} + +#region Functions +function New-TemporaryPath { + [OutputType([string])] + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $Prefix + ) + + Write-Host "Creating new temporary path: $Prefix" + + # Remove Previous Temporary Paths + Remove-Item -Path "$env:Temp\$Prefix*" -Force -Recurse -ErrorAction SilentlyContinue + + # Create New Temporary Path + $item = New-Item -Path $env:TEMP -Name "$($Prefix)_$(Get-Random)" -ItemType Directory + $item.FullName +} + +function Build-Template { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $RootPath, + + [Parameter(Mandatory = $true)] + [string] + $ProjectPath + ) + + Write-Host "Building Templates from Source" + $buildScriptPath = Join-Path -Path $ProjectPath -ChildPath "templates\build.ps1" + & $buildScriptPath -Path $RootPath + + Set-PSFConfig -FullName 'PSModuleDevelopment.Template.Store.PSModuleDevelopment' -Value "$RootPath\output" +} + +function Import-PsmdModule { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $ProjectPath + ) + + Write-Host "Importing PSModuleDevelopment from source code" + Import-Module "$ProjectPath\PSModuleDevelopment\PSModuleDevelopment.psd1" -Global + + # Does not work during initial start + # [Microsoft.PowerShell.PSConsoleReadLine]::AddToHistory("ipmo '$ProjectPath\PSModuleDevelopment\PSModuleDevelopment.psd1'") +} + +function Build-PsmdModule { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $ProjectPath + ) + + Write-Host "Building Library. This may require the .NET 4.8 Targeting Pack" + try { $null = & "$ProjectPath\build\vsts-build-library.ps1" } + catch { + Write-Host "Targeting pack Download Link: https://dotnet.microsoft.com/en-us/download/visual-studio-sdks?cid=getdotnetsdk" + throw + } +} +#endregion Functions + +$projectRoot = Resolve-Path -Path "$PSScriptRoot\.." +$templateRoot = New-TemporaryPath -Prefix PsmdTemplate +if ($Build) { Build-PsmdModule -ProjectPath $projectRoot } +Import-PsmdModule -ProjectPath $projectRoot +Build-Template -RootPath $templateRoot -ProjectPath $projectRoot \ No newline at end of file diff --git a/library/PSModuleDevelopment/PSModuleDevelopment/.vs/PSModuleDevelopment.csproj.dtbcache.json b/library/PSModuleDevelopment/PSModuleDevelopment/.vs/PSModuleDevelopment.csproj.dtbcache.json new file mode 100644 index 0000000..dd3098b --- /dev/null +++ b/library/PSModuleDevelopment/PSModuleDevelopment/.vs/PSModuleDevelopment.csproj.dtbcache.json @@ -0,0 +1 @@ +{"RootPath":"F:\\Code\\Github\\PSModuleDevelopment\\library\\PSModuleDevelopment\\PSModuleDevelopment","ProjectFileName":"PSModuleDevelopment.csproj","Configuration":"Debug|AnyCPU","FrameworkPath":"","Sources":[{"SourceFile":"Format\\Column.cs"},{"SourceFile":"Format\\Alignment.cs"},{"SourceFile":"Format\\ColumnTransformation.cs"},{"SourceFile":"Format\\Document.cs"},{"SourceFile":"Format\\TableDefinition.cs"},{"SourceFile":"Format\\ViewDefinitionBase.cs"},{"SourceFile":"Properties\\AssemblyInfo.cs"},{"SourceFile":"PsmdAssembly\\Constructor.cs"},{"SourceFile":"Template\\Parameter\\ParameterBase.cs"},{"SourceFile":"Template\\ParameterScript.cs"},{"SourceFile":"Template\\Parameter\\ParameterPrompt.cs"},{"SourceFile":"Template\\Parameter\\ParameterScript.cs"},{"SourceFile":"Template\\Parameter\\ScriptExecutionTime.cs"},{"SourceFile":"Template\\Store.cs"},{"SourceFile":"Template\\Template.cs"},{"SourceFile":"Template\\TemplateInfo.cs"},{"SourceFile":"Template\\TemplateItemBase.cs"},{"SourceFile":"Template\\TemplateItemFile.cs"},{"SourceFile":"Template\\TemplateItemFolder.cs"},{"SourceFile":"Template\\TemplateResult.cs"},{"SourceFile":"Template\\TemplateType.cs"},{"SourceFile":"Utility\\LinesOfCode.cs"},{"SourceFile":"Utility\\PropertySearchResult.cs"},{"SourceFile":"Utility\\TextAlignment.cs"},{"SourceFile":"Utility\\TextHeader.cs"},{"SourceFile":"Utility\\UtilityHost.cs"},{"SourceFile":"obj\\Debug\\.NETFramework,Version=v4.8.AssemblyAttributes.cs"}],"References":[{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\Microsoft.CSharp.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\mscorlib.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"F:\\Code\\Github\\psframework\\PSFramework\\bin\\PSFramework.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Core.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Data.DataSetExtensions.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Data.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Windows\\Microsoft.NET\\assembly\\GAC_MSIL\\System.Management.Automation\\v4.0_3.0.0.0__31bf3856ad364e35\\System.Management.Automation.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Net.Http.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Xml.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Xml.Linq.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""}],"Analyzers":[],"Outputs":[{"OutputItemFullPath":"F:\\Code\\Github\\PSModuleDevelopment\\PSModuleDevelopment\\bin\\PSModuleDevelopment.dll","OutputItemRelativePath":"PSModuleDevelopment.dll"},{"OutputItemFullPath":"","OutputItemRelativePath":""}],"CopyToOutputEntries":[]} \ No newline at end of file diff --git a/library/PSModuleDevelopment/PSModuleDevelopment/PSModuleDevelopment.csproj b/library/PSModuleDevelopment/PSModuleDevelopment/PSModuleDevelopment.csproj index b1fa450..d24e403 100644 --- a/library/PSModuleDevelopment/PSModuleDevelopment/PSModuleDevelopment.csproj +++ b/library/PSModuleDevelopment/PSModuleDevelopment/PSModuleDevelopment.csproj @@ -66,6 +66,7 @@ + @@ -74,6 +75,7 @@ + diff --git a/library/PSModuleDevelopment/PSModuleDevelopment/Template/ParameterScript.cs b/library/PSModuleDevelopment/PSModuleDevelopment/Template/ParameterScript.cs index 1e0b020..d34c24f 100644 --- a/library/PSModuleDevelopment/PSModuleDevelopment/Template/ParameterScript.cs +++ b/library/PSModuleDevelopment/PSModuleDevelopment/Template/ParameterScript.cs @@ -50,5 +50,15 @@ public ParameterScript(string Name, ScriptBlock ScriptBlock) this.Name = Name; this.ScriptBlock = ScriptBlock; } + + /// + /// Creates a prefilled parameter script. Usually used in fixing serialization the hard way. + /// + /// The deserialized ParameterScript item + public ParameterScript(PSObject Item) + { + Name = (string)Item.Properties["Name"].Value; + ScriptBlock = ScriptBlock.Create((string)Item.Properties["ScriptBlock"].Value); + } } } diff --git a/library/PSModuleDevelopment/PSModuleDevelopment/Template/Template.cs b/library/PSModuleDevelopment/PSModuleDevelopment/Template/Template.cs index 0fa0d85..494c2eb 100644 --- a/library/PSModuleDevelopment/PSModuleDevelopment/Template/Template.cs +++ b/library/PSModuleDevelopment/PSModuleDevelopment/Template/Template.cs @@ -2,8 +2,10 @@ using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Management.Automation; using System.Text; using System.Threading.Tasks; +using PSModuleDevelopment.Utility; namespace PSModuleDevelopment.Template { @@ -96,5 +98,46 @@ public TemplateInfo ToTemplateInfo() return info; } + + /// + /// Create a blank template object + /// + public Template() + { + + } + + /// + /// Create a template object based on a deserialized template object + /// + /// The deserialized tample object to restore + /// If anything at all is not as it should be. + public Template(PSObject Item) + { + try + { + Name = Item.GetValue("Name"); + Type = (TemplateType)Item.GetValue("Type"); + Version = Item.GetValue("Version"); + Description = Item.GetValue("Description"); + Author = Item.GetValue("Author"); + CreatedOn = Item.GetValue("CreatedOn"); + foreach (object item in Item.GetValue("Tags")) + Tags.Add((string)item); + foreach (object item in Item.GetValue("Parameters")) + Parameters.Add((string)item); + foreach (KeyValuePair entry in Item.GetDictionary("Scripts")) + Scripts[entry.Key] =entry.Value; + // Parameters2 not used + foreach (object item in Item.GetValue("Children")) + Children.Add(TemplateHost.GetTemplateItem(item)); + + Generation = Item.GetValue("Generation"); + } + catch (Exception e) + { + throw new ArgumentException($"Cannot convert {Item} of type {Item.BaseObject.GetType().FullName} to type PSModuleDevelopment.Template.Template! {e.Message}", e); + } + } } } diff --git a/library/PSModuleDevelopment/PSModuleDevelopment/Template/TemplateHost.cs b/library/PSModuleDevelopment/PSModuleDevelopment/Template/TemplateHost.cs new file mode 100644 index 0000000..3ed53af --- /dev/null +++ b/library/PSModuleDevelopment/PSModuleDevelopment/Template/TemplateHost.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Management.Automation; +using System.Text; +using System.Threading.Tasks; +using PSModuleDevelopment.Utility; + +namespace PSModuleDevelopment.Template +{ + /// + /// Static helpers for the template system + /// + internal static class TemplateHost + { + internal static TemplateItemBase GetTemplateItem(object Item) + { + if (Item.GetType() == typeof(TemplateItemFile)) + return (TemplateItemFile)Item; + + TemplateItemFolder result = new TemplateItemFolder(); ; + PSObject PSItem = PSObject.AsPSObject(Item); + + foreach (object child in PSItem.GetValue("Children")) + result.Children.Add(GetTemplateItem(child)); + + result.Name = PSItem.GetValue("Name"); + result.RelativePath = PSItem.GetValue("RelativePath"); + result.Identifier = PSItem.GetValue("Identifier"); + foreach (string entry in PSItem.GetValue("FileSystemParameterFlat")) + result.FileSystemParameterFlat.Add(entry); + foreach (string entry in PSItem.GetValue("FileSystemParameterScript")) + result.FileSystemParameterScript.Add(entry); + + return result; + } + } +} diff --git a/library/PSModuleDevelopment/PSModuleDevelopment/Utility/PSObjectExtension.cs b/library/PSModuleDevelopment/PSModuleDevelopment/Utility/PSObjectExtension.cs new file mode 100644 index 0000000..8fb3235 --- /dev/null +++ b/library/PSModuleDevelopment/PSModuleDevelopment/Utility/PSObjectExtension.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Management.Automation; +using System.Text; +using System.Threading.Tasks; + +namespace PSModuleDevelopment.Utility +{ + /// + /// Extends the PSObject with C# convenience + /// + public static class PSObjectExtension + { + /// + /// Get the value! + /// + /// The type of the value + /// The object to extend + /// The name of the property that has the value + /// The value + public static T GetValue(this PSObject PSObject, string Name) + { + PSObject value = PSObject.AsPSObject(PSObject.Properties[Name].Value); + return (T)value.BaseObject; + } + + /// + /// Get a hashtable value! + /// + /// The type of the values in hashtable + /// The object to extend + /// The name of the property that has the hashtable + /// The hashtable! + public static Dictionary GetDictionary(this PSObject PSObject, string Name) + { + Hashtable temp = PSObject.GetValue(Name); + Dictionary result = new Dictionary(); + foreach (DictionaryEntry pair in temp) + result[(string)pair.Key] = (T)pair.Value; + + return result; + } + } +}