Removing Hardlink from Mode property in default file system format (#8789)

This commit is contained in:
Staffan Gustafsson 2019-03-12 23:49:16 +01:00 committed by Aditya Patwardhan
parent 1e49d09d29
commit 9983297254
8 changed files with 207 additions and 143 deletions

View File

@ -42,28 +42,33 @@ namespace System.Management.Automation.Runspaces
private static IEnumerable<FormatViewDefinition> ViewsOf_FileSystemTypes(CustomControl[] sharedControls)
{
const string LengthScriptBlock =
@"if ($_ -is [System.IO.DirectoryInfo]) { return '' }
if ($_.Attributes -band [System.IO.FileAttributes]::Offline)
{
return '({0})' -f $_.Length
}
return $_.Length";
yield return new FormatViewDefinition("children",
TableControl.Create()
.GroupByProperty("PSParentPath", customControl: sharedControls[0])
.AddHeader(Alignment.Left, label: "Mode", width: 7)
.AddHeader(Alignment.Right, label: "LastWriteTime", width: 25)
.AddHeader(Alignment.Right, label: "Length", width: 14)
.AddHeader()
.AddHeader(Alignment.Left, label: "Name")
.StartRowDefinition(wrap: true)
.AddPropertyColumn("ModeWithoutHardLink")
.AddPropertyColumn("LastWriteTimeString")
.AddPropertyColumn("LengthString")
.AddPropertyColumn("NameString")
.EndRowDefinition()
.EndTable());
yield return new FormatViewDefinition("childrenWithHardlink",
TableControl.Create()
.GroupByProperty("PSParentPath", customControl: sharedControls[0])
.AddHeader(Alignment.Left, label: "Mode", width: 7)
.AddHeader(Alignment.Right, label: "LastWriteTime", width: 25)
.AddHeader(Alignment.Right, label: "Length", width: 14)
.AddHeader(Alignment.Left, label: "Name")
.StartRowDefinition(wrap: true)
.AddPropertyColumn("Mode")
.AddScriptBlockColumn(@"
[String]::Format(""{0,10} {1,8}"", $_.LastWriteTime.ToString(""d""), $_.LastWriteTime.ToString(""t""))
")
.AddScriptBlockColumn(LengthScriptBlock)
.AddPropertyColumn("Name")
.AddPropertyColumn("LastWriteTimeString")
.AddPropertyColumn("LengthString")
.AddPropertyColumn("NameString")
.EndRowDefinition()
.EndTable());
@ -72,7 +77,7 @@ return $_.Length";
.GroupByProperty("PSParentPath", customControl: sharedControls[0])
.StartEntry(entrySelectedByType: new[] { "System.IO.FileInfo" })
.AddItemProperty(@"Name")
.AddItemScriptBlock(LengthScriptBlock, label: "Length")
.AddItemProperty("LengthString", label: "Length")
.AddItemProperty(@"CreationTime")
.AddItemProperty(@"LastWriteTime")
.AddItemProperty(@"LastAccessTime")

View File

@ -183,18 +183,28 @@ namespace System.Management.Automation.Runspaces
var td19 = new TypeData(@"System.IO.DirectoryInfo", true);
td19.Members.Add("Mode",
new CodePropertyData("Mode", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "Mode"), null));
td19.Members.Add("ModeWithoutHardLink",
new CodePropertyData("ModeWithoutHardLink", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "ModeWithoutHardLink"), null));
td19.Members.Add("BaseName",
new ScriptPropertyData(@"BaseName", GetScriptBlock(@"$this.Name"), null));
td19.Members.Add("Target",
new CodePropertyData("Target", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.InternalSymbolicLinkLinkCodeMethods), "GetTarget"), null));
td19.Members.Add("LinkType",
new CodePropertyData("LinkType", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.InternalSymbolicLinkLinkCodeMethods), "GetLinkType"), null));
td19.Members.Add("NameString",
new CodePropertyData("NameString", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "NameString"), null) { IsHidden = true });
td19.Members.Add("LengthString",
new CodePropertyData("LengthString", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "LengthString"), null) { IsHidden = true });
td19.Members.Add("LastWriteTimeString",
new CodePropertyData("LastWriteTimeString", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "LastWriteTimeString"), null) { IsHidden = true });
td19.DefaultDisplayProperty = @"Name";
yield return td19;
var td20 = new TypeData(@"System.IO.FileInfo", true);
td20.Members.Add("Mode",
new CodePropertyData("Mode", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "Mode"), null));
td20.Members.Add("ModeWithoutHardLink",
new CodePropertyData("ModeWithoutHardLink", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "ModeWithoutHardLink"), null));
td20.Members.Add("VersionInfo",
new ScriptPropertyData(@"VersionInfo", GetScriptBlock(@"[System.Diagnostics.FileVersionInfo]::GetVersionInfo($this.FullName)"), null));
td20.Members.Add("BaseName",
@ -203,6 +213,12 @@ namespace System.Management.Automation.Runspaces
new CodePropertyData("Target", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.InternalSymbolicLinkLinkCodeMethods), "GetTarget"), null));
td20.Members.Add("LinkType",
new CodePropertyData("LinkType", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.InternalSymbolicLinkLinkCodeMethods), "GetLinkType"), null));
td20.Members.Add("NameString",
new CodePropertyData("NameString", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "NameString"), null) { IsHidden = true });
td20.Members.Add("LengthString",
new CodePropertyData("LengthString", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "LengthString"), null) { IsHidden = true });
td20.Members.Add("LastWriteTimeString",
new CodePropertyData("LastWriteTimeString", GetMethodInfo(typeof(Microsoft.PowerShell.Commands.FileSystemProvider), "LastWriteTimeString"), null) { IsHidden = true });
td20.DefaultDisplayPropertySet =
new PropertySetData(new[] { "LastWriteTime", "Length", "Name" }) { Name = "DefaultDisplayPropertySet" };
yield return td20;

