C# 在.NET中使用NTFS压缩压缩文件夹
我想在.NET中使用NTFS压缩来压缩文件夹。我找到了,但它不起作用。它抛出一个异常(“无效参数”)C# 在.NET中使用NTFS压缩压缩文件夹,c#,.net,windows,ntfs,C#,.net,Windows,Ntfs,我想在.NET中使用NTFS压缩来压缩文件夹。我找到了,但它不起作用。它抛出一个异常(“无效参数”) 有人知道如何在文件夹上启用NTFS压缩吗?我不相信有一种方法可以在.NET framework中设置文件夹压缩,因为文档(备注部分)声称这是无法通过的。这似乎仅在使用函数的Win32 API中可用。我们仍然可以通过.NET使用 一旦基本熟悉PInvoke,请查看网站上的参考资料,其中讨论了实现这一点所需的外观。我已经测试了代码,并且已经完成了测试 确保它适用于gui。也许分配单元的大小对于压缩
有人知道如何在文件夹上启用NTFS压缩吗?我不相信有一种方法可以在.NET framework中设置文件夹压缩,因为文档(备注部分)声称这是无法通过的。这似乎仅在使用函数的Win32 API中可用。我们仍然可以通过.NET使用
一旦基本熟悉PInvoke,请查看网站上的参考资料,其中讨论了实现这一点所需的外观。我已经测试了代码,并且已经完成了测试
- 确保它适用于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);
}
}
}
}
根据我的经验,使用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调用usingFILE\u FLAG\u BACKUP\u SEMANTICS
来获取目录上的SafeFileHandle
另外,请注意,在NTFS中的目录上设置压缩不会压缩所有内容,它只会使新文件显示为压缩文件(加密也是如此)。如果要压缩整个目录,需要遍历整个目录,并在每个文件/文件夹上调用DeviceIoControl。创建Win32_目录时。名称=。。。字符串需要将反斜杠加倍,因此,例如,路径C:\Foo\Bar将构建为: Win32\u目录。Name=“C:\\Foo\\Bar” 或者使用您的示例代码: 字符串objPath=“Win32\u目录。名称=\”C:\\\\Foo\\\\Bar\”
显然,该字符串被馈送到某个进程,该进程需要路径字符串的转义形式。这是对Igal Serban答案的轻微修改。我遇到了一个微妙的问题,
名称必须采用非常具体的格式。因此,我添加了一些Replace(“\\”,@“\\”)
magic来首先规范化路径,我还清理了一些代码
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");
}
}
有一种更简单的方法,我在Windows8中使用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到\pcname\root,如果您需要在另一台计算机上执行此操作。小心使用。这是一种比解析为p/Invoke更干净的方法,更重要的是,尽管返回了成功状态代码,但它实际上并不起作用。虽然ManagementObject
.ctor很挑剔,但我使用了这个string objPath=“Win32\u Directory.Name=“+””“+dir.FullName.Replace(“\\”,@“\\”).TrimEnd(“\\”)+”
以确保ManagementObject
不会抛出无效参数。顺便说一句,如何解压缩目录?只说“未定义类型‘ManagementObject’”&“未定义类型‘ManagementBaseObject’”。还警告导入系统。管理不是nec。我的版本是VS2019
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