.NET에서 NTFS 압축을 사용하여 폴더를 압축하십시오
문제
.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을 호출해야합니다.
다른 팁
나는 코드와 그것을 테스트했다 !
- 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");
}
}