Skip to content
Merged
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
49 changes: 42 additions & 7 deletions src/System.Management.Automation/engine/NativeCommandProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
using System.Collections;
using System.Threading;
using System.Management.Automation.Internal;
using System.Management.Automation.Runspaces;
using System.Xml;
using System.Runtime.InteropServices;
using Dbg = System.Management.Automation.Diagnostics;
Expand Down Expand Up @@ -222,6 +221,29 @@ private string Path
}
}

/// <summary>
/// Gets true if Path is Console Application.
/// </summary>
private bool IsConsoleApplication => !IsWindowsApplication;

/// <summary>
/// Gets true if Path is Windows Application.
/// </summary>
private bool IsWindowsApplication
{
get
{
if (!_isWindowsApplication.HasValue)
{
_isWindowsApplication = CheckIfWindowsApplication(Path);
}

return _isWindowsApplication.Value;
}
}

private bool? _isWindowsApplication;

#endregion ctor/native command properties

#region parameter binder
Expand Down Expand Up @@ -476,7 +498,7 @@ private void InitNativeProcess()
bool notDone = true;
if (!string.IsNullOrEmpty(executable))
{
if (IsConsoleApplication(executable))
if (CheckIfConsoleApplication(executable))
{
// Allocate a console if there isn't one attached already...
ConsoleVisibility.AllocateHiddenConsole();
Expand Down Expand Up @@ -532,7 +554,7 @@ private void InitNativeProcess()
_isRunningInBackground = true;
if (startInfo.UseShellExecute == false)
{
_isRunningInBackground = IsWindowsApplication(_nativeProcess.StartInfo.FileName);
_isRunningInBackground = IsWindowsApplication;
}
}

Expand Down Expand Up @@ -935,9 +957,9 @@ private static void KillChildProcesses(int parentId, ProcessWithParentId[] curre
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
private static bool IsConsoleApplication(string fileName)
private static bool CheckIfConsoleApplication(string fileName)
{
return !IsWindowsApplication(fileName);
return !CheckIfWindowsApplication(fileName);
}

/// <summary>
Expand All @@ -946,10 +968,22 @@ private static bool IsConsoleApplication(string fileName)
/// <param name="fileName"></param>
/// <returns></returns>
[ArchitectureSensitive]
private static bool IsWindowsApplication(string fileName)
private static bool CheckIfWindowsApplication(string fileName)
{
#if UNIX
return false;
#else
if (!Platform.IsWindowsDesktop) { return false; }

// SHGetFileInfo() does not understand reparse points and returns 0 ("non exe or error")
// so we are trying to get a real path before.
// It is a workaround for Microsoft Store applications.
string realPath = Microsoft.PowerShell.Commands.InternalSymbolicLinkLinkCodeMethods.WinInternalGetTarget(fileName);
if (realPath is not null)
{
fileName = realPath;
}

SHFILEINFO shinfo = new SHFILEINFO();
IntPtr type = SHGetFileInfo(fileName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_EXETYPE);

Expand All @@ -968,6 +1002,7 @@ private static bool IsWindowsApplication(string fileName)
// anything else - is a windows program...
return true;
}
#endif
}

#endregion checkForConsoleApplication
Expand Down Expand Up @@ -1266,7 +1301,7 @@ private void CalculateIORedirection(out bool redirectOutput, out bool redirectEr
redirectOutput = true;
redirectError = true;
}
else if (Platform.IsWindowsDesktop && IsConsoleApplication(this.Path))
else if (Platform.IsWindowsDesktop && IsConsoleApplication)
{
// On Windows desktops, if the command to run is a console application,
// then allocate a console if there isn't one attached already...
Expand Down
25 changes: 15 additions & 10 deletions src/System.Management.Automation/namespaces/FileSystemProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8073,16 +8073,7 @@ public static string GetTarget(PSObject instance)
if (instance.BaseObject is FileSystemInfo fileSysInfo)
{
#if !UNIX
// We set accessMode parameter to zero because documentation says:
// If this parameter is zero, the application can query certain metadata
// such as file, directory, or device attributes without accessing
// that file or device, even if GENERIC_READ access would have been denied.
using (SafeFileHandle handle = OpenReparsePoint(fileSysInfo.FullName, FileDesiredAccess.GenericZero))
{
string linkTarget = WinInternalGetTarget(handle);

return linkTarget;
}
return WinInternalGetTarget(fileSysInfo.FullName);
#else
return UnixInternalGetTarget(fileSysInfo.FullName);
#endif
Expand Down Expand Up @@ -8382,6 +8373,19 @@ internal static bool WinIsHardLink(ref IntPtr handle)
return succeeded && (handleInfo.NumberOfLinks > 1);
}

#if !UNIX
internal static string WinInternalGetTarget(string path)
{
// We set accessMode parameter to zero because documentation says:
// If this parameter is zero, the application can query certain metadata
// such as file, directory, or device attributes without accessing
// that file or device, even if GENERIC_READ access would have been denied.
using (SafeFileHandle handle = OpenReparsePoint(path, FileDesiredAccess.GenericZero))
{
return WinInternalGetTarget(handle);
}
}

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")]
private static string WinInternalGetTarget(SafeFileHandle handle)
{
Expand Down Expand Up @@ -8456,6 +8460,7 @@ private static string WinInternalGetTarget(SafeFileHandle handle)
Marshal.FreeHGlobal(outBuffer);
}
}
#endif

internal static bool CreateJunction(string path, string target)
{
Expand Down