My Perl scripts need to work with pathnames that are longer than 260 characters, and I can not turn on the feature in the registry to enable Windows Long Path support.
I included a small Perl test, using the Win32::LongPath
module to do this, and found that only a few functions from that module work. No luck with:
Environment:
- Windows 10 version 10.0.19041 build 19041
- Strawberry Perl 5.30.3
I can't really find evidence that Win32::LongPath
will not work in that environment, except for CPAN saying that the module has only been tested on XP and Windows 8...
⚠ However all of the help for Perl/Windows Long Paths in Windows 10 seems to recommend this module?
Am I using it wrong? I have included the output of the last iteration of the loop in the MRE (Minimal Reproducible Example):
- The
chdirL
command never changes directories. - The
getcwdL
command only has 249 characters (513 expected).
package main 1.0;
use strict;
use warnings;
use Carp;
use Readonly;
use File::Spec::Functions;
use Cwd;
use Win32::LongPath;
my $dir = 'd123456789';
my $file = 'test.txt';
my $long_path = 'C:\\Temp';
my $long_file;
my $long_root = catdir $long_path, $dir;
my $fh;
# Maximum path length on linux : 4096
# Maximum path length on Windows : 260
Readonly::Scalar my $MAX_PATH => 512;
chdirL $long_path;
while ( length $long_path < $MAX_PATH ) {
$long_path = catdir $long_path, $dir;
$long_file = catfile $long_path, $file;
printf "%-5d: %s\n", length $long_path, "Making $long_path...";
mkdirL $long_path;
# === Does not change directories ==>
chdirL $long_path;
system 'CD';
# === Truncates path name ==>
my $curdir = getcwdL;
printf "%-20s: %s (%d)\n", 'getcwpdL', $curdir, length $curdir;
printf "%-5d: %s\n", length $long_file, "Making $long_file...";
openL \$fh, '>', $long_file or die "unable to create file\n";
print {$fh} "$long_path\n" or die "unable to print to file\n";
close $fh or die "unable to close file\n";
last if ( !( testL 'e', $long_path ) );
last if ( !( testL 'e', $long_file ) );
}
unlinkL $long_file or warn "unable to delete file\n";
1;
Last loop iteration:
513 : Making C:\Temp\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789...
W:\home\_PERL\long_path
getcwpdL : C:\Temp\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789 (249)
522 : Making C:\Temp\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\d123456789\test.txt...
chdirL
is failing withThe filename or extension is too long
.chdirL
, like the others, converts the path to a long path (\\?\...
), and calls the appropriate system call. This isSetCurrentDirectoryW
forchdirL
andGetCurrentDirectoryW
forgetcwdL
.Using paths of the form
\\?\...
extends the use length limit for some calls, but not forSetCurrentDirectoryW
andGetCurrentDirectoryW
. It also doesn't extend the limit forCreateDirectoryW
,CreateDirectoryExW
andRemoveDirectoryW
. These five retain the classical length limit even when using "long paths", at least according to Maximum Path Length Limitation, which provides a registry setting PLUS a manifest entry you can use to remove the limit on long paths for those calls.I don't remember if DLLs have their own manifest or not. If they do, the settings could be changed for just the module, and nothing would break. If they don't and
perl
's manifest needs to be changed, this would affect all uses ofGetCurrentDirectoryW
in the process, and that could cause problems. (GetCurrentDirectoryW
could return an error because the buffer is too small, which could lead to a failure or crash depending on whether error checking is performed.)