当前位置:  开发笔记 > 编程语言 > 正文

如何从PowerShell获取文件的实际磁盘大小?

如何解决《如何从PowerShell获取文件的实际磁盘大小?》经验,为你挑选了3个好方法。

我正在编写一个管理脚本,我需要计算磁盘上文件的大小.

这些文件位于压缩的NTFS卷上.

我无法使用FileInfo.Length,因为这是文件大小而不是磁盘上的大小.例如,如果我有一个100MB的文件,但由于NTFS压缩它只使用25MB,我需要我的脚本返回25MB.

有没有办法在Powershell中做到这一点?

(我知道GetCompressedFileSize()Win32的调用,但我希望这已经在某种程度上受到了影响.)



1> JMarsch..:

(编辑)

我想出了如何动态地向Fileobject添加属性(称为"脚本属性"),所以现在,我可以使用语法:$ theFileObject.CompressedSize来读取大小.

(编辑结束)

阅读Goyuix的回复,我想"很酷,但在Powershell中是不是有某种类型扩展功能?".所以我发现这个Scott Hanselman的帖子:http://www.hanselman.com/blog/MakingJunctionsReparsePointsVisibleInPowerShell.aspx

我为FileInfo对象创建了一个Script属性:CompressedSize.

这就是我所做的:(注意:我对Powershell很新,或者至少我没有太多使用它.这可能会更好,但这就是我做的:

首先,我从Goyuix的帖子中编译了Ntfs.ExtendedFileInfo.我把DLL放在我的Powershell配置文件目录中(Documents\WindowsPowershell)

接下来,我在配置文件目录中创建了一个名为My.Types.ps1xml的文件.

我将以下XML放入文件中:



    System.IO.FileInfo
    
        
          CompressedSize
          
            [Ntfs.ExtendedFileInfo]::GetCompressedFileSize($this.FullName)
          
        
    


该代码(一旦合并到类型系统中)将动态地将名为CompressedSize的属性添加到get-childitem/dir返回的FileInfo对象中.但Powershell还不知道代码,它还不知道我的DLL.我们在下一步处理:

编辑Profile.ps1.在同一目录中.现在,我的配置文件恰好已经包含了一些内容,因为我安装了PowerShell社区扩展.希望我在下一个代码片段中包含您需要的所有内容,以便它甚至可以在没有扩展的机器上运行.将以下代码添加到Profile.ps1:

#This will load the ExtendedfileInfo assembly to enable the GetCompressedFileSize method.  this method is used by the
#PSCompressedSize Script Property attached to the FileInfo object.
$null = [System.Reflection.Assembly]::LoadFile("$ProfileDir\ntfs.extendedfileinfo.dll") 

#merge in my extended types
$profileTypes = $ProfileDir | join-path -childpath "My.Types.ps1xml"
Update-TypeData $profileTypes

现在,我引用的$ ProfileDir变量先前在我的Profile.ps1脚本中定义.万一它不在你的身上,这里是定义:

$ProfileDir = split-path $MyInvocation.MyCommand.Path -Parent

而已.下次运行Powershell时,您可以访问FileInfo对象上的CompressedSize属性,就像它是任何其他属性一样.例:

$ myFile = dir c:\ temp\myfile.txt

$ myFile.CompressedSize

这是有效的(无论如何,在我的机器上),但我很想知道它是否符合最佳实践.有一件事我知道我做错了:在Profile.ps1文件中,我将LoadFile的结果返回到一个我不打算使用的变量($ null = blah blah).我这样做是为了禁止将加载文件的结果显示到控制台.可能有更好的方法.



2> Goyuix..:

加载托管Windows API(http://mwinapi.sourceforge.net/)并查看ExtendedFileInfo类.有一个方法GetPhysicalFileSize()将返回磁盘上文件所需的大小.

public static ulong GetPhysicalFileSize(string filename)

或者,您可以编译自己的DLL并加载该功能的程序集:

using System;
using System.Runtime.InteropServices;

namespace NTFS {
  public class ExtendedFileInfo
  {
    [DllImport("kernel32.dll", SetLastError=true, EntryPoint="GetCompressedFileSize")]
    static extern uint GetCompressedFileSizeAPI(string lpFileName, out uint lpFileSizeHigh);
    public static ulong GetCompressedFileSize(string filename)
    {
      uint high;
      uint low;
      low = GetCompressedFileSizeAPI(filename, out high);
      int error = Marshal.GetLastWin32Error();
      if (high == 0 && low == 0xFFFFFFFF && error != 0)
      {
        throw new System.ComponentModel.Win32Exception(error);
      }
      else
      {
        return ((ulong)high << 32) + low;
      }
    }
  }
}

然后编译:

csc /target:library /out:ntfs.extendedfileinfo.dll ntfs.extendedfileinfo.cs 

最后,在PowerShell中加载并运行:

PS C:\> [System.Reflection.Assembly]::LoadFile("C:\ntfs.extendedfileinfo.dll")
PS C:\> [NTFS.ExtendedFileInfo]::GetCompressedFileSize("C:\sample.txt")



3> Jeffrey Snov..:

使用V2 Add-Type和Pinvoke.NET很容易做到:

add-type -type  @'
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace Win32Functions
{
    public class ExtendedFileInfo
    {
        [DllImport("kernel32.dll", SetLastError=true, EntryPoint="GetCompressedFileSize")]
        static extern uint GetCompressedFileSizeAPI(string lpFileName, out uint lpFileSizeHigh);

        public static ulong GetCompressedFileSize(string filename)
        {
            uint high;
            uint low;
            low = GetCompressedFileSizeAPI(filename, out high);
            int error = Marshal.GetLastWin32Error();
            if (high == 0 && low == 0xFFFFFFFF && error != 0)
            throw new Win32Exception(error);
            else
            return ((ulong)high << 32) + low;
        }
    }
}
'@

[Win32Functions.ExtendedFileInfo]::GetCompressedFileSize( "C:\autoexec.bat")

实验!请享用!从事!

Jeffrey Snover [MSFT] Windows管理合作伙伴架构师访问Windows PowerShell团队博客:http: //blogs.msdn.com/PowerShell 访问Windows PowerShell ScriptCenter,网址为:http: //www.microsoft.com/technet/scriptcenter/hubs /msh.mspx

推荐阅读
jerry613
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有