Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1841,7 +1841,7 @@ private void DoRunspaceInitialization(bool skipProfiles, string initialCommand,
if (!Path.GetExtension(filePath).Equals(".ps1", StringComparison.OrdinalIgnoreCase))
{
string script = File.ReadAllText(filePath);
c = new Command(script, isScript: true, useLocalScope: false);
c = new Command(script, scriptPath: filePath, useLocalScope: false);
}
else
{
Expand Down
53 changes: 39 additions & 14 deletions src/System.Management.Automation/engine/hostifaces/Command.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Management.Automation.Internal;

using Microsoft.Management.Infrastructure;
Expand All @@ -25,7 +26,7 @@ public sealed class Command
/// <param name="command">Name of the command or script contents.</param>
/// <exception cref="ArgumentNullException">Command is null.</exception>
public Command(string command)
: this(command, false, null)
: this(command, isScript: false, useLocalScope: null)
{
}

Expand Down Expand Up @@ -73,6 +74,12 @@ internal Command(string command, bool isScript, bool? useLocalScope)
_useLocalScope = useLocalScope;
}

internal Command(string script, string scriptPath, bool? useLocalScope)
: this(script, isScript: true, useLocalScope)
{
ScriptPath = scriptPath;
}

internal Command(string command, bool isScript, bool? useLocalScope, bool mergeUnclaimedPreviousErrorResults)
: this(command, isScript, useLocalScope)
{
Expand All @@ -83,7 +90,7 @@ internal Command(string command, bool isScript, bool? useLocalScope, bool mergeU
}

internal Command(CommandInfo commandInfo)
: this(commandInfo, false)
: this(commandInfo, isScript: false)
{
}

Expand Down Expand Up @@ -129,24 +136,29 @@ internal Command(Command command)
public CommandParameterCollection Parameters { get; } = new CommandParameterCollection();

/// <summary>
/// Access the command string.
/// Gets the command string.
/// </summary>
/// <value>The command name, if <see cref="Command.IsScript"/> is false; otherwise; the script contents</value>
public string CommandText { get; } = string.Empty;

/// <summary>
/// Access the commandInfo.
/// Gets the commandInfo.
/// </summary>
/// <value>The command info object</value>
internal CommandInfo CommandInfo { get; }

/// <summary>
/// Access the value indicating if this <see cref="Command"/> represents a script.
/// Gets the value indicating if this <see cref="Command"/> represents a script.
/// </summary>
public bool IsScript { get; }

/// <summary>
/// Gets path to the script file if this <see cref="Command"/> represents a script loaded from file.
/// </summary>
public string ScriptPath { get; }

/// <summary>
/// Access the value indicating if LocalScope is to be used for running
/// Gets the value indicating if LocalScope is to be used for running
/// this script command.
/// </summary>
/// <value>True if this command is a script and localScope is
Expand All @@ -165,7 +177,7 @@ public bool UseLocalScope
public CommandOrigin CommandOrigin { get; set; } = CommandOrigin.Runspace;

/// <summary>
/// Access the actual value indicating if LocalScope is to be used for running
/// Gets the actual value indicating if LocalScope is to be used for running
/// this script command. Needed for serialization in remoting.
/// </summary>
internal bool? UseLocalScopeNullable
Expand Down Expand Up @@ -466,7 +478,7 @@ CommandOrigin origin
null, "ScriptsNotAllowed", ParserStrings.ScriptsNotAllowed);
}

ScriptBlock scriptBlock = executionContext.Engine.ParseScriptBlock(CommandText, addToHistory);
ScriptBlock scriptBlock = executionContext.Engine.ParseScriptBlock(CommandText, ScriptPath, addToHistory);
if (origin == Automation.CommandOrigin.Internal)
{
scriptBlock.LanguageMode = PSLanguageMode.FullLanguage;
Expand Down Expand Up @@ -497,13 +509,27 @@ CommandOrigin origin
commandProcessorBase = new CommandProcessor(functionInfo, executionContext,
_useLocalScope ?? false, fromScriptFile: false, sessionState: executionContext.EngineSessionState);
}
else if (ScriptPath != null)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
else if (ScriptPath != null)
else if (ScriptPath is not null)

{
var scriptName = Path.GetFileName(ScriptPath);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script (content of the file) could be using cmdlet binding (scriptBlock.UsesCmdletBinding being true), by having a param block defined. In that case, the code execution would fall into the if (scriptBlock.UsesCmdletBinding) block, right?

var scriptInfo = new ExternalScriptInfo(scriptName, ScriptPath, executionContext);
commandProcessorBase = new DlrScriptCommandProcessor(
scriptInfo,
executionContext,
_useLocalScope ?? false,
executionContext.EngineSessionState);

commandProcessorBase.Command.MyInvocation.InvocationName = ScriptPath;
}
else
{
commandProcessorBase = new DlrScriptCommandProcessor(scriptBlock,
executionContext, _useLocalScope ?? false,
origin,
executionContext.EngineSessionState,
DollarUnderbar);
commandProcessorBase = new DlrScriptCommandProcessor(
scriptBlock,
executionContext,
_useLocalScope ?? false,
origin,
executionContext.EngineSessionState,
DollarUnderbar);
}
}
else
Expand Down Expand Up @@ -899,4 +925,3 @@ internal string GetCommandStringForHistory()
}
}
}

33 changes: 33 additions & 0 deletions test/powershell/Host/ConsoleHost.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,39 @@ Describe "ConsoleHost unit tests" -tags "Feature" {
& $powershell -noprofile -c ' ' | Should -BeNullOrEmpty
$LASTEXITCODE | Should -Be 0
}

It "MyInvocation.MyCommand.Name should contain script file name when executing script with -File argument" -TestCases @(
@{Filename = "test.ps1"},
@{Filename = "test-no-ext"}
) {
param($Filename)
$testFilePath = Join-Path $testdrive $Filename
Set-Content -Path $testFilePath -Value '$MyInvocation.MyCommand.Name'
$observed = & $powershell -File $testFilePath -NoProfile -NoLogo
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was an intentional breaking change in PowerShell 7.2 related to powershell -File: when running on Windows, a file without .ps1 extension is not allowed to run using pwsh -File. So, the test won't work on Windows.

$observed | Should -Be $Filename
}

It "MyInvocation.InvocationName should contain script file path when executing script with -File argument" -TestCases @(
@{Filename = "test.ps1"},
@{Filename = "test-no-ext"}
) {
param($Filename)
$testFilePath = Join-Path $testdrive $Filename
Set-Content -Path $testFilePath -Value '$MyInvocation.InvocationName'
$observed = & $powershell -File $testFilePath -NoProfile -NoLogo
$observed | Should -Be $testFilePath
}

It "PSScriptRoot should contain script directory path when executing script with -File argument" -TestCases @(
@{Filename = "test.ps1"},
@{Filename = "test-no-ext"}
) {
param($Filename)
$testFilePath = Join-Path $testdrive $Filename
Set-Content -Path $testFilePath -Value '$PSScriptRoot'
$observed = & $powershell -File $testFilePath -NoProfile -NoLogo
$observed | Should -Be ( Split-Path $testFilePath )
}
}

Context "-Login pwsh switch" {
Expand Down