Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unclear error message when unzipping paths > 260 characters #78

Open
tyler-ball opened this issue Aug 12, 2019 · 4 comments
Open

Unclear error message when unzipping paths > 260 characters #78

tyler-ball opened this issue Aug 12, 2019 · 4 comments

Comments

@tyler-ball
Copy link
Contributor

Description

By default Windows does not support paths > 260 characters. When trying to converge a cookbook that contains an embedded DSC resource, using policyfiles for dependency management, and testing using Test Kitchen an error occurs:

E, [2019-08-02T13:50:01.481897 #48646] ERROR -- tk-win16cor: Message: [WinRM::FS::Core::FileTransporter] Upload failed (exitcode: 0), but stderr present
Error HRESULT E_FAIL has been returned from a call to a COM component.
    + CategoryInfo          : OperationStopped: (:) [Invoke-Expression], COMException
    + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException,Microsoft.PowerShell.Commands.InvokeExpressionCommand

This exception is being thrown by the extract_files.ps1 script. This COM call is hidden beneath layers of try/catch blocks and is hiding the actual error. After troubleshooting we found the underlying error:

Exception calling "ExtractToDirectory" with "2" argument(s) : "Could not find a part of the path 'C:\Users\Administrator\AppData\local\Temp\winrm-upload\tmpzip-856e18bfe2g171640fd43 a42gdcg5562gecb1e2\mitre_win_security-e0c717650c8f0ab2f3c6e0c3e4ca1a755d5479f8\files\default\cSecurityOptions\3.1.2\DSCResources\AccountAndBasicAuditing\AccountAndBasicAuditing.psm1'."

That path is longer than 260 characters and cannot be unzipped in standard Windows.

Environment

Test Kitchen target: Windows Server 2016 Core running in vcenter

Suggested fix

For current customers: https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#enable-long-paths-in-windows-10-version-1607-and-later
Enhancement to winrm-fs: echo to stdout any caught exceptions in the try/catch logic of extract_files.ps1. Cannot echo to stderr because that would cause the run to fail via

elsif stderr != '\r\n' && stderr != ''

@mwrock
Copy link
Member

mwrock commented Aug 12, 2019

Seems like you would want to emit to stderr @tyler-ball. Wouldn't the run fail anyway if the file fails to extract?

@tyler-ball
Copy link
Contributor Author

Except that it can fail the first try block but succeed in the first catch block. Unless there is a way to temporarily pipe to a buffer and then echo to stdout in a finally?

@mwrock
Copy link
Member

mwrock commented Aug 12, 2019

Another thought would be changing:

  try {
    try{
      [IO.Compression.ZipFile]::ExtractToDirectory($src, $unpack)
    }
    catch {
      Add-Type -AssemblyName System.IO.Compression.FileSystem -ErrorAction Stop
      [IO.Compression.ZipFile]::ExtractToDirectory($src, $unpack)
    }
  }
  catch {
    Try {
      $s = New-Object -ComObject Shell.Application
      ($s.NameSpace($unpack)).CopyHere(($s.NameSpace($src)).Items(), 0x610) | Out-Null
    }
    Finally {
      [void][Runtime.Interopservices.Marshal]::ReleaseComObject($s)
    }
  }

to

$useShellComponent = $false
try{
    Add-Type -AssemblyName System.IO.Compression.FileSystem -ErrorAction Stop
}
catch { $useShellComponent = $true }
if($useShellComponent) {
    try {
        $s = New-Object -ComObject Shell.Application
        ($s.NameSpace($unpack)).CopyHere(($s.NameSpace($src)).Items(), 0x610) | Out-Null
    }
    Finally {
      [void][Runtime.Interopservices.Marshal]::ReleaseComObject($s)
    }
} else {
     [IO.Compression.ZipFile]::ExtractToDirectory($src, $unpack)
}

Here we always call Add-Type and assume the type is not loaded which should also run fine if it is already loaded. If it fails it would be an older PS version and we would attempt to use Shell.Application. If either approach (Shell.Application or ExtractToDirectory) fails, then the actual filesystem error is thrown and extract-files fails with the with the more relevant error.

Does that make sense?

@sandratiffin
Copy link

For this issue, a workaround has been used to enable long paths in certain versions of Windows. However, that will not work for 2012/2012R2, and also will break some 32-bit apps.

I suggest that we try to reduce the lengths of the paths we are using rather than trying to fix it here (or in addition to some fixes here that make it clear that the path length is exceeded) -- the base path of the files being extracted is pretty long and the filename is too, and when added to long paths within a cookbook we are pushed over the limit. I am sure we can find ways to make the directory and filename Test Kitchen is extracting, a lot shorter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants