Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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 @@ -650,7 +650,10 @@ protected override void ProcessRecord()
//if fileversion of each process is to be displayed
try
{
WriteObject(PsUtils.GetMainModule(process).FileVersionInfo, true);
ProcessModule mainModule = PsUtils.GetMainModule(process);
if (mainModule != null) {
Copy link
Member

Choose a reason for hiding this comment

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

When mainModule == null, is the expected behavior to be writing out nothing or throwing an error?
On windows, the current behavior is to throw error when the FileInfoVersion is not accessible.

@JamesWTruher Your insight would be helpful here.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Collaborator

Choose a reason for hiding this comment

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

it's also possible on non-windows platforms that mainmodule could be null due to the underlying corefx implementation (ex: process id 0). Throwing an error doesn't seem reasonable.

WriteObject(mainModule.FileVersionInfo, true);
}
}
catch (InvalidOperationException exception)
{
Expand Down
7 changes: 2 additions & 5 deletions src/System.Management.Automation/utils/PsUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,12 @@ internal static class PsUtils
internal static ProcessModule GetMainModule(Process targetProcess)
{
int caughtCount = 0;
ProcessModule mainModule = null;

while (mainModule == null)
while (true)
{
try
{
mainModule = targetProcess.MainModule;
return targetProcess.MainModule;
}
catch (System.ComponentModel.Win32Exception e)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@daxian-dbw what do you think?

Copy link
Member

Choose a reason for hiding this comment

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

I don't think we should catch InvalidOperationException. It seems to me we catch Win32Exception only to work around the flaw described in the summary.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Why we should wait if process already exit? I'd re-throw immediately.

Copy link
Member

Choose a reason for hiding this comment

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

InvalidOperationException will be thrown when process already exists, but we don't catch InvalidOperationException and thus no waiting in that case.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks for clarify!

{
Expand All @@ -81,8 +80,6 @@ internal static ProcessModule GetMainModule(Process targetProcess)
throw;
}
}

return mainModule;
}

// Cache of the current process' parentId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,25 @@ Describe "Get-Process for admin" -Tags @('CI', 'RequireAdminOnWindows') {
}
}

It "Should support -FileVersionInfo" -Skip:(!$IsWindows) {
Copy link
Member

Choose a reason for hiding this comment

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

This test is wrong for non-Windows. If you run the Get-Process line below on non-Windows, you'll see that FileVersion is $null. "anything" -match $null returns $true. This test for correct FileVersion being returned will only work on Windows. Perhaps we can modify this test to work on both Windows and non-Windows:

It "Should support -FileVersionInfo" {
  $pwshVersion = ...
  if ($IsWindows) {
     $pwshVersion | Should -BeExactly $PSVersionTable.PSVersion
 } else {
     $pwshVersion | Should -BeNullOrEmpty
 }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do we know that process' FileVersion always would be null or non windows platform?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, the FileVersion information is stored as resources in PE file format on Windows whereas Linux uses ELF format which is not compatible with this extended file information.

It "Should support -FileVersionInfo" {
$pwshVersion = Get-Process -Id $pid -FileVersionInfo
$PSVersionTable.PSVersion | Should -Match $pwshVersion.FileVersion
if ($IsWindows) {
$PSVersionTable.PSVersion | Should -MatchExactly $pwshVersion.FileVersion
$gitCommitId = $PSVersionTable.GitCommitId
if ($gitCommitId.StartsWith("v")) { $gitCommitId = $gitCommitId.Substring(1) }
$pwshVersion.ProductVersion.Replace("-dirty","") | Should -BeExactly $gitCommitId
} else {
$pwshVersion.FileVersion | Should -BeNullOrEmpty
}
}

It "Run with parameter -FileVersionInfo should not hang on non Windows platform also when process' main module is null." -Skip:$IsWindows {
# Main module for idle process can be null on non-Windows platforms
{ $pwshVersion = Get-Process -Id 0 -FileVersionInfo -ErrorAction Stop } | Should -Not -Throw
}

It "Run with parameter -FileVersionInfo for idle process should throw on Windows." -Skip:(!$IsWindows) {
{ $pwshVersion = Get-Process -Id 0 -FileVersionInfo -ErrorAction Stop } | Should -Throw -ErrorId "CouldNotEnumerateFileVer,Microsoft.PowerShell.Commands.GetProcessCommand"
}
}

Expand Down