문제

.NET에서 NTFS 압축을 사용하여 폴더를 압축하고 싶습니다. 나는 찾았다 이 게시물, 그러나 작동하지 않습니다. 예외 ( "유효하지 않은 매개 변수")가 발생합니다.

DirectoryInfo directoryInfo = new DirectoryInfo( destinationDir );
if( ( directoryInfo.Attributes & FileAttributes.Compressed ) != FileAttributes.Compressed )
{
   string objPath = "Win32_Directory.Name=" + "\"" + destinationDir + "\"";
   using( ManagementObject dir = new ManagementObject( objPath ) )
   {
      ManagementBaseObject outParams = dir.InvokeMethod( "Compress", null, null );
      uint ret = (uint)( outParams.Properties["ReturnValue"].Value );
   }
}

폴더에서 NTFS 압축을 활성화하는 방법을 아는 사람이 있습니까?

도움이 되었습니까?

해결책

P/Invoke를 사용하는 것은 내 경험상 일반적으로 WMI보다 쉽습니다. 다음이 효과가 있다고 생각합니다.

private const int FSCTL_SET_COMPRESSION = 0x9C040;
private const short COMPRESSION_FORMAT_DEFAULT = 1;

[DllImport("kernel32.dll", SetLastError = true)]
private static extern int DeviceIoControl(
    SafeFileHandle hDevice,
    int dwIoControlCode,
    ref short lpInBuffer,
    int nInBufferSize,
    IntPtr lpOutBuffer,
    int nOutBufferSize,
    ref int lpBytesReturned,
    IntPtr lpOverlapped);

public static bool EnableCompression(SafeFileHandle handle)
{
    int lpBytesReturned = 0;
    short lpInBuffer = COMPRESSION_FORMAT_DEFAULT;

    return DeviceIoControl(handle, FSCTL_SET_COMPRESSION,
        ref lpInBuffer, sizeof(short), IntPtr.Zero, 0,
        ref lpBytesReturned, IntPtr.Zero) != 0;
}

디렉토리에서 이것을 설정하려고하므로 p/invoke를 사용해야합니다. CreateFile 사용 FILE_FLAG_BACKUP_SEMANTICS 디렉토리에서 SafeFileHandle을 얻으려면

또한 NTFS의 디렉토리에서 압축을 설정하면 모든 내용이 압축되지 않으며 새 파일 만 압축 된 것으로 표시됩니다 (암호화에 대해서도 마찬가지입니다). 전체 디렉토리를 압축하려면 전체 디렉토리를 걸어 각 파일/폴더에서 DeviceioControl을 호출해야합니다.

다른 팁

나는 코드와 그것을 테스트했다 alt text!

  • GUI와 함께 작동하는지 확인하십시오. 아마도 할당 장치 크기가 압축하기에는 너무 커질 수 있습니다. 또는 충분한 권한이 없습니다.
  • 대상 사용 형식과 같은 형식 : 전방 슬래시가있는 "C :/Temp/TestComp".

전체 코드 :

using System.IO;
using System.Management;

class Program
{
    static void Main(string[] args)
    {
        string destinationDir = "c:/temp/testcomp";
        DirectoryInfo directoryInfo = new DirectoryInfo(destinationDir);
        if ((directoryInfo.Attributes & FileAttributes.Compressed) != FileAttributes.Compressed)
        {
            string objPath = "Win32_Directory.Name=" + "\"" + destinationDir + "\"";
            using (ManagementObject dir = new ManagementObject(objPath))
            {
                ManagementBaseObject outParams = dir.InvokeMethod("Compress", null, null);
                uint ret = (uint)(outParams.Properties["ReturnValue"].Value);
            }
        }
     }
}

win32_directory.name = ... 문자열을 만들 때는 백 슬래시를 두 배로 늘려야하므로 경로 C : foo bar는 다음과 같이 구축됩니다.

win32_directory.name = "c : foo bar",

또는 예제 코드 사용 :

String objpath = "win32_directory.name = "c : foo bar "";

분명히 문자열은 탈출 된 형태의 경로 문자열을 기대하는 일부 프로세스에 공급됩니다.

Docs (비고 섹션)가 말할 수 없다고 주장하는 것처럼 .NET 프레임 워크에서 폴더 압축을 설정하는 방법이 있다고 생각하지 않습니다. file.setattributes. 이것은 Win32 API에서만 사용할 수있는 것 같습니다. Deviceiocontrol 기능. 사용하여 .NET를 통해 여전히이 작업을 수행 할 수 있습니다 핀 보크.

일반적으로 Pinvoke에 익숙하면 참조를 확인하십시오. pinvoke.net 그것은 무엇을 논의합니다 서명 이 일을하기 위해서는 모양이 필요합니다.

Windows 8 64 비트에서 사용중인 훨씬 간단한 방법이 있으며 VB.NET에 다시 작성했습니다. 즐기다.

    Dim Path as string = "c:\test"
    Dim strComputer As String = "."
    Dim objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
    Dim colFolders = objWMIService.ExecQuery("Select * from Win32_Directory where name = '" & Replace(path, "\", "\\") & "'")
    For Each objFolder In colFolders
        objFolder.Compress()
    Next

나를 위해 잘 작동합니다. chagne. root to pcname root 다른 컴퓨터에서 수행 해야하는 경우. 조심스럽게 사용하십시오.

이것은 Igal Serban 답변의 약간의 적응입니다. 나는 미묘한 문제를 일으켰다 Name 매우 구체적인 형식이어야합니다. 그래서 나는 몇 가지를 추가했습니다 Replace("\\", @"\\").TrimEnd('\\') 마법 먼저 경로를 정규화하기 위해 코드도 약간 정리했습니다.

var dir = new DirectoryInfo(_outputFolder);

if (!dir.Exists)
{
    dir.Create();
}

if ((dir.Attributes & FileAttributes.Compressed) == 0)
{
    try
    {
        // Enable compression for the output folder
        // (this will save a ton of disk space)

        string objPath = "Win32_Directory.Name=" + "'" + dir.FullName.Replace("\\", @"\\").TrimEnd('\\') + "'";

        using (ManagementObject obj = new ManagementObject(objPath))
        {
            using (obj.InvokeMethod("Compress", null, null))
            {
                // I don't really care about the return value, 
                // if we enabled it great but it can also be done manually
                // if really needed
            }
        }
    }
    catch (Exception ex)
    {
        System.Diagnostics.Trace.WriteLine("Cannot enable compression for folder '" + dir.FullName + "': " + ex.Message, "WMI");
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top