PowerShell / PowerShellGetv2

PowerShellGet is the Package Manager for PowerShell
https://www.PowerShellGallery.com
MIT License
430 stars 138 forks source link

PowerShellGet doesn't automatically check for NetFx version of CredentialProvider.Microsoft.exe #622

Open ld0614 opened 5 years ago

ld0614 commented 5 years ago

Steps to reproduce

Install fresh Windows 10 1903 with no additional software

Install-Module -Name PackageManagement -Force -AllowClobber
Install-Module -Name PowerShellGet -Force -AllowClobber

Import-Module -Name PackageManagement -ErrorAction Stop
Import-Module -Name PowerShellGet -ErrorAction Stop -Force

$script = Invoke-WebRequest -Uri https://raw.githubusercontent.com/microsoft/artifacts-credprovider/master/helpers/installcredprovider.ps1

$TempFile = New-TemporaryFile
$OldTempFile = $TempFile.ToString()
$TempFile = $TempFile.ToString().Replace($TempFile.Extension,".ps1")
Remove-Item -Path $OldTempFile -Force

Out-File -InputObject $script.Content -FilePath $TempFile

Invoke-Command -ScriptBlock {powershell.exe -file $TempFile -AddNetFx -Force}

Remove-Item -Path $TempFile -Force

Register-PSRepository -Name RepoName -SourceLocation $RepoURL -PublishLocation $RepoURL -Debug

Expected behavior

Repository is registered using the CredentialProvider.Microsoft helper for Azure DevOps Artifacts Integration

Actual behaviour

Start-Process : This command cannot be run due to the error: The system cannot find the file specified.
At C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\2.2.1\PSModule.psm1:9331 char:5
+     Start-Process $filename -ArgumentList "$arguments -V minimal" `
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Start-Process], InvalidOperationException
    + FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand

Looking at the code it appears that only .nuget/plugins/netcore/CredentialProvider.Microsoft/CredentialProvider.Microsoft.dll in the user profile is checked. The advice from https://github.com/microsoft/artifacts-credprovider is that the NetFx package is required as such this was downloaded to .nuget\plugins\netfx\CredentialProvider.Microsoft and includes the CredentialProvider.Microsoft.exe file. On a standard Windows 10 device the dotnet application is not available, therefore the error received is highly confusing (implicit dependency on dotnet application) and as there is a supported approach avoiding the requirement of dotnet, IMO this should be silently checked for.

Possible Fix

Starts Line 9252 of Version 2.2.1

        # Option 1b) Find User-location - The NuGet Home location - %UserProfile%/.nuget/plugins/
        $path = "$($env:UserProfile)/.nuget/plugins/netcore/CredentialProvider.Microsoft/CredentialProvider.Microsoft.dll";
        $exePath = "$($env:UserProfile)/.nuget\plugins\netfx\CredentialProvider.Microsoft\CredentialProvider.Microsoft.exe";
        if ($script:IsLinux -or $script:IsMacOS) {
            $path = "$($HOME)/.nuget/plugins/netcore/CredentialProvider.Microsoft/CredentialProvider.Microsoft.dll";
        }
        if (Test-Path $exePath -PathType Leaf) {
            $credProviderPath = $exePath
            $callDotnet = $false
        }
        elseif (Test-Path $path -PathType Leaf) {
            $credProviderPath = $path
        }

Environment data

> $PSVersionTable
Name                           Value                                                                                                                                                          
----                           -----                                                                                                                                                          
PSVersion                      5.1.18362.145                                                                                                                                                  
PSEdition                      Desktop                                                                                                                                                        
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                                                                                                                        
BuildVersion                   10.0.18362.145                                                                                                                                                 
CLRVersion                     4.0.30319.42000                                                                                                                                                
WSManStackVersion              3.0                                                                                                                                                            
PSRemotingProtocolVersion      2.3                                                                                                                                                            
SerializationVersion           1.1.0.1
> Get-Module -ListAvailable PowerShellGet,PackageManagement
ModuleType Version    Name                                ExportedCommands                                                                                                                    
---------- -------    ----                                ----------------                                                                                                                    
Script     1.4.4      PackageManagement                   {Find-Package, Get-Package, Get-PackageProvider, Get-PackageSource...}                                                              
Binary     1.0.0.1    PackageManagement                   {Find-Package, Get-Package, Get-PackageProvider, Get-PackageSource...}                                                              
Script     2.2.1      PowerShellGet                       {Find-Command, Find-DSCResource, Find-Module, Find-RoleCapability...}                                                               
Script     1.0.0.1    PowerShellGet                       {Install-Module, Find-Module, Save-Module, Update-Module...}   
> Get-PackageProvider -ListAvailable
Name                     Version          DynamicOptions                                                                                                                                      
----                     -------          --------------                                                                                                                                      
msi                      3.0.0.0          AdditionalArguments                                                                                                                                 
msu                      3.0.0.0                                                                                                                                                              
NuGet                    2.8.5.208        Destination, ExcludeVersion, Scope, SkipDependencies, Headers, FilterOnTag, Contains, AllowPrereleaseVersions, ConfigFile, SkipValidate             
PowerShellGet            2.2.1.0          PackageManagementProvider, Type, Scope, AllowClobber, SkipPublisherCheck, InstallUpdate, NoPathUpdate, AllowPrereleaseVersions, Filter, Tag, Incl...
PowerShellGet            1.0.0.1          PackageManagementProvider, Type, Scope, AllowClobber, SkipPublisherCheck, InstallUpdate, NoPathUpdate, Filter, Tag, Includes, DscResource, RoleCa...
Programs                 3.0.0.0          IncludeWindowsInstaller, IncludeSystemComponent 
SydneyhSmith commented 4 years ago

@ld0614 thanks for opening this issue, and providing detailed explanation--it is very helpful! We will try to make this change when possible, but please note that we do not have any planned releases for PowerShell 2.x (we are currently undergoing a major re-architecture for PowerShell Get 3.0)

One work around for this is to set your NUGET_PLUGIN_PATHS to .nuget\plugins\netfx\CredentialProvider.Microsoft\CredentialProvider.Microsoft.exe in other words put $Env:NUGET_PLUGIN_PATHS = "fullpath\.nuget\plugins\netfx\CredentialProvider.Microsoft\CredentialProvider.Microsoft.exe" in your PowerShell profile