Merge branch 'PowerShell:master' into KeywordCompletions

This commit is contained in:
MartinGC94 2024-02-10 18:22:04 +01:00 committed by GitHub
commit 9ebc8f9085
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 321 additions and 157 deletions

View File

@ -1,5 +1,41 @@
# 7.4 Changelog
## [7.4.1] - 2024-01-11
### General Cmdlet Updates and Fixes
- Fix `Group-Object` output using interpolated strings (#20745) (Thanks @mawosoft!)
- Fix `Start-Process -PassThru` to make sure the `ExitCode` property is accessible for the returned `Process` object (#20749) (#20866) (Thanks @CodeCyclone!)
- Fix rendering of DisplayRoot for network PSDrive (#20793) (#20863)
### Engine Updates and Fixes
- Ensure filename is not null when logging WDAC ETW events (#20910) (Thanks @jborean93!)
- Fix four regressions introduced by WDAC audit logging feature (#20913)
### Build and Packaging Improvements
<details>
<summary>
Bump .NET 8 to version 8.0.101
</summary>
<ul>
<li>Update .NET SDK and dependencies for v7.4.1 (Internal 29142)</li>
<li>Update cgmanifest for v7.4.1 (#20874)</li>
<li>Update package dependencies for v7.4.1 (#20871)</li>
<li>Set the <code>rollForwardOnNoCandidateFx</code> in <code>runtimeconfig.json</code> to roll forward only on minor and patch versions (#20689) (#20865)</li>
<li>Remove RHEL7 publishing to packages.microsoft.com as it's no longer supported (#20849) (#20864)</li>
<li>Fix the tab completion tests (#20867)</li>
</ul>
</details>
[7.4.1]: https://github.com/PowerShell/PowerShell/compare/v7.4.0...v7.4.1
## [7.4.0] - 2023-11-16
### General Cmdlet Updates and Fixes

View File

@ -20,6 +20,15 @@
<?else?>
<?define UpgradeCode = $(var.UpgradeCodeRelease)?>
<?endif?>
<?elseif $(sys.BUILDARCH) = "ARM64"?>
<?define ExplorerContextMenuDialogText = "&$(var.ProductName) $(var.SimpleProductVersion) ($(sys.BUILDARCH))"?>
<?define UpgradeCodePreview = "f064cf16-97b7-4550-b392-ce0f4a6823a3"?>
<?define UpgradeCodeRelease = "75c68ab2-09d8-46b8-b697-d829bdd4c94f"?>
<?if $(var.IsPreview)=True?>
<?define UpgradeCode = $(var.UpgradeCodePreview)?>
<?else?>
<?define UpgradeCode = $(var.UpgradeCodeRelease)?>
<?endif?>
<?else?>
<?define ExplorerContextMenuDialogText = "&$(var.ProductName) $(var.SimpleProductVersion) ($(sys.BUILDARCH))"?>
<?define UpgradeCodePreview = "86abcfbd-1ccc-4a88-b8b2-0facfde29094"?>

View File

@ -9,6 +9,15 @@
<?else?>
<?define UpgradeCode = $(var.UpgradeCodeRelease)?>
<?endif?>
<?elseif $(sys.BUILDARCH) = "ARM64"?>
<?define ExplorerContextMenuDialogText = "&$(var.ProductName) $(var.SimpleProductVersion) ($(sys.BUILDARCH))"?>
<?define UpgradeCodePreview = "499e9123-48aa-41df-aa20-6f4d28b54722"?>
<?define UpgradeCodeRelease = "4cc0e36a-17db-4c84-b4f4-560a11e7ddb6"?>
<?if $(var.IsPreview)=True?>
<?define UpgradeCode = $(var.UpgradeCodePreview)?>
<?else?>
<?define UpgradeCode = $(var.UpgradeCodeRelease)?>
<?endif?>
<?else?>
<?define UpgradeCodePreview = "4A699A9C-E904-4024-BCD2-44E098A8C6BD"?>
<?define UpgradeCodeRelease = "ED46CB02-64B3-43FD-A63E-6CF269D8C21C"?>

View File

@ -38,6 +38,7 @@ Special consideration should be given to topics like **backwards compatibility**
* @adityapatwardhan (SDK)
* @michaeltlombardi
* @SeeminglyScience
* @bergmeister
## Engine
@ -49,8 +50,8 @@ This includes (but is not limited to):
* The language parser
* The command and parameter binders
* The module and provider systems
* `*-Item` cmdlets
* Providers
* `*-Item` cmdlets
* Providers
* Performance
* Componentization
* AssemblyLoadContext
@ -61,7 +62,6 @@ However, it's expected that many issues will require input from both WGs.
### Members
* @BrucePay
* @daxian-dbw
* @JamesWTruher
* @rkeithhill
@ -104,7 +104,6 @@ particularly given the long-lasting effects of language decisions.
* @JamesWTruher
* @daxian-dbw
* @BrucePay
* @SeeminglyScience
## Remoting
@ -118,14 +117,13 @@ Given the commonality of serialization boundaries, the Remoting WG should also f
### Members
* @anmenaga
* @PaulHigin
* @TravisEz13
## Cmdlets and Modules
The Cmdlet WG should focus on core/inbox modules whose source code lives within the
`PowerShell/PowerShell` repository,
including the proposal of new cmdlets and parameters, improvements and bug fixes to existing
including the proposal of new cmdlets and parameters, improvements and bugfixes to existing
cmdlets/parameters, and breaking changes.
However, some modules that ship as part of the PowerShell package are managed in other source repositories.
@ -147,6 +145,7 @@ These modules include:
* @SteveL-MSFT
* @jdhitsolutions
* @TobiasPSP
* @doctordns
## Security
@ -156,7 +155,8 @@ in order to provide their expertise, concerns, and guidance.
### Members
* @TravisEz13
* @PaulHigin
* @SydneySmithReal
* @anamnavi
## Explicitly not Working Groups
@ -170,12 +170,12 @@ This bucket is also not oriented a customer-facing deliverable and is already so
so we don't need to address it as part of the WGs.
* Build
* `build.psm1`
* `install-powershell.ps1`
* Build infrastructure and automation
* `build.psm1`
* `install-powershell.ps1`
* Build infrastructure and automation
* Packaging
* Scripts
* Infrastructure
* Scripts
* Infrastructure
### Quality
@ -184,10 +184,10 @@ Similar to the topic of building PowerShell, quality
should be managed by the PowerShell Maintainers.
* Test code
* Pester unit tests
* xUnit unit tests
* Pester unit tests
* xUnit unit tests
* Test infrastructure
* Nightlies
* CI
* Nightlies
* CI
* Code coverage
* Pester

View File

@ -35,7 +35,7 @@
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
<PackageReference Include="System.Threading.AccessControl" Version="8.0.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.1" />
<PackageReference Include="JsonSchema.Net" Version="5.5.0" />
<PackageReference Include="JsonSchema.Net" Version="5.5.1" />
</ItemGroup>
</Project>

View File

@ -946,9 +946,11 @@ namespace System.Management.Automation
/// <summary>
/// Add a cmdlet to construct a command pipeline.
/// For example, to construct a command string "get-process | sort-object",
/// For example, to construct a command string "Get-Process | Sort-Object",
/// <code>
/// PowerShell shell = PowerShell.Create("get-process").AddCommand("sort-object");
/// PowerShell shell = PowerShell.Create()
/// .AddCommand("Get-Process")
/// .AddCommand("Sort-Object");
/// </code>
/// </summary>
/// <param name="cmdlet">
@ -984,9 +986,11 @@ namespace System.Management.Automation
/// <summary>
/// Add a cmdlet to construct a command pipeline.
/// For example, to construct a command string "get-process | sort-object",
/// For example, to construct a command string "Get-Process | Sort-Object",
/// <code>
/// PowerShell shell = PowerShell.Create("get-process").AddCommand("sort-object");
/// PowerShell shell = PowerShell.Create()
/// .AddCommand("Get-Process", true)
/// .AddCommand("Sort-Object", true);
/// </code>
/// </summary>
/// <param name="cmdlet">
@ -1025,10 +1029,10 @@ namespace System.Management.Automation
/// <summary>
/// Add a piece of script to construct a command pipeline.
/// For example, to construct a command string "get-process | foreach { $_.Name }"
/// For example, to construct a command string "Get-Process | ForEach-Object { $_.Name }"
/// <code>
/// PowerShell shell = PowerShell.Create("get-process").
/// AddCommand("foreach { $_.Name }", true);
/// PowerShell shell = PowerShell.Create()
/// .AddScript("Get-Process | ForEach-Object { $_.Name }");
/// </code>
/// </summary>
/// <param name="script">
@ -1064,10 +1068,10 @@ namespace System.Management.Automation
/// <summary>
/// Add a piece of script to construct a command pipeline.
/// For example, to construct a command string "get-process | foreach { $_.Name }"
/// For example, to construct a command string "Get-Process | ForEach-Object { $_.Name }"
/// <code>
/// PowerShell shell = PowerShell.Create("get-process").
/// AddCommand("foreach { $_.Name }", true);
/// PowerShell shell = PowerShell.Create()
/// .AddScript("Get-Process | ForEach-Object { $_.Name }", true);
/// </code>
/// </summary>
/// <param name="script">
@ -1173,10 +1177,11 @@ namespace System.Management.Automation
/// <summary>
/// Add a parameter to the last added command.
/// For example, to construct a command string "get-process | select-object -property name"
/// For example, to construct a command string "Get-Process | Select-Object -Property Name"
/// <code>
/// PowerShell shell = PowerShell.Create("get-process").
/// AddCommand("select-object").AddParameter("property","name");
/// PowerShell shell = PowerShell.Create()
/// .AddCommand("Get-Process")
/// .AddCommand("Select-Object").AddParameter("Property", "Name");
/// </code>
/// </summary>
/// <param name="parameterName">
@ -1378,10 +1383,11 @@ namespace System.Management.Automation
/// <summary>
/// Adds an argument to the last added command.
/// For example, to construct a command string "get-process | select-object name"
/// For example, to construct a command string "Get-Process | Select-Object Name"
/// <code>
/// PowerShell shell = PowerShell.Create("get-process").
/// AddCommand("select-object").AddParameter("name");
/// PowerShell shell = PowerShell.Create()
/// .AddCommand("Get-Process")
/// .AddCommand("Select-Object").AddArgument("Name");
/// </code>
/// This will add the value "name" to the positional parameter list of "select-object"
/// cmdlet. When the command is invoked, this value will get bound to positional parameter 0

View File

@ -2801,7 +2801,7 @@ namespace System.Management.Automation.Language
{
if (!string.IsNullOrEmpty(scriptFileName) && !Path.IsPathRooted(assemblyFileName))
{
assemblyFileName = Path.GetDirectoryName(scriptFileName) + "\\" + assemblyFileName;
assemblyFileName = Path.Combine(Path.GetDirectoryName(scriptFileName), assemblyFileName);
}
if (File.Exists(assemblyFileName))

View File

@ -5133,7 +5133,7 @@ namespace System.Management.Automation.Language
workingDirectory = Path.GetDirectoryName(scriptFileName);
}
assemblyFileName = workingDirectory + @"\" + assemblyFileName;
assemblyFileName = Path.Combine(workingDirectory, assemblyFileName);
}
}
catch

View File

@ -8,6 +8,7 @@ using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.PowerShell;
using System.Management.Automation.Security;
@ -17,7 +18,7 @@ using Microsoft.PowerShell.DesiredStateConfiguration.Internal;
namespace System.Management.Automation.Language
{
internal sealed class SemanticChecks : AstVisitor2, IAstPostVisitHandler
internal sealed partial class SemanticChecks : AstVisitor2, IAstPostVisitHandler
{
private readonly Parser _parser;
@ -1319,20 +1320,50 @@ namespace System.Management.Automation.Language
public override AstVisitAction VisitUsingStatement(UsingStatementAst usingStatementAst)
{
bool usingKindSupported = usingStatementAst.UsingStatementKind == UsingStatementKind.Namespace ||
usingStatementAst.UsingStatementKind == UsingStatementKind.Assembly ||
usingStatementAst.UsingStatementKind == UsingStatementKind.Module;
if (!usingKindSupported ||
usingStatementAst.Alias != null)
UsingStatementKind kind = usingStatementAst.UsingStatementKind;
bool usingKindSupported = kind is UsingStatementKind.Namespace or UsingStatementKind.Assembly or UsingStatementKind.Module;
if (!usingKindSupported || usingStatementAst.Alias != null)
{
_parser.ReportError(usingStatementAst.Extent,
_parser.ReportError(
usingStatementAst.Extent,
nameof(ParserStrings.UsingStatementNotSupported),
ParserStrings.UsingStatementNotSupported);
}
if (kind is UsingStatementKind.Namespace)
{
Regex nsPattern = NamespacePattern();
if (!nsPattern.IsMatch(usingStatementAst.Name.Value))
{
_parser.ReportError(
usingStatementAst.Name.Extent,
nameof(ParserStrings.InvalidNamespaceValue),
ParserStrings.InvalidNamespaceValue);
}
}
return AstVisitAction.Continue;
}
/// <summary>
/// This regular expression is for validating if a namespace string is valid.
///
/// In C#, a legit namespace is defined as `identifier ('.' identifier)*` [see https://learn.microsoft.com/dotnet/csharp/language-reference/language-specification/namespaces#143-namespace-declarations].
/// And `identifier` is defined in https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/identifier-names#naming-rules, summarized below:
/// - Identifiers must start with a letter or underscore (_).
/// - Identifiers can contain
/// * Unicode letter characters (categories: Lu, Ll, Lt, Lm, Lo or Nl);
/// * decimal digit characters (category: Nd);
/// * Unicode connecting characters (category: Pc);
/// * Unicode combining characters (categories: Mn, Mc);
/// * Unicode formatting characters (category: Cf).
///
/// For details about how Unicode categories are represented in regular expression, see the "Unicode Categories" section in the following article:
/// - https://www.regular-expressions.info/unicode.html
/// </summary>
[GeneratedRegex(@"^[\p{L}\p{Nl}_][\p{L}\p{Nl}\p{Nd}\p{Pc}\p{Mn}\p{Mc}\p{Cf}_]*(?:\.[\p{L}\p{Nl}_][\p{L}\p{Nl}\p{Nd}\p{Pc}\p{Mn}\p{Mc}\p{Cf}_]*)*$")]
private static partial Regex NamespacePattern();
public override AstVisitAction VisitConfigurationDefinition(ConfigurationDefinitionAst configurationDefinitionAst)
{
//

View File

@ -46,7 +46,7 @@ namespace Microsoft.PowerShell.Commands
[OutputType(typeof(FileSecurity), typeof(DirectorySecurity), ProviderCmdlet = ProviderCmdlet.GetAcl)]
[OutputType(typeof(bool), typeof(string), typeof(FileInfo), typeof(DirectoryInfo), ProviderCmdlet = ProviderCmdlet.GetItem)]
[OutputType(typeof(bool), typeof(string), typeof(DateTime), typeof(System.IO.FileInfo), typeof(System.IO.DirectoryInfo), ProviderCmdlet = ProviderCmdlet.GetItemProperty)]
[OutputType(typeof(string), typeof(System.IO.FileInfo), ProviderCmdlet = ProviderCmdlet.NewItem)]
[OutputType(typeof(string), typeof(System.IO.FileInfo), typeof(DirectoryInfo), ProviderCmdlet = ProviderCmdlet.NewItem)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "This coupling is required")]
public sealed partial class FileSystemProvider : NavigationCmdletProvider,
IContentCmdletProvider,

View File

@ -1229,6 +1229,9 @@ ModuleVersion : Version of module to import. If used, ModuleName must represent
<data name="UsingStatementNotSupported" xml:space="preserve">
<value>This syntax of the 'using' statement is not supported.</value>
</data>
<data name="InvalidNamespaceValue" xml:space="preserve">
<value>The specified namespace in the 'using' statement contains invalid characters.</value>
</data>
<data name="InformationStream" xml:space="preserve">
<value>information stream</value>
</data>

View File

@ -43,6 +43,29 @@ enum LogKeyword
ManagedPlugin = 0x100
}
# mac log command can emit json, so just use that
# we need to deconstruct the eventmessage to get the event id
# we also need to filter out the non-default messages
function Get-MacOsSyslogItems {
param ([int]$processId, [string]$logId)
$logArgs = "show", "--process", "$processId", "--style", "json"
log $logArgs |
ConvertFrom-Json |
Where-Object { $_.category -eq "$logId" -and $_.messageType -eq "Default" } |
ForEach-Object {
$s = $_.eventMessage.IndexOf('[') + 1
$e = $_.EventMessage.IndexOf(']')
$l = $e - $s
if ($l -gt 0) {
$eventId = $_.eventMessage.SubString($s, $l)
}
else {
$eventId = "unknown"
}
$_ | Add-Member -MemberType NoteProperty -Name EventId -Value $eventId -PassThru
}
}
<#
.SYNOPSIS
Creates a powershell.config.json file with syslog settings
@ -317,26 +340,19 @@ Path:.*
}
}
It 'Verifies basic logging with no customizations' -Skip:(!$IsSupportedEnvironment) {
It 'Verifies basic logging with no customizations' -Skip:(!$IsMacOS) {
try {
$timeString = [DateTime]::Now.ToString('yyyy-MM-dd HH:mm:ss')
$configFile = WriteLogSettings -LogId $logId
copy-item $configFile /tmp/pwshtest.config.json
$testPid = & $powershell -NoProfile -SettingsFile $configFile -Command '$PID'
Export-PSOsLog -After $after -LogPid $testPid -TimeoutInMilliseconds 30000 -IntervalInMilliseconds 3000 -MinimumCount 3 |
Set-Content -Path $contentFile
$items = @(Get-PSOsLog -Path $contentFile -Id $logId -After $after -TotalCount 3 -Verbose)
$items = Get-MacOsSyslogItems -processId $testPid -logId $logId
$items | Should -Not -Be $null
$items.Count | Should -BeGreaterThan 2
$items[0].EventId | Should -BeExactly 'Perftrack_ConsoleStartupStart:PowershellConsoleStartup.WinStart.Informational'
$items[1].EventId | Should -BeExactly 'NamedPipeIPC_ServerListenerStarted:NamedPipe.Open.Informational'
$items[2].EventId | Should -BeExactly 'Perftrack_ConsoleStartupStop:PowershellConsoleStartup.WinStop.Informational'
# if there are more items than expected...
if ($items.Count -gt 3)
{
# Force reporting of the first unexpected item to help diagnosis
$items[3] | Should -Be $null
}
$items.EventId | Should -Contain 'Perftrack_ConsoleStartupStart:PowershellConsoleStartup.WinStart.Informational'
$items.EventId | Should -Contain 'NamedPipeIPC_ServerListenerStarted:NamedPipe.Open.Informational'
$items.EventId | Should -Contain 'Perftrack_ConsoleStartupStop:PowershellConsoleStartup.WinStop.Informational'
}
catch {
if (Test-Path $contentFile) {
@ -346,7 +362,7 @@ Path:.*
}
}
It 'Verifies scriptblock logging' -Skip:(!$IsSupportedEnvironment) {
It 'Verifies scriptblock logging' -Skip:(!$IsMacOS) {
try {
$script = @'
$PID
@ -357,24 +373,23 @@ $PID
$testScriptPath = Join-Path -Path $TestDrive -ChildPath $testFileName
$script | Out-File -FilePath $testScriptPath -Force
$testPid = & $powershell -NoProfile -SettingsFile $configFile -Command $testScriptPath
Export-PSOsLog -After $after -LogPid $testPid -TimeoutInMilliseconds 30000 -IntervalInMilliseconds 3000 -MinimumCount 17 |
Set-Content -Path $contentFile
$items = @(Get-PSOsLog -Path $contentFile -Id $logId -After $after -Verbose)
$items = Get-MacOsSyslogItems -processId $testPid -logId $logId
$items | Should -Not -Be $null
$items.Count | Should -BeGreaterThan 2
$createdEvents = $items | Where-Object {$_.EventId -eq 'ScriptBlock_Compile_Detail:ExecuteCommand.Create.Verbose'}
$createdEvents.Count | Should -BeGreaterOrEqual 3
$createdEvents | ConvertTo-Json | set-content /tmp/createdEvents.json
# Verify we log that we are executing a file
$createdEvents[0].Message | Should -Match ($scriptBlockCreatedRegExTemplate -f ".*/$testFileName")
$createdEvents[0].EventMessage | Should -Match $testFileName
# Verify we log that we are the script to create the scriptblock
$createdEvents[1].Message | Should -Match ($scriptBlockCreatedRegExTemplate -f (Get-RegEx -SimpleMatch $Script))
$createdEvents[1].EventMessage | Should -Match (Get-RegEx -SimpleMatch $Script)
# Verify we log that we are executing the created scriptblock
$createdEvents[2].Message | Should -Match ($scriptBlockCreatedRegExTemplate -f "Write\-Verbose 'testheader123' ;Write\-verbose 'after'")
$createdEvents[2].EventMessage | Should -Match "Write-Verbose 'testheader123' ;Write-verbose 'after'"
}
catch {
if (Test-Path $contentFile) {
@ -384,35 +399,28 @@ $PID
}
}
It 'Verifies scriptblock logging with null character' -Skip:(!$IsSupportedEnvironment) {
It 'Verifies scriptblock logging with null character' -Skip:(!$IsMacOS) {
try {
$script = @'
$PID
& ([scriptblock]::create("Write-Verbose 'testheader123$([char]0x0000)' ;Write-verbose 'after'"))
'@
$configFile = WriteLogSettings -ScriptBlockLogging -LogId $logId -LogLevel Verbose
$testFileName = 'test01.ps1'
$testFileName = 'test02.ps1'
$testScriptPath = Join-Path -Path $TestDrive -ChildPath $testFileName
$script | Out-File -FilePath $testScriptPath -Force
$testPid = & $powershell -NoProfile -SettingsFile $configFile -Command $testScriptPath
$testPid = & $powershell -NoProfile -SettingsFile $configFile -Command $testScriptPath | Select-Object -First 1
Export-PSOsLog -After $after -LogPid $testPid -TimeoutInMilliseconds 30000 -IntervalInMilliseconds 3000 -MinimumCount 17 |
Set-Content -Path $contentFile
$items = @(Get-PSOsLog -Path $contentFile -Id $logId -After $after -Verbose)
$items = Get-MacOsSyslogItems -processId $testPid -logId $logId
$items | convertto-json | set-content /tmp/items.json
$items | Should -Not -Be $null
$items.Count | Should -BeGreaterThan 2
$createdEvents = $items | Where-Object {$_.EventId -eq 'ScriptBlock_Compile_Detail:ExecuteCommand.Create.Verbose'}
$createdEvents.Count | Should -BeGreaterOrEqual 3
# Verify we log that we are executing a file
$createdEvents[0].Message | Should -Match ($scriptBlockCreatedRegExTemplate -f ".*/$testFileName")
$createdEvents[0].EventMessage | Should -Match $testFileName
# Verify we log that we are the script to create the scriptblock
$createdEvents[1].Message | Should -Match ($scriptBlockCreatedRegExTemplate -f (Get-RegEx -SimpleMatch $Script))
# Verify we log that we are executing the created scriptblock
$createdEvents[2].Message | Should -Match ($scriptBlockCreatedRegExTemplate -f "Write\-Verbose 'testheader123␀' ;Write\-verbose 'after'")
# Verify we log the null in the message
$createdEvents[1].EventMessage | Should -Match "Write-Verbose 'testheader123\`$\(\[char\]0x0000\)' ;Write-verbose 'after'"
}
catch {
if (Test-Path $contentFile) {
@ -422,25 +430,13 @@ $PID
}
}
# This is pending because it results in false postitives (-Skip:(!$IsSupportedEnvironment) )
It 'Verifies logging level filtering works' -Pending {
try {
$configFile = WriteLogSettings -LogId $logId -LogLevel Warning
$testPid = & $powershell -NoLogo -NoProfile -SettingsFile $configFile -Command '$PID'
# this is now specific to MacOS
It 'Verifies logging level filtering works' -skip:(!$IsMacOs) {
$configFile = WriteLogSettings -LogId $logId -LogLevel Warning
$testPid = & $powershell -NoLogo -NoProfile -SettingsFile $configFile -Command '$PID'
Export-PSOsLog -After $after -LogPid $testPid |
Set-Content -Path $contentFile
# by default, powershell startup should only logs informational events.
# With Level = Warning, nothing should be logged.
$items = Get-PSOsLog -Path $contentFile -Id $logId -After $after -TotalCount 3
$items | Should -Be $null
}
catch {
if (Test-Path $contentFile) {
Send-VstsLogFile -Path $contentFile
}
throw
}
$items = Get-MacOsSyslogItems -processId $testPid -logId $logId
$items | Should -Be $null -Because ("{0} Warning event logs were found" -f @($items).Count)
}
}

View File

@ -44,24 +44,15 @@ public class ABC {}
$err[0].ErrorId | Should -Be CannotLoadAssemblyWithUriSchema
}
It "parse does not load the assembly" -Pending {
It "parse does not load the assembly '<Script>'" -TestCases @{ Script = "using assembly UsingAssemblyTest$guid.dll"; Expected = $false },
@{ Script = "using assembly '$(Join-Path -Path $PSScriptRoot -ChildPath UsingAssemblyTest$guid.dll)'"; Expected = $false },
@{ Script = "using assembly `"$(Join-Path -Path $PSScriptRoot -ChildPath UsingAssemblyTest$guid.dll)`""; Expected = $false } {
param ($script)
$assemblies = [Appdomain]::CurrentDomain.GetAssemblies().GetName().Name
$assemblies -contains "UsingAssemblyTest$guid" | Should -BeFalse
$err = $null
$ast = [System.Management.Automation.Language.Parser]::ParseInput("using assembly .\UsingAssemblyTest$guid.dll", [ref]$null, [ref]$err)
$assemblies = [Appdomain]::CurrentDomain.GetAssemblies().GetName().Name
$assemblies -contains "UsingAssemblyTest$guid" | Should -BeFalse
$err.Count | Should -Be 0
$ast = [System.Management.Automation.Language.Parser]::ParseInput("using assembly '$PSScriptRoot\UsingAssemblyTest$guid.dll'", [ref]$null, [ref]$err)
$assemblies = [Appdomain]::CurrentDomain.GetAssemblies().GetName().Name
$assemblies -contains "UsingAssemblyTest$guid" | Should -BeFalse
$err.Count | Should -Be 0
$ast = [System.Management.Automation.Language.Parser]::ParseInput("using assembly `"$PSScriptRoot\UsingAssemblyTest$guid.dll`"", [ref]$null, [ref]$err)
$ast = [System.Management.Automation.Language.Parser]::ParseInput($script, [ref]$null, [ref]$err)
$assemblies = [Appdomain]::CurrentDomain.GetAssemblies().GetName().Name
$assemblies -contains "UsingAssemblyTest$guid" | Should -BeFalse
@ -69,39 +60,42 @@ public class ABC {}
}
It "reports runtime error about non-existing assembly with relative path" {
$e = { [scriptblock]::Create("using assembly .\NonExistingAssembly.dll") } | Should -Throw -ErrorId 'ParseException' -PassThru
$script = "using assembly {0}" -f (Join-Path "." "NonExistingAssembly.dll")
$e = { [scriptblock]::Create($script) } | Should -Throw -ErrorId 'ParseException' -PassThru
$e.Exception.InnerException.ErrorRecord.FullyQualifiedErrorId | Should -Be 'ErrorLoadingAssembly'
}
#>
It "Assembly loaded at runtime" -Pending {
$assemblies = & "$PSHOME/pwsh" -noprofile -command @"
using assembly .\UsingAssemblyTest$guid.dll
[Appdomain]::CurrentDomain.GetAssemblies().GetName().Name
"@
$assemblies -contains "UsingAssemblyTest$guid" | Should -BeTrue
Context "Runtime loading of assemblies" {
BeforeAll {
copy-item "UsingAssemblyTest$guid.dll" $TestDrive
$assemblyPath = Join-Path $TestDrive "UsingAssemblyTest$guid.dll"
$assemblies = & "$PSHOME/pwsh" -noprofile -command @"
using assembly $PSScriptRoot\UsingAssemblyTest$guid.dll
[Appdomain]::CurrentDomain.GetAssemblies().GetName().Name
"@
$assemblies -contains "UsingAssemblyTest$guid" | Should -BeTrue
function InvokeScript ([string]$pathToScript) {
$result = & "$PSHOME/pwsh" -noprofile -file $pathToScript
return $result
}
}
$assemblies = & "$PSHOME/pwsh" -noprofile -command @"
using assembly System.Drawing
[Appdomain]::CurrentDomain.GetAssemblies().GetName().Name
"@
$assemblies -contains "System.Drawing" | Should -BeTrue
It "Assembly loaded at runtime" {
$testFile = Join-Path $TestDrive "TestFile1.ps1"
$script = "using assembly UsingAssemblyTest$guid.dll`n[ABC].Assembly.Location"
Set-Content -Path $testFile -Value $script
$assembly = InvokeScript $testFile
$assembly | Should -Be $assemblyPath
}
$assemblies = & "$PSHOME/pwsh" -noprofile -command @"
using assembly 'System.Drawing, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
[Appdomain]::CurrentDomain.GetAssemblies().GetName().Name
"@
$assemblies -contains "System.Drawing" | Should -BeTrue
It "Assembly loaded at runtime with fully qualified name" {
$script = "using assembly $assemblyPath`n[ABC].Assembly.Location"
$testFile = Join-Path $TestDrive "TestFile2.ps1"
Set-Content -Path $testFile -Value $script
$assembly = InvokeScript $testFile
$assembly | Should -Be $assemblyPath
}
}
}
finally
{
Remove-Item .\UsingAssemblyTest$guid.dll
Remove-Item -ErrorAction Ignore .\UsingAssemblyTest$guid.dll
Pop-Location
}
}

View File

@ -128,7 +128,10 @@ Describe "Using Namespace" -Tags "CI" {
ShouldBeParseError "1; using namespace System" UsingMustBeAtStartOfScript 3
ShouldBeParseError "using namespace Foo = System" UsingStatementNotSupported 0
ShouldBeParseError "using namespace ''" InvalidNamespaceValue 16
ShouldBeParseError "using namespace [System]" InvalidNamespaceValue 16
ShouldBeParseError "using namespace ',System'" InvalidNamespaceValue 16
ShouldBeParseError "using namespace ']System'" InvalidNamespaceValue 16
# TODO: add diagnostic (low pri)
# ShouldBeParseError "using namespace System; using namespace System" UsingNamespaceAlreadySpecified 24
}

View File

@ -438,7 +438,8 @@ class PSLogItem
if($item.LogId -notmatch '^\[com\.microsoft\.powershell')
{
Write-Verbose "Skipping logId: $($item.LogId)" -Verbose
# this is really a lot of output, so we'll skip it for now.
# Write-Verbose "Skipping logId: $($item.LogId)" -Verbose
$result = $null
break
}

View File

@ -1,4 +1,5 @@
{
"$schema": "https://json.schemastore.org/component-detection-manifest.json",
"Registrations": [
{
"Component": {
@ -435,7 +436,7 @@
"Type": "nuget",
"Nuget": {
"Name": "System.Data.SqlClient",
"Version": "4.8.5"
"Version": "4.8.6"
}
},
"DevelopmentDependency": false
@ -505,7 +506,7 @@
"Type": "nuget",
"Nuget": {
"Name": "System.Drawing.Common",
"Version": "8.0.0"
"Version": "8.0.1"
}
},
"DevelopmentDependency": false
@ -830,6 +831,5 @@
},
"DevelopmentDependency": false
}
],
"$schema": "https://json.schemastore.org/component-detection-manifest.json"
]
}

View File

@ -541,9 +541,11 @@ function Invoke-CIFinish
}
'win-arm.*' {
$runPackageTest = $false
$packageTypes = 'zip', 'zip-pdb', 'msix'
$packageTypes = 'msi', 'zip', 'zip-pdb', 'msix'
}
}
Install-WixArmZip
$packages = Start-PSPackage -Type $packageTypes -ReleaseTag $preReleaseVersion -SkipReleaseChecks -WindowsRuntime $Runtime
foreach ($package in $packages) {
@ -620,6 +622,62 @@ function Invoke-CIFinish
}
}
function Install-WixArmZip
{
# cleanup previous install
if((Test-Path "${env:ProgramFiles(x86)}\Arm Support WiX Toolset xcopy")) {
Remove-Item "${env:ProgramFiles(x86)}\Arm Support WiX Toolset xcopy" -Recurse -Force
}
# This URI is for wix 3.14 which supports generating msi for arm architecures.
$wixUriArmSupport = 'https://aka.ms/ps-wix-3-14-zip'
$zipArmSupport = "$env:TEMP\wixArmSupport.zip"
$targetRoot = "${env:ProgramFiles(x86)}\Arm Support WiX Toolset xcopy"
Invoke-RestMethod -Uri $wixUriArmSupport -OutFile $zipArmSupport
$binPath = Join-Path -Path $targetRoot -ChildPath 'bin'
Write-Verbose "Expanding $zipArmSupport to $binPath ..." -Verbose
Expand-Archive -Path $zipArmSupport -DestinationPath $binPath -Force
$docExpandPath = Join-Path -Path $binPath -ChildPath 'doc'
$sdkExpandPath = Join-Path -Path $binPath -ChildPath 'sdk'
$docTargetPath = Join-Path -Path $targetRoot -ChildPath 'doc'
$sdkTargetPath = Join-Path -Path $targetRoot -ChildPath 'sdk'
Write-Verbose "Fixing folder structure ..." -Verbose
Move-Item -Path $docExpandPath -Destination $docTargetPath
Move-Item -Path $sdkExpandPath -Destination $sdkTargetPath
Set-Path -Append -Path $binPath
Write-Verbose "Done installing WIX for arm!"
}
function Set-Path
{
param
(
[Parameter(Mandatory)]
[string]
$Path,
[Parameter(Mandatory)]
[switch]
$Append
)
$machinePathString = [System.Environment]::GetEnvironmentVariable('path',[System.EnvironmentVariableTarget]::Machine)
$machinePath = $machinePathString -split ';'
if($machinePath -inotcontains $path)
{
$newPath = "$machinePathString;$path"
Write-Verbose "Adding $path to path..." -Verbose
[System.Environment]::SetEnvironmentVariable('path',$newPath,[System.EnvironmentVariableTarget]::Machine)
Write-Verbose "Added $path to path." -Verbose
}
else
{
Write-Verbose "$path already in path." -Verbose
}
}
# Bootstrap script for Linux and macOS
function Invoke-BootstrapStage
{

View File

@ -477,6 +477,12 @@ function Start-PSPackage {
$TargetArchitecture = "x86"
$r2rArchitecture = "i386"
}
elseif ($Runtime -match "-arm64")
{
$TargetArchitecture = "arm64"
$r2rArchitecture = "arm64"
}
Write-Verbose "TargetArchitecture = $TargetArchitecture" -Verbose
$Arguments = @{
@ -3206,12 +3212,23 @@ function Get-NugetSemanticVersion
# Get the paths to various WiX tools
function Get-WixPath
{
$wixToolsetBinPath = "${env:ProgramFiles(x86)}\WiX Toolset *\bin"
[CmdletBinding()]
param (
[bool] $IsProductArchitectureArm = $false
)
Write-Verbose "Ensure Wix Toolset is present on the machine @ $wixToolsetBinPath"
$wixToolsetBinPath = $IsProductArchitectureArm ? "${env:ProgramFiles(x86)}\Arm Support WiX Toolset *\bin" : "${env:ProgramFiles(x86)}\WiX Toolset *\bin"
Write-Verbose -Verbose "Ensure Wix Toolset is present on the machine @ $wixToolsetBinPath"
if (-not (Test-Path $wixToolsetBinPath))
{
throw "The latest version of Wix Toolset 3.11 is required to create MSI package. Please install it from https://github.com/wixtoolset/wix3/releases"
if (!$IsProductArchitectureArm)
{
throw "The latest version of Wix Toolset 3.11 is required to create MSI package. Please install it from https://github.com/wixtoolset/wix3/releases"
}
else {
throw "The latest version of Wix Toolset 3.14 is required to create MSI package for arm. Please install it from https://aka.ms/ps-wix-3-14-zip"
}
}
## Get the latest if multiple versions exist.
@ -3235,7 +3252,6 @@ function Get-WixPath
WixLightExePath = $wixLightExePath
WixInsigniaExePath = $wixInsigniaExePath
}
}
<#
@ -3287,7 +3303,7 @@ function New-MSIPackage
# Architecture to use when creating the MSI
[Parameter(Mandatory = $true)]
[ValidateSet("x86", "x64")]
[ValidateSet("x86", "x64", "arm64")]
[ValidateNotNullOrEmpty()]
[string] $ProductTargetArchitecture,
@ -3297,7 +3313,7 @@ function New-MSIPackage
[string] $CurrentLocation = (Get-Location)
)
$wixPaths = Get-WixPath
$wixPaths = Get-WixPath -IsProductArchitectureArm ($ProductTargetArchitecture -eq "arm64")
$windowsNames = Get-WindowsNames -ProductName $ProductName -ProductNameSuffix $ProductNameSuffix -ProductVersion $ProductVersion
$productSemanticVersionWithName = $windowsNames.ProductSemanticVersionWithName
@ -3335,6 +3351,11 @@ function New-MSIPackage
$fileArchitecture = 'x86'
$ProductProgFilesDir = "ProgramFilesFolder"
}
elseif ($ProductTargetArchitecture -eq "arm64")
{
$fileArchitecture = 'arm64'
$ProductProgFilesDir = "ProgramFiles64Folder"
}
$wixFragmentPath = Join-Path $env:Temp "Fragment.wxs"
@ -3449,7 +3470,7 @@ function New-ExePackage {
# Architecture to use when creating the MSI
[Parameter(Mandatory = $true)]
[ValidateSet("x86", "x64")]
[ValidateSet("x86", "x64", "arm64")]
[ValidateNotNullOrEmpty()]
[string] $ProductTargetArchitecture,
@ -3571,7 +3592,7 @@ function Start-MsiBuild {
$outDir = $env:Temp
$wixPaths = Get-WixPath
$wixPaths = Get-WixPath -IsProductArchitectureArm ($ProductTargetArchitecture -eq "arm64")
$extensionArgs = @()
foreach ($extensionName in $Extension) {

View File

@ -153,11 +153,8 @@ try
if (!$Symbols -and $Runtime -notlike 'fxdependent*' -and !$ForMinimalSize)
{
if ($Runtime -notmatch 'arm')
{
Write-Verbose "Starting powershell packaging(msi)..." -Verbose
Start-PSPackage @pspackageParams @releaseTagParam
}
Write-Verbose "Starting powershell packaging(msi)..." -Verbose
Start-PSPackage @pspackageParams @releaseTagParam
$pspackageParams['Type']='msix'
Write-Verbose "Starting powershell packaging(msix)..." -Verbose

View File

@ -99,7 +99,7 @@ jobs:
parameters:
architecture: arm64
version: $(version)
msi: no
msi: yes
- template: upload.yml
parameters:

View File

@ -270,7 +270,7 @@ jobs:
displayName: Upload unsigned packages
retryCountOnTaskFailure: 2
- ${{ if and(ne(variables['BuildConfiguration'],'minSize'), in(variables['Architecture'], 'x64', 'x86')) }}:
- ${{ if and(ne(variables['BuildConfiguration'],'minSize'), in(variables['Architecture'], 'x64', 'x86', 'arm64')) }}:
- template: EsrpSign.yml@ComplianceRepo
parameters:
buildOutputPath: $(System.ArtifactsDirectory)\pkgSigned