2009-03-08 38 views
10

Tôi muốn nén một thư mục bằng cách sử dụng nén NTFS trong .NET. Tôi tìm thấy this post, nhưng nó không hoạt động. Nó ném một ngoại lệ ("Tham số không hợp lệ").Nén một thư mục bằng cách sử dụng nén NTFS trong .NET

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); 
    } 
} 

Bất kỳ ai biết cách bật tính năng nén NTFS trên một thư mục?

Trả lời

11

Sử dụng P/Invoke, trong kinh nghiệm của tôi, thường dễ dàng hơn WMI. Tôi tin rằng sau nên làm việc:

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; 
} 

Vì bạn đang cố gắng để thiết lập này vào một thư mục, bạn có thể sẽ cần phải sử dụng P/Invoke để gọi CreateFile sử dụng FILE_FLAG_BACKUP_SEMANTICS để có được những SafeFileHandle trên thư mục. Ngoài ra, lưu ý rằng thiết lập nén trên một thư mục trong NTFS không nén tất cả các nội dung, nó chỉ làm cho các tệp mới hiển thị dưới dạng nén (điều này cũng đúng cho mã hóa). Nếu bạn muốn nén toàn bộ thư mục, bạn sẽ cần phải đi bộ toàn bộ thư mục và gọi DeviceIoControl trên mỗi tệp/thư mục.

0

Tôi không tin rằng có một cách để đặt nén thư mục trong khuôn khổ .NET dưới dạng tài liệu (phần nhận xét) yêu cầu không thể thực hiện thông qua File.SetAttributes. Điều này dường như chỉ có sẵn trong API Win32 sử dụng chức năng DeviceIoControl. Người ta vẫn có thể thực hiện việc này thông qua .NET bằng cách sử dụng PInvoke.

Khi đã quen với PInvoke nói chung, hãy xem tham chiếu tại số pinvoke.net thảo luận về những gì mà signature cần phải trông giống như thế để thực hiện điều này.

8

Tôi đã thử nghiệm mã và nó alt text!

  • Đảm bảo nó hoạt động với gui. Có lẽ kích thước đơn vị phân bổ quá lớn để nén. Hoặc bạn không có đủ quyền.
  • Đối với định dạng sử dụng đích của bạn như sau: "c:/temp/testcomp" với dấu gạch chéo về phía trước.

Full mã:

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); 
      } 
     } 
    } 
} 
+2

các dấu gạch chéo của foward đã thực hiện thủ thuật, cảm ơn !! – decasteljau

+3

Đây là một cách tiếp cận sạch hơn nhiều so với việc giải quyết P/Invoke, quan trọng hơn, nó không thực sự hoạt động mặc dù trả lại mã trạng thái thành công. Mặc dù 'ManagementObject' .ctor là cầu kỳ, tôi đã sử dụng' string objPath = "Win32_Directory.Name =" + "'" + dir.FullName.Replace ("\\", @ "\\"). TrimEnd (' \ \ ') + "'"; 'để đảm bảo rằng' ManagementObject' không ném tham số không hợp lệ. –

+0

làm thế nào để bạn giải nén thư mục btw? –

1

Khi tạo Win32_Directory.Name = ... chuỗi bạn cần phải tăng gấp đôi gạch chéo ngược, ví dụ như vậy đường dẫn C: \ Foo \ Bar sẽ được xây dựng như:

Win32_Directory.Name =" C: \\ \\ Foo Bar",

hoặc sử dụng mã ví dụ của bạn:

chuỗi objPath = "Win32_Directory.Name = \" C: \\\\ Foo \\\\ Bar \ "";

Dường như chuỗi được cấp cho một số quy trình dự kiến ​​dạng thoát của chuỗi đường dẫn.

0

Đây là một sự thích ứng nhỏ của câu trả lời Igal Serban. Tôi chạy vào một vấn đề tinh tế với Name phải ở định dạng rất cụ thể.Vì vậy, tôi đã thêm một số Replace("\\", @"\\").TrimEnd('\\')ma thuật để chuẩn hóa đường dẫn trước tiên, tôi cũng đã làm sạch mã một chút.

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"); 
    } 
} 
0

Có một cách đơn giản hơn nhiều, mà tôi đang sử dụng trong Windows 8 64 bit, được viết lại cho VB.NET. Thưởng thức.

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 

phù hợp với tôi. Chagne. \ Root to \ pcname \ root nếu bạn cần thực hiện trên máy tính khác. Sử dụng cẩn thận.

Các vấn đề liên quan