同样的代码为何在delphi7编译运行正常~而在Xe2会出错呢?
本帖最后由 iislove 于 2012-09-05 20:01:38 编辑 代码如下:
unit UnitUtil;
interface
uses
System.SysUtils, System.Classes, Winapi.Windows;
function HexToString(S:string):string;
function HexScan(t:tstream; s:string):integer;
function HexRead(t:tstream; s:DWORD; b:Byte):Integer;
function ReadAddress(FlagCode:string;MyFile:TFileStream;Offset:Integer):string;
function ReadOffsetAdress(FlagCode:string;MyFile:TFileStream;Offset:Integer;const nSize:Integer=4):string;
function ReadCallAddress(FlagCode:string;MyFile:TFileStream;Offset,Modify:Integer):string;
implementation
function HexToString(S: string): string;//转十六进制字符串
var
i: integer;
tmpstr:string;
Begin
Result := '';
for i := 1 to Length(S) do
begin
if ((i mod 2)=1) then
begin
tmpstr:=Copy(S, i, 2);
if tmpstr='**' then
Result:=Result+'*'
else
Result:=Result + Chr(StrToInt('0x' + Copy(S, i, 2)));
end;
end;
end;
function HexScan(t:tstream; s:string):integer; //找地址所在位置
var
i, j: integer;
p: pchar;
begin
Result:=-1;
getmem(p, t.size); // ---- 分配内存
t.readbuffer(p^, t.size ); // ---- 读
for i:=0 to t.size -1 do
begin
for j:=1 to length(s) do
begin
if s[j]='*' then //匹配通配符'*',强制下一轮循环
Continue;
if p[i+j]<>s[j] then // ---- 有一个不同即退出
begin
break;
end;
end;
if j>length(s) then // ---- 依据
begin
Result:=i+1;
break;
end;
end;
freemem(p);
t.seek(0, soBeginning); // ---- 返回文件头
end;
function HexRead(t:tstream; s:DWORD; b:Byte):Integer;//读地址所在位置
var
d: DWORD;
begin
t.seek(s, soBeginning); // ---- 到Length位置;
t.Read(d, b); // ---- 读b字节
Result:=d;
t.seek(0, soBeginning); // ---- 返回文件头
end;
function ReadAddress(FlagCode:string;MyFile:TFileStream;Offset:Integer):string;
var
Addr:Integer;
begin
Addr := HexScan(MyFile, HexToString(FlagCode));
if Addr = -1 then
Result := 'Null'
else
Result :='$' + IntToHex($400000 + Addr + Offset, 1);
end;
function ReadOffsetAdress(FlagCode:string;MyFile:TFileStream;Offset:Integer;const nSize:Integer=4):string;
var
Addr:Integer;
begin
Addr:=HexScan(MyFile,HexToString(FlagCode));
if Addr=-1 then
Result:='Null'
else
Result:='$'+ IntToHex(HexRead(MyFile, Addr + Offset, nSize),1)
end;
function ReadCallAddress(FlagCode:string;MyFile:TFileStream;Offset,Modify:Integer):string;
var
Addr:Integer;
begin
Addr:=HexScan(MyFile,HexToString(FlagCode));
if Addr=-1 then
Result:='Null'
else
Result := '$' + IntToHex(($400000 + Addr) + HexRead(MyFile, Addr+Offset, 4) + Modify, 1)
end;
end.
unit UnitMain;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, UnitUtil;
type
TMainForm = class(TForm)
edt_Path: TEdit;
Label1: TLabel;
btn_GetClient: TButton;
dlgOpen: TOpenDialog;
lv_Show_Addr: TListView;
procedure btn_GetClientClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
procedure TMainForm.btn_GetClientClick(Sender: TObject);
var
MyFile: TFileStream;
VerionFilePath:string;
VerionFile:TextFile;
Version:string;
tmp_Addr:Integer;
begin
if not dlgOpen.Execute then
Exit;
edt_Path.Text := dlgOpen.FileName;
VerionFilePath := ExtractFilePath(edt_Path.Text)+'..\'+'config\element\version.sw';
if FileExists(VerionFilePath) then
begin
AssignFile(VerionFile,VerionFilePath);
Reset(VerionFile);
Readln(VerionFile,Version);
Self.Caption:=Self.Caption+'--客户端版本号:'+Copy(Version,1,3);
end
else
begin
Self.Caption:=Self.Caption+'--无法检测到客户端版本';
end;
if edt_Path.Text<>'' then
begin
MyFile:=TFileStream.Create(edt_Path.Text,fmShareDenyNone);
lv_Show_Addr.Items.Clear;
try
with lv_Show_Addr.Items.Add do
begin
Caption:='基址';
SubItems.Add(ReadOffsetAdress('53578b4820e8',MyFile,-$4));
end;
except
on Err:Exception do
begin
ShowMessage('异常类名称:'+Err.ClassName+#13#10+'异常信息'+Err.Message);
end;
end;
end;
end;
end.
8,把Char转化为小写用什么?
答案:试试看Character单元的新函数 ToUpper ToLower。以前我都是用System里面的UpCase函数,现在依然可用不过却找不到LowCase DownCase之类的函数,困扰我好久好久。索性全使用Character单元提供的新函数吧。
9,编译期警告:[DCC Warning] Unit1.pas(31): W1057 Implicit string cast from 'AnsiString' to 'string'
如果你的代码中包含了两种字符串(Unicode、Ansi)之间进行隐式转化的时候就会出现该提示。
如下代码就会触发该警告:
var Unicode:String; Ansi:AnsiString; begin Ansi:='test..'; Unicode:=Ansi;
把旧版本的Delphi项目升级到2010,我通常都是借助编译警告来快速寻找需要改动的部分。通常你可以把赋值双方都声明为String(默认影射到UnicodeString),就可以避免该警告。但如果你确定必须在此处保留Ansi并进行转化的时候,建议你显式的转化他们(例如:Unicode:=String(Ansi);),这样可以避免该警告,方便你在升级过程中继续寻找其他需要修改的地方。
10,Readln Writeln 写入文件时候要注意
如果你传给Writeln一个AnsiString,那么它也会在文件中写入AnsiString,那么你读取得时候就必须传给Readln一个AnsiString的类型,否则就是乱码。例如旧工程的配置文件是Ansi的,而你已经把相关读取配置的代码升级为支持Unicode,那么运行工程前你首先要用记事本之类的工具把配置文件另存为成Unicode编码。当然你还要注意跳过Unicode文件头的两个字节FE FF。
11,别再用String来操作二进制数据了
一定要记住String只是字符串,不要把它当作缓冲区、内存流使用。我的项目中,有很多地方是使用字符串来处理二进制数据,导致在本次升级中颇为费脑。如果当时用TBytes或TStream就好了。
反面教材:
var Int1,Int2,Int3,Int4:Integer; Buf:String; begin SetLength(Buf,12); Move(Int1,Buf[1],SizeOf(Integer)); Move(Int1,Buf[5],SizeOf(Integer)); Move(Int1,Buf[9],SizeOf(Integer)); Buf:=Buf+'前面有3个Integer。';
12,还是PChar
注意在2010中是这样的:
PChar= Pointer to a WideChar array;
PAnsiChar = Pointer to a AnsiChar array;
如果你还像是在Delphi 7中那样:PChar(AnsiString)那后果过是很严重的。
[解决办法]
HexScan里
for i := 0 to t.Size div 2 - 1 do
[解决办法]