Set file compression attribute

1.5k views Asked by At

I expected this code:

if (!File.Exists(fullFileName))
{
    File.Create(fullFileName);
}

File.SetAttributes(fullFileName, FileAttributes.Compressed);

To set this flag:

enter image description here

But it doesn't... What am I doing wrong? How do I set that flag on a file?


UPDATE: It says in the documentation

"It is not possible to change the compression status of a File object using the SetAttributes method."

And apparently it doesn't work when using the static File.SetAttributes either.

Given that, how can this be achieved?

2

There are 2 answers

3
Jashaszun On

The attributes are a bitmask.

Try this:

File.SetAttributes(fullFileName,
    File.GetAttributes(fullFileName) | FileAttributes.Compressed);

(Found in File.SetAttributes Method under Examples.)

1
Sam On

You can use p/invoke to compress files.

I made myself a static helper function:

public static class FileTools
{
  private const int FSCTL_SET_COMPRESSION = 0x9C040;
  private const short COMPRESSION_FORMAT_DEFAULT = 1;

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

  public static bool EnableCompression(IntPtr 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;
  }
}

Which I use in my code for example with the file name:

using (var fileToCompress = File.Open(fileNameToCompress, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
  FileTools.EnableCompression(fileToCompress.Handle);