小弟由于要通过Windows客户端发批命令去一台Linux主机上执行相关命令,因此想用Indy控件写一个通过telnet方式去执行命令的dll来供其他开发工具调用。
由于我第一次写DLL,出现问题很大。
 调用出现主要错误提示如下:
                   ---------------------------
Debugger Exception Notification
---------------------------
Project Project2.exe raised exception class EAccessViolation with message 'Access violation at address 00245DD9 in module 'Project1.dll'. Read of address 00000000'. Process stopped. Use Step or Run to continue.  现把源代码发布如下:(敬请高手指正)DLL部分:
  library project1;{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }uses
  SysUtils,
  Classes,
  IdTCPConnection, IdTCPClient, IdTelnet;//{$R *.res}Function Telnet(host,user,pwd,command:pchar;handle:Thandle) :integer;stdcall;
  var
   i : integer;
   lhost,luser,lpwd,lcommand:string;
   IdTelnetDemo: TIdTelnet;
begin   lhost:=string(host);
   luser:=string(user) ;
   lpwd:=string(pwd);
   lcommand:=string(command)  ;
 try
   //CoInitialize(nil);
   IDTelnetDemo.Create(nil);
   IDTelnetDemo.Host :=lhost;
   IDTelnetDemo.port :=23;
   IdTelnetDemo.Connect;
   if IdTelnetDemo.Connected then
    begin
      for i := 1 to length(luser) do
        begin
           IdTelnetDemo.SendCh(luser[i]);
           IdTelnetDemo.SendCh(#13);
        end;
      for i:= 1 to length(lpwd) do
         begin
           IdTelnetDemo.SendCh(lpwd[i]);
           IdTelnetDemo.SendCh(#13);
         end;
      for i:= 1 to length(lcommand) do
         begin
           IdTelnetDemo.SendCh(lcommand[i]);
           IdTelnetDemo.SendCh(#13);
         end;         result:=1;
         IdTelnetDemo.Disconnect;
      end
      else
         result:=2;
  //except
        //result:=3;
  finally
      begin
        IdTelnetDemo.Destroy;
      end;
  end;end;exports
   Telnet;
end.
 Delphi调用程序部分:unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, Buttons;type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    GroupBox1: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    edtID: TEdit;
    edtUser: TEdit;
    edtHost: TEdit;
    GroupBox2: TGroupBox;
    Memo1: TMemo;
    BitBtnOK: TBitBtn;
    BitBtnCancel: TBitBtn;
    procedure BitBtnCancelClick(Sender: TObject);
    procedure BitBtnOKClick(Sender: TObject);  private
    { Private declarations }
  public
    { Public declarations }
  end;
  Function Telnet(host:string;user:string;id:string;command:string) :integer;stdcall;
var
  Form1: TForm1;implementation
{$R *.dfm}
Function Telnet;external 'Project1.dll' name 'Telnet';procedure TForm1.BitBtnCancelClick(Sender: TObject);
begin
close;
end;procedure TForm1.BitBtnOKClick(Sender: TObject);
var
host,user,id,command :string;
i:integer;
begin
    host:='192.168.5.2';
    user:='bonny';
    id:='happysky';
    command:='mkdir telnet';
    i:=Telnet(pchar('192.168.5.2'),pchar('bonny'),pchar('happysky'),pchar('mkdir telnet'));
    edtuser.text:=inttostr(i);
end;end.  这个调用程序是一个Demo,最终结果是想传一个批处理命令给Linux主机去执行。用户只要在客户机上点击一下相关选项就行了。
  现在问题只是在传递参数过程中出现问题,不知这种方式的可执行程度如何,且程序当中还有未知的问题敬请高手指教。                                  谢谢!!!

解决方案 »

  1.   

    刚才Delphi调用程序部分那个函数Telnet声明部分贴错了,应该如下: Function Telnet(host,user,id,command:pchar) :integer;stdcall;但是错误还是如上所示。敬请指教!!
      

  2.   

    这样实现是可行的,你跟踪执行一下这个DLL先自己找找出错的地方.
      

  3.   

    你好,halfdream!传参数的问题我已经解决了。也就是上面的故障已经解决了!
    现在又出现一个新问题。也可能是我的实现方法上有错误。
    在这里再重新讲述一下我要解决的问题:
      用delphi写一个Dll,这个dll主要实现通过telnet协议与unix主机通信。然后供其他应用程序调用。(主要用处是通过它发命令给unix主机去执行)。我想,这大概就是WinSocket编程范围了。我看到delphi提供了indy控件,所以我想通过indy控件集合中telnet控件来实现它。但是现在好像用普通dll方式不行,大概必须要用Activex方式包装才行。应为indy控件的Create(AOwner: TComponent)方法中的参数AOwner必须是一个容器控件。我现在思想比较混乱,敬请高手指教!!
      

  4.   

    普通DLL不行?怎么会呢?它需要注意的一个处理地方是.TELNET是长连接的,你要让idTcpclient对象保持在内存中.另外,普通DLL同COM的DLL都是动态库,装入内存这方面是一样的.indy控件它创建需要OWNER,那你就把它扔在一个数据模块吧,
    在DLL里面动态创建这个数据模块还可靠些.
      

  5.   

    To halfdream:我把它改放在一个数据模块(TDataModule)里了,不用form了,在dll入口函数处创建了这个TIdTelnet实例。
    但发现又一问题:在调用connect方法后,IdTelnetDemoDataAvailable事件没有响应。但是如果不用dll,在普通delphi里调用indy控件的telnet控件事,一样情况下IdTelnetDemoDataAvailable事件是有响应的。敬请指教!!