Delphi开发更新程序(调用WebService)

    刚毕业找了个软件公司,到公司找老大接了第一个任务:写一个更新程序,用来更新公司产品的客户端 。本人水平实在有限,还好大学读的是“百度专业” ,最后勉强做了个Setup.exe出来。现在把涉及到的知识点记录在这里,希望对刚入行的朋友们(我!)有帮助。

IDE:Delphi 7

1、调用Web Service(C#)

导入WSDL:在你建立的工程里点File->New->Other->WebService->WebService Importer,然后按提示一步步来。

如何获得WSDL地址:如果老大给了你一个URL,可以访问他写的WS,那么只需要在这个URL上加'?wsdl'就是WSDL地址了。

如果要调用的WS需要传递参数,则需要在默认模式下产生的WSDL文件内initialization部分加一句:
InvRegistry.RegisterInvokeOptions(TypeInfo(????Soap), ioDocument);

使用WebSeriver里的THTTPRIO控件,在需要调用WS的程序段,
声明变量 a:????Soap,
然后初始化 a := HTTPRIO1 as ????Soap;
这样就可以直接用 a.WebMethodName();来调用了。

2、Http方式下载:
使用IdHTTP控件

IdHTTP采用阻塞方式(瞎掰的:)
表现结果为:当不使用多线程技术把下载的任务独立出来,那么开始下载时程序将无法响应任何操作,除非下载完成。
所以有时候你需要使用一个到多个小小的线程来做这些事情。如果你恰巧和某人(我!)一样不了解多线程技术,那么有个好消息就是,我花了大概7个小时从0开始搞定了这个问题,当然不涉及复杂的多线程设计、同步什么的。毕竟我们只需要满足任务要求就OK了,如果那些知识需要深入了解,可以稍候再学。

一下是利用IdHTTP的功能,写的一个自定义函数。

procedure TForm1.HttpDownLoad(aURL, aFile: string; bResume: Boolean);
var
  tStream: TFileStream;
  FileTarget:string;
  DirList:TStringList;
  tmpCurrectTestDir:String;
  i:integer;
begin
  // ´´½¨È«Â·¾¶Îļþ¼Ð
  FileTarget:= aFile;
  DirList := SplitString( FileTarget,'');
  tmpCurrectTestDir := tmpCurrectTestDir + DirList[0] + '';
  for i:=1 to DirList.count-2 do
  begin
    tmpCurrectTestDir := tmpCurrectTestDir + DirList[i] + '';
    if not DirectoryExists(tmpCurrectTestDir) then
      CreateDirectory( Pchar(tmpCurrectTestDir),nil);
  end;
  if not Thread1.Terminated then
  begin
    try
       // Èç¹ûÎļþÒÑ´æÔÚ
      if FileExists(aFile) then
      begin
        tStream := TFileStream.Create(aFile, fmOpenWrite);
        IdHTTP1.Request.ContentRangeStart := 0;
        IdHTTP1.Get(aURL,tStream); // ¿ªÊ¼ÏÂÔØ
        try
          tStream.Free;
        except
        end;
      end
      else
      begin
        tStream := TFileStream.Create(aFile, fmCreate);
        IdHTTP1.Request.ContentRangeStart := 0;
        IdHTTP1.Get(aURL,tStream); // ¿ªÊ¼ÏÂÔØ
        try
          tStream.Free;
        except
        end;
      end;
    Except
      abort;
    end;
  end;// if not Thread1.Terminated
end;

 关于线程:

以下代码写在 Uses单元下面。控件TYPE单元上面。

//线程类
type
  TThread1 = class(TThread)
  // Variable
  protected
    FMMUrl:string;
    FDestPath:string;
    FSubJ:string;
  procedure Execute;override;
  public
  // Methods
  // Constructor/Destructor
    constructor Create();
  end;

3、访问和下载都搞定了,现在要解决的是字符串的类型转换问题。

这里可能涉及到的字符串类型是: array of byte ,array of string ,TStringList。
最常用的字符串操作函数:Copy , SetLength, Length ,  StrLen, Chr , Inc ,Pos。
我在这里收集了一些字符串转换函数,但是有时候不得不自己写一些函数来满足具体的转换要求。
(就不弄成图片啦,方便需要的朋友Ctrl+C)

以上就是最主要的技术点。解决这3个方面的问题了,其他的问题都不难。比如
获取当前系统内的某个盘盘符
读取无类型文件、二进制文件
进度条的设置
等等。

需要注意的地方是:
1、如果申请了一个变量,模板,类实例...注意把它Free,Terminate,Destroy,Delete,或者别的什么。一定要释放。
2、有可能的话,所有的变量全部都要初始化,免得出现莫名其妙的错误。同样的,能手动释放的就释放。
3、如果出了什么问题,一定是代码有问题。不要去怀疑编译器,某人(我!)水平还没达到质疑编译器的程度。

最后,如果碰巧你也在做这方面的任务,而且你又是比我还新的新手~ 欢迎来问我~

//***********************************************************************
//
//                            自定义函数/方法
//
//***********************************************************************
//=======================================================================
// Helper Methods
//=======================================================================
function TForm1.GetTempDir(): string;//获取系统临时文件夹
var
  Buffer: array[0..1023] of Char;
begin
  SetString(Result, Buffer, GetTempPath(SizeOf(Buffer), Buffer));
end;
//=======================================================================
// Helper Methods
//=======================================================================
function TForm1.SplitString(const Source,ch:string):TStringList;// Split() in Delphi
var
  temp:String;
  i:Integer;
begin
  Result:=TStringList.Create;
  if Source=''  then exit;
  temp:=Source;
  i:=pos(ch,Source);
  while i<>0 do
  begin
    Result.add(copy(temp,0,i-1));
    Delete(temp,1,i+length(ch)-1);
    i:=pos(ch,temp);
  end;
  Result.add(temp);
end;
//=======================================================================
// Helper Methods
//=======================================================================
function TForm1.LastIndexOf(const s,str:String):integer;
var
  i: integer;
  tmpStr:string;
begin
  tmpStr:= s;
  i := Pos(str,tmpStr);
  while i <>0 do
  begin
    Delete(tmpStr,1,i);
    i := Pos(str,tmpStr);
  end;
  Result := Pos(tmpStr,s);
end;
//=======================================================================
// Helper Methods
//=======================================================================
function TForm1.StrToByte(GTuserProductSN:string):TByteDynArray;
var
  a: TByteDynArray;
begin
  SetLength(a, Length(GTuserProductSN));
  Move(GTuserProductSN[1], a[0], Length(GTuserProductSN));

  Result:= a;
end;
//=======================================================================
// Helper Methods
//=======================================================================
function TForm1.HexCharToInt(ch:char):integer;// 16½øÖƵÄ×Ö·ûת³ÉÏà¶ÔÓ¦µÄÕûÊý
begin
  Case ord(ch) of
  65:Result:= 10;
  66:Result:= 11;
  67:Result:= 12;
  68:Result:= 13;
  69:Result:= 14;
  70:Result:= 15;
  else
  Result:= StrToint(ch);
  end;
end;
//=======================================================================
// Helper Methods
//=======================================================================
function TForm1.HexCharToStr(const S:string):string;
var
  a:string;
  i:integer;
begin
  a := '';
  i := 1;
  while i < length(s) do
  begin
    a := a + chr(HexCharToInt(s[i])*16 + HexCharToInt(s[i+1]));
    i := i + 2;
  end;
  Result := a;
end;
//=======================================================================
// Helper Methods
//=======================================================================
//获取磁盘空间
function TForm1.GetDiskSpace(const _type,DriverName:String):Cardinal;
var
driver:pchar;
sec1, byt1,TotalSpace, FreeSpace:longword;
begin
driver:= Pchar(DriverName + ':/');//DriverName like : C D E H ,not C: or C:/
GetDiskFreeSpace(driver, sec1, byt1, FreeSpace, TotalSpace);
FreeSpace := FreeSpace * sec1 * byt1;
TotalSpace := TotalSpace * sec1 * byt1;
if _type = 'Free' then
  Result:= FreeSpace
else if _type = 'Total' then
  Result:= TotalSpace
else
  Result:= 0;
end;
//=======================================================================
// Helper Methods
//=======================================================================
function TForm1.DoCopyDir(sDirName:String; sToDirName:String):Boolean;
var
   hFindFile: Cardinal; 
   t,tfile:String;
   sCurDir:String[255];
   FindFileData:WIN32_FIND_DATA;
begin
   sCurDir:=GetCurrentDir;
   ChDir(sDirName);
   hFindFile:=FindFirstFile('*.*',FindFileData);
   if hFindFile<>INVALID_HANDLE_VALUE then
   begin
        if not DirectoryExists(sToDirName) then
           ForceDirectories(sToDirName);
        repeat
              tfile:=FindFileData.cFileName;
              if (tfile='.') or (tfile='..') then
                 Continue;
              if FindFileData.dwFileAttributes=
              FILE_ATTRIBUTE_DIRECTORY then
              begin
                   t:=sToDirName+'/'+tfile;
                   if  not DirectoryExists(t) then
                       ForceDirectories(t);
                   if sDirName[Length(sDirName)]<>'/' then
                      DoCopyDir(sDirName+'/'+tfile,t)
                   else
                      DoCopyDir(sDirName+tfile,sToDirName+tfile);
              end
              else
              begin
                   t:=sToDirName+'/'+tFile;
                   CopyFile(PChar(tfile),PChar(t),False);
              end;
        until (FindNextFile(hFindFile, FindFileData)=false);
        Windows.FindClose(hFindFile);  
   end
   else
   begin
        ChDir(sCurDir);
        result:=false;
        exit;
   end;
   ChDir(sCurDir);
   result:=true;
end;

function TForm1.CopyDir(sDirName:String; sToDirName:string):Boolean;
begin
      if Length(sDirName)<=0 then
         exit;
       Result:=DoCopyDir(sDirName,sToDirName);
end;
//=======================================================================
// Helper Methods
//=======================================================================
function TForm1.DeleteDir(sDirName:string):Boolean;
var
  sr:   TSearchRec;
  sPath,sFile:   String;
begin
  try
    if   Copy(sDirName,Length(sDirName),1)   <>   '/'   then
      sPath   :=   sDirName   +   '/'
    else
      sPath   :=   sDirName;
    if   FindFirst(sPath+'*.*',faAnyFile,   sr)   =   0   then
    begin
      repeat
        sFile:=Trim(sr.Name);
        if   sFile='.'   then   Continue;
        if   sFile='..'   then   Continue;
        sFile:=sPath+sr.Name;
        if   (sr.Attr   and   faDirectory)<>0   then
          DeleteDir(sFile)
        else   if   (sr.Attr   and   faAnyFile)   =   sr.Attr   then
          DeleteFile(sFile);                                                
      until   FindNext(sr)   <>   0;
      FindClose(sr);
    end;
    RemoveDir(sPath);
  except
  Result:= false;
  end;
end;

你可能感兴趣的:(Delphi开发更新程序(调用WebService))