View File

@ -1867,33 +1867,99 @@ namespace Microsoft.PowerShell.Commands
/// Provides a mode property for FileSystemInfo.
/// </summary>
/// <param name="instance">Instance of PSObject wrapping a FileSystemInfo.</param>
/// <returns>A string representation of the FileAttributes, with one letter per attribute.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")]
public static string Mode(PSObject instance)
public static string Mode(PSObject instance) => Mode(instance, excludeHardLink: false);
/// <summary>
/// Provides a ModeWithoutHardLink property for FileSystemInfo, without HardLinks for performance reasons.
/// </summary>
/// <param name="instance">Instance of PSObject wrapping a FileSystemInfo.</param>
/// <returns>A string representation of the FileAttributes, with one letter per attribute.</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods")]
public static string ModeWithoutHardLink(PSObject instance) => Mode(instance, excludeHardLink: true);
private static string Mode(PSObject instance, bool excludeHardLink)
{
if (instance == null)
string ToModeString(FileSystemInfo fileSystemInfo)
{
return string.Empty;
FileAttributes fileAttributes = fileSystemInfo.Attributes;
bool isReparsePoint = InternalSymbolicLinkLinkCodeMethods.IsReparsePoint(fileSystemInfo);
bool isLink = isReparsePoint || (excludeHardLink ? false : InternalSymbolicLinkLinkCodeMethods.IsHardLink(fileSystemInfo));
if (!isLink)
{
// special casing for the common cases - no allocations
switch (fileAttributes)
{
case FileAttributes.Archive:
return "-a---";
case FileAttributes.Directory:
return "d----";
case FileAttributes.Normal:
return "-----";
case FileAttributes.Directory | FileAttributes.ReadOnly:
return "d-r--";
case FileAttributes.Archive | FileAttributes.ReadOnly:
return "-ar--";
}
}
bool isDirectory = fileAttributes.HasFlag(FileAttributes.Directory);
ReadOnlySpan<char> mode = stackalloc char[]
{
isLink ? 'l' : isDirectory ? 'd' : '-',
fileAttributes.HasFlag(FileAttributes.Archive) ? 'a' : '-',
fileAttributes.HasFlag(FileAttributes.ReadOnly) ? 'r' : '-',
fileAttributes.HasFlag(FileAttributes.Hidden) ? 'h' : '-',
fileAttributes.HasFlag(FileAttributes.System) ? 's' : '-',
};
return new string(mode);
}
FileSystemInfo fileInfo = (FileSystemInfo)instance.BaseObject;
if (fileInfo == null)
{
return string.Empty;
}
return instance?.BaseObject is FileSystemInfo fileInfo
? ToModeString(fileInfo)
: string.Empty;
}
char[] mode = new char[6];
mode[0] = (fileInfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory ? 'd' : '-';
mode[1] = (fileInfo.Attributes & FileAttributes.Archive) == FileAttributes.Archive ? 'a' : '-';
mode[2] = (fileInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly ? 'r' : '-';
mode[3] = (fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden ? 'h' : '-';
mode[4] = (fileInfo.Attributes & FileAttributes.System) == FileAttributes.System ? 's' : '-';
// Mark the last bit as a "l" if it's a reparsepoint (symbolic link or junction)
// Porting note: these need to be handled specially
bool isReparsePoint = InternalSymbolicLinkLinkCodeMethods.IsReparsePoint(fileInfo);
bool isHardLink = InternalSymbolicLinkLinkCodeMethods.IsHardLink(fileInfo);
mode[5] = isReparsePoint || isHardLink ? 'l' : '-';
/// <summary>
/// Provides a NameString property for FileSystemInfo.
/// </summary>
/// <param name="instance">Instance of PSObject wrapping a FileSystemInfo.</param>
/// <returns>Name if a file or directory, Name -> Target if symlink.</returns>
public static string NameString(PSObject instance)
{
return instance?.BaseObject is FileSystemInfo fileInfo
? InternalSymbolicLinkLinkCodeMethods.IsReparsePoint(fileInfo)
? $"{fileInfo.Name} -> {InternalSymbolicLinkLinkCodeMethods.GetTarget(instance)}"
: fileInfo.Name
: string.Empty;
}
return new string(mode);
/// <summary>
/// Provides a LengthString property for FileSystemInfo.
/// </summary>
/// <param name="instance">Instance of PSObject wrapping a FileSystemInfo.</param>
/// <returns>Length as a string.</returns>
public static string LengthString(PSObject instance)
{
return instance?.BaseObject is FileInfo fileInfo
? fileInfo.Attributes.HasFlag(FileAttributes.Offline)
? $"({fileInfo.Length})"
: fileInfo.Length.ToString()
: string.Empty;
}
/// <summary>
/// Provides a LastWriteTimeString property for FileSystemInfo.
/// </summary>
/// <param name="instance">Instance of PSObject wrapping a FileSystemInfo.</param>
/// <returns>LastWriteTime formatted as short date + short time.</returns>
public static string LastWriteTimeString(PSObject instance)
{
return instance?.BaseObject is FileSystemInfo fileInfo
? string.Format(CultureInfo.CurrentCulture, "{0,10:d} {0,8:t}", fileInfo.LastWriteTime)
: string.Empty;
}
#region RenameItem
@ -2481,8 +2547,8 @@ namespace Microsoft.PowerShell.Commands
flags |= NativeMethods.SymbolicLinkFlags.AllowUnprivilegedCreate;
}
int created = NativeMethods.CreateSymbolicLink(path, strTargetPath, flags);
return (created == 1) ? true : false;
var created = NativeMethods.CreateSymbolicLink(path, strTargetPath, flags);
return created;
}
private static bool WinCreateHardLink(string path, string strTargetPath)
@ -7013,7 +7079,8 @@ namespace Microsoft.PowerShell.Commands
/// <param name="symbolicLinkFlags">Flag values from SymbolicLinkFlags enum.</param>
/// <returns>1 on successful creation.</returns>
[DllImport(PinvokeDllNames.CreateSymbolicLinkDllName, CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern int CreateSymbolicLink(string name, string destination, SymbolicLinkFlags symbolicLinkFlags);
[return: MarshalAs(UnmanagedType.I1)]
internal static extern bool CreateSymbolicLink(string name, string destination, SymbolicLinkFlags symbolicLinkFlags);
/// <summary>
/// Flags used when creating a symbolic link.
@ -7034,7 +7101,7 @@ namespace Microsoft.PowerShell.Commands
/// <summary>
/// Allow creation of symbolic link without elevation. Requires Developer mode.
/// </summary>
AllowUnprivilegedCreate = 2
AllowUnprivilegedCreate = 2,
}
/// <summary>
@ -7709,7 +7776,7 @@ namespace Microsoft.PowerShell.Commands
/// </summary>
/// <param name="instance">The object of FileInfo or DirectoryInfo type.</param>
/// <returns>The target of the reparse point.</returns>
public static IEnumerable<string> GetTarget(PSObject instance)
public static string GetTarget(PSObject instance)
{
if (instance.BaseObject is FileSystemInfo fileSysInfo)
{
@ -7718,13 +7785,11 @@ namespace Microsoft.PowerShell.Commands
{
string linkTarget = WinInternalGetTarget(handle);
if (linkTarget != null)
{
return (new string[] { linkTarget });
}
return linkTarget;
}
#else
return UnixInternalGetTarget(fileSysInfo.FullName);
#endif
return InternalGetTarget(fileSysInfo.FullName);
}
return null;
@ -7743,84 +7808,23 @@ namespace Microsoft.PowerShell.Commands
{
return InternalGetLinkType(fileSysInfo);
}
else
return null;
return null;
}
private static List<string> InternalGetTarget(string filePath)
{
var links = new List<string>();
#if UNIX
private static string UnixInternalGetTarget(string filePath)
{
string link = Platform.NonWindowsInternalGetTarget(filePath);
if (!string.IsNullOrEmpty(link))
{
links.Add(link);
}
else
if (string.IsNullOrEmpty(link))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
#elif !CORECLR // FindFirstFileName, FindNextFileName and FindClose are not available on Core Clr
UInt32 linkStringLength = 0;
var linkName = new StringBuilder();
// First get the length for the linkName buffer.
IntPtr fileHandle = InternalSymbolicLinkLinkCodeMethods.FindFirstFileName(filePath, 0, ref linkStringLength, linkName);
int lastError = Marshal.GetLastWin32Error();
// Return handle is INVALID_HANDLE_VALUE and LastError was ERROR_MORE_DATA
if ((fileHandle == (IntPtr)(-1)) && (lastError == 234))
{
linkName = new StringBuilder((int)linkStringLength);
fileHandle = InternalSymbolicLinkLinkCodeMethods.FindFirstFileName(filePath, 0, ref linkStringLength, linkName);
lastError = Marshal.GetLastWin32Error();
}
if (fileHandle == (IntPtr)(-1))
{
throw new Win32Exception(lastError);
}
bool continueFind = false;
try
{
do
{
StringBuilder fullName = new StringBuilder();
fullName.Append(Path.GetPathRoot(filePath)); // hard link source and target must be on the same drive. So we can use the source for find the path root.
fullName.Append(linkName.ToString());
FileInfo fInfo = new FileInfo(fullName.ToString());
// Don't add the target link to the list.
if (string.Compare(fInfo.FullName, filePath, StringComparison.OrdinalIgnoreCase) != 0)
links.Add(fInfo.FullName);
continueFind = InternalSymbolicLinkLinkCodeMethods.FindNextFileName(fileHandle, ref linkStringLength, linkName);
lastError = Marshal.GetLastWin32Error();
if (!continueFind && lastError == 234) // ERROR_MORE_DATA
{
linkName = new StringBuilder((int)linkStringLength);
continueFind = InternalSymbolicLinkLinkCodeMethods.FindNextFileName(fileHandle, ref linkStringLength, linkName);
}
if (!continueFind && lastError != 38) // ERROR_HANDLE_EOF. No more links.
{
throw new Win32Exception(lastError);
}
}
while (continueFind);
}
finally
{
InternalSymbolicLinkLinkCodeMethods.FindClose(fileHandle);
}
#endif
return links;
return link;
}
#endif
private static string InternalGetLinkType(FileSystemInfo fileInfo)
{
@ -7909,16 +7913,9 @@ namespace Microsoft.PowerShell.Commands
internal static bool IsReparsePoint(FileSystemInfo fileInfo)
{
if (Platform.IsWindows)
{
// Note that this class also has a enum called FileAttributes, so use fully qualified name
return (fileInfo.Attributes & System.IO.FileAttributes.ReparsePoint)
== System.IO.FileAttributes.ReparsePoint;
}
else
{
return Platform.NonWindowsIsSymLink(fileInfo);
}
return Platform.IsWindows
? fileInfo.Attributes.HasFlag(System.IO.FileAttributes.ReparsePoint)
: Platform.NonWindowsIsSymLink(fileInfo);
}
internal static bool WinIsHardLink(FileSystemInfo fileInfo)

View File

@ -10,5 +10,10 @@
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IsWindows Condition="'$(OS)' == 'Windows_NT'">true</IsWindows>
</PropertyGroup>
<PropertyGroup Condition=" '$(IsWindows)' != 'true' ">
<DefineConstants>$(DefineConstants);UNIX</DefineConstants>
</PropertyGroup>
</Project>

View File

@ -190,3 +190,51 @@ Describe "Get-ChildItem" -Tags "CI" {
}
}
}
Describe 'FileSystem Provider Formatting' -Tag "CI","RequireAdminOnWindows" {
BeforeAll {
$modeTestDir = New-Item -Path "$TestDrive/testmodedirectory" -ItemType Directory -Force
$targetFile1 = New-Item -Path "$TestDrive/targetFile1" -ItemType File -Force
$targetFile2 = New-Item -Path "$TestDrive/targetFile2" -ItemType File -Force
$targetDir1 = New-Item -Path "$TestDrive/targetDir1" -ItemType Directory -Force
$targetDir2 = New-Item -Path "$TestDrive/targetDir2" -ItemType Directory -Force
$testcases = @(
@{ expectedMode = "d----"; expectedModeWithoutHardlink = "d----"; itemType = "Directory"; itemName = "Directory"; fileAttributes = [System.IO.FileAttributes] "Directory"; target = $null }
@{ expectedMode = "l----"; expectedModeWithoutHardlink = "l----"; itemType = "SymbolicLink"; itemName = "SymbolicLink-Directory"; fileAttributes = [System.IO.FileAttributes]::Directory -bor [System.IO.FileAttributes]::ReparsePoint; target = $targetDir2.FullName }
)
if ($IsWindows)
{
$testcases += @{ expectedMode = "l----"; expectedModeWithoutHardlink = "l----"; itemType = "Junction"; itemName = "Junction-Directory"; fileAttributes = [System.IO.FileAttributes]::Directory -bor [System.IO.FileAttributes]::ReparsePoint; target = $targetDir1.FullName }
$testcases += @{ expectedMode = "-a---"; expectedModeWithoutHardlink = "-a---"; itemType = "File"; itemName = "ArchiveFile"; fileAttributes = [System.IO.FileAttributes] "Archive"; target = $null }
$testcases += @{ expectedMode = "la---"; expectedModeWithoutHardlink = "la---"; itemType = "SymbolicLink"; itemName = "SymbolicLink-File"; fileAttributes = [System.IO.FileAttributes]::Archive -bor [System.IO.FileAttributes]::ReparsePoint; target = $targetFile1.FullName }
$testcases += @{ expectedMode = "la---"; expectedModeWithoutHardlink = "-a---"; itemType = "HardLink"; itemName = "HardLink"; fileAttributes = [System.IO.FileAttributes] "Archive"; target = $targetFile2.FullName }
}
}
It 'Validate Mode property - <itemName>' -TestCases $testcases {
param($expectedMode, $expectedModeWithoutHardlink, $itemType, $itemName, $fileAttributes, $target)
$item = if ($target)
{
New-Item -Path $modeTestDir -Name $itemName -ItemType $itemType -Target $target
}
else
{
New-Item -Path $modeTestDir -Name $itemName -ItemType $itemType
}
$item | Should -BeOfType "System.IO.FileSystemInfo"
$actualMode = [Microsoft.PowerShell.Commands.FileSystemProvider]::Mode($item)
$actualMode | Should -BeExactly $expectedMode
$actualModeWithoutHardlink = [Microsoft.PowerShell.Commands.FileSystemProvider]::ModeWithoutHardlink($item)
$actualModeWithoutHardlink | Should -BeExactly $expectedModeWithoutHardlink
$item.Attributes | Should -Be $fileAttributes
}
}

View File

@ -15,7 +15,7 @@ Describe "Get-FormatData" -Tags "CI" {
$format.TypeNames | Should -HaveCount 2
$format.TypeNames[0] | Should -BeExactly "System.IO.DirectoryInfo"
$format.TypeNames[1] | Should -BeExactly "System.IO.FileInfo"
$format.FormatViewDefinition | Should -HaveCount 3
$format.FormatViewDefinition | Should -HaveCount 4
}
It "Should return nothing for format data requiring '-PowerShellVersion 5.1' and not provided" {

View File

@ -418,7 +418,7 @@ Describe "Type inference Tests" -tags "CI" {
It "Infers typeof Select-Object when Parameter is ExcludeProperty" {
$res = [AstTypeInference]::InferTypeOf( { [io.fileinfo]::new("file") | Select-Object -ExcludeProperty *Time*, E* }.Ast)
$res.Count | Should -Be 1
$res[0].Name | Should -Be "System.Management.Automation.PSObject#Attributes:BaseName:Directory:DirectoryName:FullName:IsReadOnly:Length:LinkType:Mode:Name:Target:VersionInfo"
$res[0].Name | Should -BeExactly "System.Management.Automation.PSObject#Attributes:BaseName:Directory:DirectoryName:FullName:IsReadOnly:Length:LengthString:LinkType:Mode:ModeWithoutHardLink:Name:NameString:Target:VersionInfo"
$names = $res[0].Members.Name
$names -contains "BaseName" | Should -BeTrue
$names -contains "Name" | Should -BeTrue

View File

@ -14,6 +14,8 @@ using System.Management.Automation.Internal.Host;
using System.Management.Automation.Provider;
using System.Management.Automation.Runspaces;
using System.Reflection;
using System.Reflection.Metadata;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.PowerShell;
using Microsoft.PowerShell.Commands;
using Xunit;
@ -107,9 +109,9 @@ namespace PSTests.Parallel
executableObject = new FileInfo(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
}
Assert.Equal("d-----", FileSystemProvider.Mode(PSObject.AsPSObject(directoryObject)).Replace("r", "-"));
Assert.Equal("------", FileSystemProvider.Mode(PSObject.AsPSObject(fileObject)).Replace("r", "-").Replace("a", "-"));
Assert.Equal("------", FileSystemProvider.Mode(PSObject.AsPSObject(executableObject)).Replace("r", "-").Replace("a", "-"));
Assert.Equal("d----", FileSystemProvider.Mode(PSObject.AsPSObject(directoryObject)).Replace("r", "-"));
Assert.Equal("-----", FileSystemProvider.Mode(PSObject.AsPSObject(fileObject)).Replace("r", "-").Replace("a", "-"));
Assert.Equal("-----", FileSystemProvider.Mode(PSObject.AsPSObject(executableObject)).Replace("r", "-").Replace("a", "-"));
}
[Fact]
@ -125,13 +127,8 @@ namespace PSTests.Parallel
fileSystemProvider.GetProperty(testPath, new Collection<string>(){ "IsReadOnly" });
FileInfo fileSystemObject1 = new FileInfo(testPath);
PSObject psobject1 = PSObject.AsPSObject(fileSystemObject1);
foreach (PSPropertyInfo property in psobject1.Properties)
{
if (property.Name == "IsReadOnly")
{
Assert.False((bool)property.Value);
}
}
PSPropertyInfo property = psobject1.Properties["IsReadOnly"];
Assert.False((bool)property.Value);
}
[Fact]
@ -144,13 +141,9 @@ namespace PSTests.Parallel
fileSystemProvider.GetProperty(testPath, new Collection<string>(){ "Name" });
FileInfo fileSystemObject1 = new FileInfo(testPath);
PSObject psobject1 = PSObject.AsPSObject(fileSystemObject1);
foreach (PSPropertyInfo property in psobject1.Properties)
{
if (property.Name == "FullName")
{
Assert.Equal(testPath, property.Value);
}
}
PSPropertyInfo property = psobject1.Properties["FullName"];
Assert.Equal(testPath, property.Value);
}
[Fact]