Delphi/C++Builder在没有做任何代码修改,重新编译后CRC不一致的解决方案。

本文提供了一种解决Delphi/C++Builder应用程序在未更改代码的情况下,因重新编译而导致CRC校验不一致的问题方案。通过调整时间戳处理方式,确保了CRC的一致性和准确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Delphi/C++Builder在没有做任何代码修改,只要重新编译后,再计算CRC,就会与原来不一致的。经同事的朋友查得是时间戳在做怪。解决方案见贴子:http://topic.youkuaiyun.com/u/20080613/11/9fa12d6b-473d-4ac9-a091-0b02f4ffcac6.html

下面只贴出代码:

  1. function FileDateToDateTime_UTC(FileDate: Integer): TDateTime;inline;
  2. var
  3.   st: SYSTEMTIME;
  4.   ft: FILETIME;
  5. begin
  6.   if FileDate = 0 then
  7.     Result := EncodeDate(1980,1,1) +
  8.     EncodeTime(0,0,00)
  9.   else
  10.   Result :=
  11.     EncodeDate(
  12.       LongRec(FileDate).Hi shr 9 + 1980,
  13.       LongRec(FileDate).Hi shr 5 and 15,
  14.       LongRec(FileDate).Hi and 31) +
  15.     EncodeTime(
  16.       LongRec(FileDate).Lo shr 11,
  17.       LongRec(FileDate).Lo shr 5 and 63,
  18.       LongRec(FileDate).Lo and 31 shl 10);
  19.   DateTimeToSystemTime(Result, st);
  20.   SystemTimeToFileTime(st,ft);
  21.   LocalFileTimeToFileTime(ft,ft);
  22.   FileTimeToSystemTime(ft,st);
  23.   Result := SystemTimeToDateTime(st)
  24. end;
  25. function FileDateToDateTime_(FileDate: Integer): TDateTime;inline;
  26. begin
  27.   if FileDate = 0 then
  28.     Result := EncodeDate(1980,1,1) +
  29.     EncodeTime(0,0,00)
  30.   else
  31.   Result :=
  32.     EncodeDate(
  33.       LongRec(FileDate).Hi shr 9 + 1980,
  34.       LongRec(FileDate).Hi shr 5 and 15,
  35.       LongRec(FileDate).Hi and 31) +
  36.     EncodeTime(
  37.       LongRec(FileDate).Lo shr 11,
  38.       LongRec(FileDate).Lo shr 5 and 63,
  39.       LongRec(FileDate).Lo and 31 shl 10);
  40. end;
  41. function FileTime_2_UnixTime (const pft:FILETIME):DWORD;inline;
  42. begin
  43.   Result := ((UInt64(pft.dwHighDateTime) shl 32) + UInt64(pft.dwLowDateTime) - UInt64(116444736000000000)) div UInt64(10000000);
  44. end;
  45. function DateTime_2_UnixTime(const dt: TDateTime):DWORD;inline;
  46. var
  47.   st:SYSTEMTIME;
  48.   ft:FILETIME;
  49. begin
  50.   DateTimeToSystemTime(dt,st);
  51.   SystemTimeToFileTime(st,ft);
  52.   LocalFileTimeToFileTime(ft,ft);
  53.   Result := FileTime_2_UnixTime(ft);
  54. end;
  55. procedure UnixTime_2_FileTime (const time_in:DWORD ; const pft:PFILETIME);inline;
  56. var
  57.   X:Int64;
  58. begin
  59.   x := LongLong(time_in) * 10000000 + 116444736000000000;//$19db1ded53ea710;
  60.   pft^.dwHighDateTime := DWORD((x shr 32and $0ffffffff);
  61.   pft^.dwLowDateTime := DWORD(x and $0ffffffff);
  62. end;
  63. function UinxTime_2_FileTime_String(const time_in:DWORD):String;inline;
  64. var
  65.   ft:FILETIME;
  66.   st:SYSTEMTIME;
  67. begin
  68.   UnixTime_2_FileTime(time_in,@ft);
  69.   FileTimeToLocalFileTime(ft,ft);
  70.   FileTimeToSystemTime(ft,st);
  71.   result := FormatDateTime('yyyy-mm-dd hh:nn:ss',SystemTimeToDateTime(st));
  72. end;
  73. function UnixTime_2_FileTime_String_UTC(const time_in:DWORD):String;inline;
  74. var
  75.   ft:FILETIME;
  76.   st:SYSTEMTIME;
  77. begin
  78.   UnixTime_2_FileTime(time_in,@ft);
  79.   FileTimeToSystemTime(ft,st);
  80.   result := FormatDateTime('yyyy-mm-dd hh:nn:ss',SystemTimeToDateTime(st));
  81. end;
  82. procedure DoIt(IsModify:Boolean);
  83. type
  84.   _IMAGE_RESOURCE_DIRECTORY = record
  85.     Characteristics: DWORD;
  86.     TimeDateStamp: DWORD;
  87.     MajorVersion: WORD;
  88.     MinorVersion: WORD;
  89.     NumberOfNamedEntries :WORD;
  90.     NumberOfIdEntries: WORD;
  91. //  IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
  92.   end;
  93.   IMAGE_RESOURCE_DIRECTORY = _IMAGE_RESOURCE_DIRECTORY;
  94.   TIMAGERESOURCEDIRECTORY = _IMAGE_RESOURCE_DIRECTORY;
  95.   PIMAGE_RESOURCE_DIRECTORY = ^IMAGE_RESOURCE_DIRECTORY;
  96.   PIMAGERESOURCEDIRECTORY = ^TIMAGERESOURCEDIRECTORY;
  97.   _IRDE_NAME = record
  98.     case Integer of
  99.       0:
  100.         //struct {
  101.         //    DWORD NameOffset:31;
  102.         //    DWORD NameIsString:1;
  103.         // };
  104.         (NameOffset: DWORD);
  105.       1:  (Name: DWORD);
  106.       2:  (Id: Word);
  107.     end;
  108.   _IRDE_OFFSET_DATA = record
  109.       case Integer of
  110.         0:(OffsetToData: DWORD);
  111.         //struct {
  112.         //    DWORD   OffsetToDirectory:31;
  113.         //    DWORD   DataIsDirectory:1;
  114.         //};
  115.         1:(Directory: DWORD);
  116.     end;
  117.   _IMAGE_RESOURCE_DIRECTORY_ENTRY = record
  118.     IRDE_NAME: _IRDE_NAME;
  119.     IRDE_OFFSET_DATA: _IRDE_OFFSET_DATA;
  120.   end;
  121.   IMAGE_RESOURCE_DIRECTORY_ENTRY = _IMAGE_RESOURCE_DIRECTORY_ENTRY;
  122.   PIMAGE_RESOURCE_DIRECTORY_ENTRY = ^IMAGE_RESOURCE_DIRECTORY_ENTRY;
  123.   TIMAGERESOURCEDIRECTORYENTRY = IMAGE_RESOURCE_DIRECTORY_ENTRY;
  124.   PIMAGERESOURCEDIRECTORYENTRY = TIMAGERESOURCEDIRECTORYENTRY;
  125. const
  126.   INVALID_SET_FILE_POINTER = DWORD(-1);
  127. var
  128.   FileName: String;
  129.   hFileSource: THandle;
  130.   dwSourceSize, byte_write: Cardinal;
  131.   pFileSource: PChar;
  132.   I,J,K: Integer;
  133.   dosHeadA: PImageDosHeader;
  134.   ntHeadA: PIMAGENTHEADERS ;
  135.   secHeadA: PIMAGESECTIONHEADER;
  136.   dirResourceA: PIMAGERESOURCEDIRECTORY;
  137.   entryResourceA: PIMAGE_RESOURCE_DIRECTORY_ENTRY;
  138.   dirTemp: PIMAGE_RESOURCE_DIRECTORY;
  139.   entryTemp: PIMAGE_RESOURCE_DIRECTORY_ENTRY;
  140.   dirTempICON: PIMAGE_RESOURCE_DIRECTORY;
  141. begin
  142.     //打开文件
  143.     if (Not OpenDialog1.Execute()) then Exit;
  144.     //取得文件名
  145.     FileName := OpenDialog1.FileName;
  146.     //打开文件
  147.     hFileSource := CreateFile(  PChar(FileName),
  148.                                       GENERIC_READ or GENERIC_WRITE,
  149.                                       FILE_SHARE_READ ,
  150.                                       Nil,
  151.                                       OPEN_EXISTING,
  152.                                       FILE_ATTRIBUTE_ARCHIVE or
  153.                                       FILE_ATTRIBUTE_HIDDEN or
  154.                                       FILE_ATTRIBUTE_NORMAL or
  155.                                       FILE_ATTRIBUTE_SYSTEM,
  156.                                       0
  157.                                      );
  158.     if (hFileSource = INVALID_HANDLE_VALUE) then begin
  159.         MessageBox(Handle,'打开文件失败!''文件时间戳修改器' ,MB_OK or MB_ICONERROR);
  160.         Exit;
  161.     end;
  162.     dwSourceSize := GetFileSize(hFileSource,Nil);
  163.     if (dwSourceSize = INVALID_FILE_SIZE) then begin
  164.         CloseHandle(hFileSource);
  165.         MessageBox(Handle,'无法取得文件大小!','文件时间戳修改器',MB_OK or MB_ICONERROR);
  166.         exit;
  167.     end;
  168.     byte_write := 0;
  169.     //讀取
  170.     pFileSource := HeapAlloc(GetProcessHeap,HEAP_ZERO_MEMORY,dwSourceSize);
  171.     if (pFileSource = Nil) then begin
  172.         CloseHandle(hFileSource);
  173.         MessageBox(Handle,'分配内存失败!','文件时间戳修改器',MB_OK or MB_ICONERROR);
  174.         Exit;
  175.     end;
  176.     if (INVALID_SET_FILE_POINTER = SetFilePointer(hFileSource,0,NIL,FILE_BEGIN)) then begin
  177.         HeapFree(GetProcessHeap,0, pFileSource);
  178.         CloseHandle(hFileSource);
  179.         MessageBox(Handle,'设置文件位置失败!','文件时间戳修改器',MB_OK or MB_ICONERROR);
  180.         Exit;
  181.     end;
  182.     if(Not ReadFile( hFileSource, pFileSource^,dwSourceSize,byte_write,Nil)) then begin
  183.         HeapFree(GetProcessHeap,0, pFileSource);
  184.         CloseHandle(hFileSource);
  185.         MessageBox(Handle,'读取文件失败!','文件时间戳修改器',MB_OK or MB_ICONERROR);
  186.         Exit;
  187.     end;
  188.     if (StrLIComp( pFileSource,'MZ',2)<>0then begin
  189.         HeapFree(GetProcessHeap,0, pFileSource);
  190.         CloseHandle(hFileSource);
  191.         MessageBox(Handle,'文件非PE格式!','文件时间戳修改器',MB_OK or MB_ICONERROR);
  192.         Exit;
  193.     end;
  194.     dosHeadA :=PImageDosHeader(pFileSource); //DOS Header
  195.     ntHeadA := PIMAGENTHEADERS (PChar(Cardinal(pFileSource) + Cardinal( dosHeadA^._lfanew))); //NT Header
  196.     if (ntHeadA^.Signature <> $4550then begin
  197.         HeapFree(GetProcessHeap,0, pFileSource);
  198.         CloseHandle(hFileSource);
  199.         MessageBox(Handle,'文件非PE格式!','文件时间戳修改器',MB_OK or MB_ICONERROR);
  200.         Exit;
  201.     end;
  202.     ListView1.Items.Clear;
  203.     secHeadA := PIMAGESECTIONHEADER (PChar(Cardinal(Pchar(ntHeadA))+ sizeof(IMAGE_NT_HEADERS))); //第一個節的首位址
  204.     with ListView1.Items.Add do begin
  205.       //IMAGE_NT_HEADERS.TimeDateStamp UnixTime 1970-1-1 0:0:0
  206.       Caption := ':' + IntToHex(Integer(@(ntHeadA^.FileHeader.TimeDateStamp)),8);
  207.       SubItems.Add('0x' + IntToHex(Integer((ntHeadA^.FileHeader.TimeDateStamp)),8));
  208.       SubItems.Add(UnixTime_2_FileTime_String_UTC(ntHeadA^.FileHeader.TimeDateStamp));
  209.       SubItems.Add(UinxTime_2_FileTime_String(ntHeadA^.FileHeader.TimeDateStamp));
  210.     end;
  211.     if IsModify then begin
  212.       ntHeadA^.FileHeader.TimeDateStamp := DateTime_2_UnixTime(DateTimePicker1.DateTime); //镜像头时间戳
  213.     end;
  214.     //循環找出.rsrc節
  215.     for i:=0 to ntHeadA^.FileHeader.NumberOfSections - 1 do begin
  216.         //IMAGE_EXPORT_DIRECTORY 导出表变动
  217.         //_IMAGE_IMPORT_DESCRIPTOR or _IMAGE_BOUND_IMPORT_DESCRIPTOR ->_IMAGE_BOUND_FORWARDER_REF
  218.         //IMAGE_LOAD_CONFIG_DIRECTORY32 or IMAGE_LOAD_CONFIG_DIRECTORY64
  219.         //IMAGE_DEBUG_DIRECTORY ->IMAGE_SEPARATE_DEBUG_HEADER ->NON_PAGED_DEBUG_INFO
  220.         //if(strcmp((char *)secHeadA->Name,".rsrc")==0) //找到.rsrc節
  221.         if (secHeadA^.VirtualAddress = ntHeadA^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress) then begin//只对Resource感兴趣
  222.             if(0 <> secHeadA^.SizeOfRawData ) then begin
  223.               dirResourceA := PIMAGERESOURCEDIRECTORY(Pchar(Cardinal(PChar(pFileSource)) + secHeadA^.PointerToRawData)); //得到資源入口位址
  224.               entryResourceA := PIMAGE_RESOURCE_DIRECTORY_ENTRY (PChar(DWORD(PChar(dirResourceA)) + sizeof (IMAGE_RESOURCE_DIRECTORY)));
  225.               with ListView1.Items.Add do begin
  226.                 //IMAGE_RESOURCE_DIRECTORY.TimeDateStamp FileDate 1980
  227.                 Caption := ':' + IntToHex(Integer(@(dirResourceA^.TimeDateStamp)),8);
  228.                 SubItems.Add('0x' + IntToHex(Integer((dirResourceA^.TimeDateStamp)),8));
  229.                 SubItems.Add(FormatDateTime('yyyy-mm-dd hh:nn:ss',FileDateToDateTime_UTC(dirResourceA^.TimeDateStamp)));
  230.                 SubItems.Add(FormatDateTime('yyyy-mm-dd hh:nn:ss',FileDateToDateTime_(dirResourceA^.TimeDateStamp)));
  231.               end;
  232.               if IsModify  then
  233.                 dirResourceA^.TimeDateStamp := DateTimeToFileDate(DateTimePicker1.DateTime);
  234.               for J := 0 to (dirResourceA^.NumberOfIdEntries+dirResourceA^.NumberOfNamedEntries) - 1 do begin //所有資源
  235.                     if (0 <> ((entryResourceA^.IRDE_OFFSET_DATA.Directory shr 31and 1)) then begin
  236.                       dirTemp := PIMAGE_RESOURCE_DIRECTORY (PChar(Cardinal(Pchar(dirResourceA))+(entryResourceA^.IRDE_OFFSET_DATA.Directory and $7fffffff)));
  237.                       with ListView1.Items.Add do begin
  238.                         //IMAGE_RESOURCE_DIRECTORY.TimeDateStamp FileDate 1980
  239.                         Caption := ':' + IntToHex(Integer(@(dirTemp^.TimeDateStamp)),8);
  240.                         SubItems.Add('0x' + IntToHex(Integer((dirTemp^.TimeDateStamp)),8));
  241.                         SubItems.Add(FormatDateTime('yyyy-mm-dd hh:nn:ss',FileDateToDateTime_UTC(dirTemp^.TimeDateStamp)));
  242.                         SubItems.Add(FormatDateTime('yyyy-mm-dd hh:nn:ss',FileDateToDateTime_(dirTemp^.TimeDateStamp)));
  243.                       end;
  244.                       if IsModify then
  245.                         dirTemp^.TimeDateStamp := DateTimeToFileDate(DateTimePicker1.DateTime);
  246.                       entryTemp := PIMAGE_RESOURCE_DIRECTORY_ENTRY (PChar(Cardinal(pchar(dirTemp))+sizeof(IMAGE_RESOURCE_DIRECTORY)));
  247.                       for k:=0 to (dirTemp^.NumberOfIdEntries+dirTemp^.NumberOfNamedEntries) - 1 do begin //子目錄
  248.                         if (((entryTemp^.IRDE_OFFSET_DATA.Directory shr 31and 1) >0then begin //還有子目錄
  249.                             dirTempICON :=PIMAGE_RESOURCE_DIRECTORY (PChar(Cardinal(PChar(dirResourceA)) + (entryTemp^.IRDE_OFFSET_DATA.Directory and $7fffffff )));
  250.                             with ListView1.Items.Add do begin
  251.                               //IMAGE_RESOURCE_DIRECTORY.TimeDateStamp FileDate 1980
  252.                               Caption := ':' + IntToHex(Integer(@(dirTempICON^.TimeDateStamp)),8);
  253.                               SubItems.Add('0x' + IntToHex(Integer((dirTempICON^.TimeDateStamp)),8));
  254.                               SubItems.Add(FormatDateTime('yyyy-mm-dd hh:nn:ss',FileDateToDateTime_UTC(dirTempICON^.TimeDateStamp)));
  255.                               SubItems.Add(FormatDateTime('yyyy-mm-dd hh:nn:ss',FileDateToDateTime_(dirTempICON^.TimeDateStamp)));
  256.                             end;
  257.                             if IsModify then
  258.                               dirTempICON^.TimeDateStamp := DateTimeToFileDate(DateTimePicker1.DateTime);
  259.                         end;
  260.                         Inc(entryTemp);
  261.                       end;
  262.                     end;
  263.                 Inc(entryResourceA);
  264.               end;
  265.             end;
  266.         end;
  267.         Inc(secHeadA)
  268.     end;
  269.     if IsModify  then begin
  270.       SetFilePointer(hFileSource,0,NIL,FILE_BEGIN);
  271.       byte_write := 0;
  272.       WriteFile( hFileSource,pFileSource^,dwSourceSize,byte_write,Nil);
  273.     end;
  274.     CloseHandle(hFileSource);
  275.     HeapFree(GetProcessHeap,0, pFileSource);
  276.     if IsModify  then
  277.       MessageBox(Handle,'修改完成!','文件时间戳修改器',MB_OK or MB_ICONINFORMATION);
  278. end;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值