diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImportPowerShellDataFile.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImportPowerShellDataFile.cs new file mode 100644 index 000000000..d0418892b --- /dev/null +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImportPowerShellDataFile.cs @@ -0,0 +1,95 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Management.Automation; +using System.Management.Automation.Language; + +namespace Microsoft.PowerShell.Commands +{ + /// + /// This class implements Import-PowerShellDataFile command. + /// + [Cmdlet(VerbsData.Import, "PowerShellDataFile", DefaultParameterSetName = "ByPath", + HelpUri = "https://go.microsoft.com/fwlink/?LinkID=623621", RemotingCapability = RemotingCapability.None)] + public class ImportPowerShellDataFileCommand : PSCmdlet + { + bool _isLiteralPath; + + /// + /// Path specified, using globbing to resolve + /// + [Parameter(Mandatory = true, Position = 0, ParameterSetName = "ByPath")] + [ValidateNotNullOrEmpty] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public string[] Path { get; set; } + + /// + /// Specifies a path to one or more locations, without globbing + /// + [Parameter(Mandatory = true, Position = 0, ParameterSetName = "ByLiteralPath", ValueFromPipelineByPropertyName = true)] + [ValidateNotNullOrEmpty] + [Alias("PSPath")] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public string[] LiteralPath + { + get { return _isLiteralPath ? Path : null; } + set { _isLiteralPath = true; Path = value; } + } + + /// + /// For each path, resolve it, parse it and write all hashtables + /// to the output stream + /// + protected override void ProcessRecord() + { + foreach (var path in Path) + { + var resolved = PathUtils.ResolveFilePath(path, this, _isLiteralPath); + if(!string.IsNullOrEmpty(resolved) && System.IO.File.Exists(resolved)) + { + Token[] tokens; + ParseError[] errors; + var ast = Parser.ParseFile(resolved, out tokens, out errors); + if (errors.Length > 0) + { + WriteInvalidDataFileError(resolved, "CouldNotParseAsPowerShellDataFile"); + } + else + { + var data = ast.Find(a => a is HashtableAst, false); + if (data != null) + { + WriteObject(data.SafeGetValue()); + } + else + { + WriteInvalidDataFileError(resolved, "CouldNotParseAsPowerShellDataFileNoHashtableRoot"); + } + } + } + else + { + WritePathNotFoundError(path); + } + } + } + + private void WritePathNotFoundError(string path) + { + var errorId = "PathNotFound"; + var errorCategory = ErrorCategory.InvalidArgument; + var errorMessage = string.Format(UtilityResources.PathDoesNotExist, path); + var exception = new ArgumentException(errorMessage); + var errorRecord = new ErrorRecord(exception, errorId, errorCategory, path); + WriteError(errorRecord); + } + + void WriteInvalidDataFileError(string resolvedPath, string errorId) + { + var errorCategory = ErrorCategory.InvalidData; + var errorMessage = string.Format(UtilityResources.CouldNotParseAsPowerShellDataFile, resolvedPath); + var exception = new InvalidOperationException(errorMessage); + var errorRecord = new ErrorRecord(exception, errorId, errorCategory, resolvedPath); + WriteError(errorRecord); + } + } +} diff --git a/src/Modules/Shared/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psm1 b/src/Modules/Shared/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psm1 index f693cc64c..1f5acbe86 100644 --- a/src/Modules/Shared/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psm1 +++ b/src/Modules/Shared/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psm1 @@ -321,62 +321,6 @@ function Format-Hex } -## Imports a PowerShell Data File - a PowerShell hashtable defined in -## a file (such as a Module manifest, session configuration file) -function Import-PowerShellDataFile -{ - [CmdletBinding(DefaultParameterSetName = "ByPath", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=623621")] - [OutputType("System.Collections.Hashtable")] - param( - [Parameter(ParameterSetName = "ByPath", Position = 0)] - [String[]] $Path, - - [Parameter(ParameterSetName = "ByLiteralPath", ValueFromPipelineByPropertyName = $true)] - [Alias("PSPath")] - [String[]] $LiteralPath - ) - - begin - { - function ThrowInvalidDataFile - { - param($resolvedPath, $extraError) - - $errorId = "CouldNotParseAsPowerShellDataFile$extraError" - $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidData - $errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::CouldNotParseAsPowerShellDataFile -f $resolvedPath - $exception = [System.InvalidOperationException]::New($errorMessage) - $errorRecord = [System.Management.Automation.ErrorRecord]::New($exception, $errorId, $errorCategory, $null) - $PSCmdlet.WriteError($errorRecord) - } - } - - process - { - foreach($resolvedPath in (Resolve-Path @PSBoundParameters)) - { - $parseErrors = $null - $ast = [System.Management.Automation.Language.Parser]::ParseFile(($resolvedPath.ProviderPath), [ref] $null, [ref] $parseErrors) - if ($parseErrors.Length -gt 0) - { - ThrowInvalidDataFile $resolvedPath - } - else - { - $data = $ast.Find( { $args[0] -is [System.Management.Automation.Language.HashtableAst] }, $false ) - if($data) - { - $data.SafeGetValue() - } - else - { - ThrowInvalidDataFile $resolvedPath "NoHashtableRoot" - } - } - } - } -} - ## Converts a SDDL string into an object-based representation of a security ## descriptor function ConvertFrom-SddlString @@ -549,4 +493,4 @@ function ConvertFrom-SddlString RawDescriptor = $rawSecurityDescriptor } } -} \ No newline at end of file +} diff --git a/src/Modules/Unix/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 b/src/Modules/Unix/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 index 3f1324027..03ab08635 100644 --- a/src/Modules/Unix/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 +++ b/src/Modules/Unix/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 @@ -17,7 +17,7 @@ CmdletsToExport= "Format-List", "Format-Custom", "Format-Table", "Format-Wide", "Start-Sleep", "Tee-Object", "Measure-Command", "Update-TypeData", "Update-FormatData", "Remove-TypeData", "Get-TypeData", "Write-Host", "Write-Progress", "New-Object", "Select-Object", "Group-Object", "Sort-Object", "Get-Variable", "New-Variable", "Set-Variable", "Remove-Variable", - "Clear-Variable", "Export-Clixml", "Import-Clixml", "ConvertTo-Xml", "Select-Xml", "Write-Debug", + "Clear-Variable", "Export-Clixml", "Import-Clixml", "Import-PowerShellDataFile", "ConvertTo-Xml", "Select-Xml", "Write-Debug", "Write-Verbose", "Write-Warning", "Write-Error", "Write-Information", "Write-Output", "Set-PSBreakpoint", "Get-PSBreakpoint", "Remove-PSBreakpoint", "Enable-PSBreakpoint", "Disable-PSBreakpoint", "Get-PSCallStack", "Get-TraceSource", "Set-TraceSource", "Trace-Command", "Get-FileHash", diff --git a/src/Modules/Windows-Core/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 b/src/Modules/Windows-Core/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 index a6d6ed2ba..d42ab9be6 100644 --- a/src/Modules/Windows-Core/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 +++ b/src/Modules/Windows-Core/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 @@ -17,13 +17,13 @@ CmdletsToExport= "Format-List", "Format-Custom", "Format-Table", "Format-Wide", "Start-Sleep", "Tee-Object", "Measure-Command", "Update-TypeData", "Update-FormatData", "Remove-TypeData", "Get-TypeData", "Write-Host", "Write-Progress", "New-Object", "Select-Object", "Group-Object", "Sort-Object", "Get-Variable", "New-Variable", "Set-Variable", "Remove-Variable", - "Clear-Variable", "Export-Clixml", "Import-Clixml", "ConvertTo-Xml", "Select-Xml", "Write-Debug", + "Clear-Variable", "Export-Clixml", "Import-Clixml", "Import-PowerShellDataFile","ConvertTo-Xml", "Select-Xml", "Write-Debug", "Write-Verbose", "Write-Warning", "Write-Error", "Write-Information", "Write-Output", "Set-PSBreakpoint", "Get-PSBreakpoint", "Remove-PSBreakpoint", "New-TemporaryFile", "Enable-PSBreakpoint", "Disable-PSBreakpoint", "Get-PSCallStack", "Get-TraceSource", "Set-TraceSource", "Trace-Command", "Get-FileHash", "Unblock-File", "Get-Runspace", "Debug-Runspace", "Enable-RunspaceDebug", "Disable-RunspaceDebug", "Get-RunspaceDebug", "Wait-Debugger" , "Get-Uptime", "Get-Verb" -FunctionsToExport= "Format-Hex", "Import-PowerShellDataFile", "ConvertFrom-SddlString" +FunctionsToExport= "Format-Hex", "ConvertFrom-SddlString" AliasesToExport= "fhx" NestedModules="Microsoft.PowerShell.Commands.Utility.dll","Microsoft.PowerShell.Utility.psm1" HelpInfoURI = 'https://go.microsoft.com/fwlink/?linkid=390787' diff --git a/src/Modules/Windows-Full/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 b/src/Modules/Windows-Full/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 index 7566b3d42..62eafabfd 100644 --- a/src/Modules/Windows-Full/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 +++ b/src/Modules/Windows-Full/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1 @@ -19,13 +19,13 @@ CmdletsToExport= "Format-List", "Format-Custom", "Format-Table", "Format-Wide", "Start-Sleep", "Tee-Object", "Measure-Command", "Update-List", "Update-TypeData", "Update-FormatData", "Remove-TypeData", "Get-TypeData", "Write-Host", "Write-Progress", "New-Object", "Select-Object", "Group-Object", "Sort-Object", "Get-Variable", "New-Variable", "Set-Variable", "Remove-Variable", - "Clear-Variable", "Export-Clixml", "Import-Clixml", "ConvertTo-Xml", "Select-Xml", "Write-Debug", + "Clear-Variable", "Export-Clixml", "Import-Clixml", "Import-PowerShellDataFile", "ConvertTo-Xml", "Select-Xml", "Write-Debug", "Write-Verbose", "Write-Warning", "Write-Error", "Write-Information", "Write-Output", "Set-PSBreakpoint", "Get-PSBreakpoint", "Remove-PSBreakpoint", "Enable-PSBreakpoint", "Disable-PSBreakpoint", "Get-PSCallStack", "Send-MailMessage", "Get-TraceSource", "Set-TraceSource", "Trace-Command", "Show-Command", "Unblock-File", "Get-FileHash", "Get-Runspace", "Debug-Runspace", "Enable-RunspaceDebug", "Disable-RunspaceDebug", "Get-RunspaceDebug", "Wait-Debugger", "ConvertFrom-String", "Convert-String" , "Get-Uptime", "New-TemporaryFile", "Get-Verb" -FunctionsToExport= "Format-Hex", "Import-PowerShellDataFile", "ConvertFrom-SddlString" +FunctionsToExport= "Format-Hex", "ConvertFrom-SddlString" AliasesToExport= "CFS", "fhx" NestedModules="Microsoft.PowerShell.Commands.Utility.dll","Microsoft.PowerShell.Utility.psm1" HelpInfoURI = 'https://go.microsoft.com/fwlink/?linkid=390787' diff --git a/src/vs-csproj/Microsoft.PowerShell.Commands.Utility.csproj b/src/vs-csproj/Microsoft.PowerShell.Commands.Utility.csproj index a992a72a7..67abf7ef1 100644 --- a/src/vs-csproj/Microsoft.PowerShell.Commands.Utility.csproj +++ b/src/vs-csproj/Microsoft.PowerShell.Commands.Utility.csproj @@ -580,7 +580,12 @@ singleshell\installer\MshUtilityMshSnapin.cs - + + commands\utility\GetVerbCommand.cs + + + commands\utility\ImportPowerShellDataFile.cs + diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 index 9bd64bd9b..d4a413570 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/PowerShellData.tests.ps1 @@ -9,7 +9,7 @@ } catch { - $_.FullyQualifiedErrorId | Should be "PathNotFound,Microsoft.PowerShell.Commands.ResolvePathCommand" + $_.FullyQualifiedErrorId | Should be "PathNotFound,Microsoft.PowerShell.Commands.ImportPowerShellDataFileCommand" } } @@ -22,7 +22,7 @@ } catch { - $_.FullyQualifiedErrorId | Should be "CouldNotParseAsPowerShellDataFile,Import-PowerShellDataFile" + $_.FullyQualifiedErrorId | Should be "PathNotFound,Microsoft.PowerShell.Commands.ImportPowerShellDataFileCommand" } } @@ -37,7 +37,7 @@ } catch { - $_.FullyQualifiedErrorId | Should be "InvalidOperationException,Import-PowerShellDataFile" + $_.FullyQualifiedErrorId | Should be "System.InvalidOperationException,Microsoft.PowerShell.Commands.ImportPowerShellDataFileCommand" } } @@ -51,7 +51,7 @@ } catch { - $_.FullyQualifiedErrorId | Should be "CouldNotParseAsPowerShellDataFileNoHashtableRoot,Import-PowerShellDataFile" + $_.FullyQualifiedErrorId | Should be "CouldNotParseAsPowerShellDataFileNoHashtableRoot,Microsoft.PowerShell.Commands.ImportPowerShellDataFileCommand" } }