긴 경로 하위에 압축 해제하는 방법 알려주세요.

안녕하세요
C#으로 Windows 환경에서 파일을 마스킹 처리해주는 프로그램을 만들고 있습니다.

사용자가 압축 파일을 업로드하면 Temp Directory에 압축 해제한 뒤 파일을 편집하고 있는데, 내부 Depth가 깊은 압축 파일의 경우 Windows의 MAX_PATH로 인해 Exception이 발생합니다.
(Temp Directory : 사용자 폴더\Local\ProgramData~ 로 해당 경로만으로도 MAX_PATH의 1/2이 사용됩니다.)

이를 해결하기 위해 2가지 시도를 해봤는데 잘 되지 않아 질문 드립니다.

  1. 접두사로 "\?"를 Path앞에 붙이면 문제 없이 폴더 및 파일이 생성된다고 하여 테스트를 해보았습니다.
string prefix = @"\\?\";
string dirPath = prefix + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "PostDirectory");

Directory.CreateDirectory(dirPath);

  • prefix를 안붙이면 "System.IO.PathTooLongException 발생
  • prefix를 붙이면 “System.IO.IOException: '파일 이름, 디렉터리 이름 또는 볼륨 레이블 구문이 잘못되었습니다.” 가 발생

테스트 코드가 잘못된걸까요?

  1. AlphaFS 패키지를 사용해서도 테스트를 해봤습니다.
    Windows API 사용해서 MAX_PATH 우회는 가능하지만 tarArchive.ExtractContents 메서드처럼 .NET의 기능을 사용하는 것까지는 대응이 안되네요.

긴 경로 하위에 압축해제하는 방법이 있을까요?
많은 조언 부탁드립니다.

혹시 운영체제나 재현 코드를 알 수 있을까요? 제 경우에 다음과 같이 테스트를 해봤는데,

string tempPath = @"C:\temp";
for (int i = 0; i < 10; i++)
{
    tempPath = Path.Combine(tempPath, "longpathtest_01234567890123456789012345678901234567890123456789");
    Directory.CreateDirectory(tempPath);
}

Console.WriteLine(tempPath.Length);

string filePath = Path.Combine(tempPath, "test.txt");
File.WriteAllText(filePath, "test");

using ZipArchive zipArchive = ZipFile.Open("ConsoleApp1.zip", ZipArchiveMode.Read);
zipArchive.ExtractToDirectory(tempPath, true);

잘 동작합니다. Windows 7하고 11에서 .NET 5로 테스트해봤습니다.

3 Likes

Windows10입니다.
MAX_PATH는 260자를 넘어야 발생하기 때문에 아래와 같이 테스트 해봤습니다.

string prefix = @"\\?\";
string postPath = "";
for(int i=0; i<280; i++)
{
    postPath += "a";
}
string dirPath = prefix + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), postPath);

Directory.CreateDirectory(dirPath);

음… 그냥 전체 경로를 해시로 바꿔서 작업하면 안 되려나요? ㅎㅎㅎ

2 Likes

문서상으로는, 단일 디렉터리의 이름은 여전히 255를 넘을 수 없습니다. 이에 대해서는 다음의 문서에서,

CreateDirectory function (winbase.h) - Win32 apps | Microsoft Learn

아래와 같이 명시돼 있습니다.

The 255 character limit per path segment still applies.

4 Likes

.NET 프레임워크에서 .NET 6 이상으로 마이그레이션 가능하다면 마이그레이션 하고.

아니면 해당 로직만 별도 실행파일로 분리하세요

또 다른 편법으로는 심볼릭 링크를 통한 경로 단축 등이 있겠네요

3 Likes

LongPathsEnabled를 사용해 보셨을까요?

2 Likes

사용자 PC의 Windows 버전을 특정할 수 없어 LongPathsEnabled는 사용하지 못하고, Path 길이 제한을 해제할 방법이 없을 것 같아 사양을 변경하기로 했습니다.
다들 조언해주셔서 감사합니다!!

2 Likes