Inno Setup获取在另一个应用程序中打开超过2GB限制的文件大小

时间:2015-09-25 16:22:18

标签: inno-setup pascalscript

我正在尝试使用来自vincenzo.net的ISXKB的公共域代码返回文件的大小。

protected void FILL_DATA (object sender, EventArgs e)
{
    DataTable IACS = new DataTable ();
    IACS = GenerateTransposedTableinCsharp (generateIacs ());
    for (int i = 6; i <= 8; i++) {

        string rowText = "A0" + i; // this gets updated for each outer iteration

        for (int j = 1; j <= 14; j++) {
            string text = rowText + j; // text is now in the form A0XJ
            // convert string to object id
        }
    }
}

但是,这似乎无法正常工作并返回function CloseHandle (hHandle: THandle): Boolean; external 'CloseHandle@kernel32.dll stdcall'; const // Some constants for CreateFile (). GENERIC_READ = $80000000; GENERIC_WRITE = $40000000; GENERIC_EXECUTE = $20000000; GENERIC_ALL = $10000000; FILE_SHARE_READ = 1; FILE_SHARE_WRITE = 2; FILE_SHARE_DELETE = 4; CREATE_NEW = 1; CREATE_ALWAYS = 2; OPEN_EXISTING = 3; OPEN_ALWAYS = 4; TRUNCATE_EXISTING = 5; FILE_READ_ATTRIBUTES = $80; FILE_WRITE_ATTRIBUTES = $100; // General Win32. INVALID_HANDLE_VALUE = -1; function CreateFile ( lpFileName : String; dwDesiredAccess : Cardinal; dwShareMode : Cardinal; lpSecurityAttributes : Cardinal; dwCreationDisposition : Cardinal; dwFlagsAndAttributes : Cardinal; hTemplateFile : Integer ): Integer; external 'CreateFileA@kernel32.dll stdcall'; function GetFileSize (hFile: THandle; var lpFileSizeHigh: Integer): Integer; external 'GetFileSize@kernel32.dll stdcall'; function GetTheFileSize (FileName: String): Integer; var hFile: THandle; iSize: Integer; hSize: Integer; begin hFile := CreateFile (FileName, GENERIC_READ,// Desired access. FILE_SHARE_READ + FILE_SHARE_WRITE, 0, // Security attributes. OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, 0); if (INVALID_HANDLE_VALUE = hFile) then begin Result := 0; Exit; end; iSize := GetFileSize (hFile, hSize); CloseHandle (hFile); Result := iSize; end; ,我认为这是因为它正在0退出。我传递给它的文件存在且可访问。任何人都可以解释为什么这是失败或建议替代方法?请注意,我无法使用内置的if (INVALID_HANDLE_VALUE = hFile) then Result := 0函数,因为它有2GB的限制,这对我的目的来说还不够。

1 个答案:

答案 0 :(得分:1)

我假设你使用的是Inno Setup的Unicode版本。

因此,您必须使用CreateFile的Unicode版本,CreateFileW,而不是CreateFileA

external 'CreateFileW@kernel32.dll stdcall';

无论如何,ISXKB implementation也有2 GB的限制:

  

此声明适用于最高2 GB 的文件   ...
  ...以整数形式检索文件大小的低32位部分,然后再次关闭文件。

要支持64位大小,请将其更改为:

function GetTheFileSize (FileName: String): Int64;
...
begin
  ...
  Result := Int64(Cardinal(iSize)) + (Int64(Cardinal(hSize)) shl 32);
end;

无论如何,这有点矫枉过正。并且正如您发现如果另一个应用程序打开文件而不允许其他应用程序至少读取该文件(它在FILE_SHARE_READ的调用中未指定CreateFile)它不起作用。

请注意,FileSize在这种情况下不会起作用,因为它与ISXKB的GetTheFileSize基本相同。

使用FindFirst support function

是一个简单的解决方案
function GetTheFileSize(FileName: String): Int64;
var
  FindRec: TFindRec;
begin
  if FindFirst(FileName, FindRec) then
  begin
    Result := Int64(FindRec.SizeHigh) shl 32 + FindRec.SizeLow;
    FindClose(FindRec);
  end
    else
  begin
    Result := -1;
  end;
end;