Тема: Як ззвоні викликати DoAction плагіну Download master?

Код з файлу dmtest_plugin.dpr. Файл проекту:

library dmtest_plugin;

uses
  ShareMem,
  SysUtils,
  Classes,
  dmtest_pluginImpl in 'dmtest_pluginImpl.pas',
  DMPluginIntf in 'DMPluginIntf.pas';

var
 //обʼєкт плагіну
  e: TDMTestPlugIn;
{$R *.res}
function RegisterPlugIn: IDMPlugIn; stdcall;
begin
  try
    e := TDMTestPlugIn.Create;
    Result := e as IDMPlugIn;
    //Result := TDMTestPlugIn.Create;
  except
    Result := nil;
  end;
end;

//Моя процедура
procedure StartDownload(url, save: PWideChar); stdcall;
begin
  e.creare_new_download(UTF8Encode(WideString(url)), UTF8Encode(WideString(save)));
end;

exports RegisterPlugIn;
exports StartDownload;

begin
end.

Код з файлу dmtest_pluginImpl.pas. Реалізація плагіну.

unit dmtest_pluginImpl;

interface

uses DMPluginIntf, Classes, Dialogs;

type
TDMTestPlugIn = class(TInterfacedObject, IDMPlugIn)
  public
    myIDmInterface: IDmInterface;

    procedure PluginInit(_IDmInterface: IDmInterface); stdcall;
    procedure creare_new_download(url, save: WideString); stdcall
end;

implementation


procedure TDMTestPlugIn.PluginInit(_IDmInterface: IDmInterface);//ініціалізія плагіну і передача інтерфейсу для доступу до DM
begin
  myIDmInterface := _IDmInterface;
end;

procedure TDMTestPlugIn.creare_new_download(url, save: WideString); stdcall;
begin
  myIDmInterface.DoAction('AddingURL', '<url>http://www.westbyte.com/plugin</url> <sectionslimit>2</sectionslimit>');
end;
end.

Файл DMPluginIntf.pas. Інтерфейс плагіну:

unit DMPluginIntf;

interface

type
  { IDMInterface }
  IDMInterface = interface(IUnknown)
  ['{B412B405-0578-4B99-BB06-368CDA0B2F8C}']
    function DoAction(action: WideString; parameters: WideString): WideString; stdcall;
  end;

  { IDMPlugIn }
  IDMPlugIn = interface(IUnknown)
  ['{959CD0D3-83FD-40F7-A75A-E5C6500B58DF}']
    function getID: WideString; stdcall;
    //-----info
    function GetName: WideString; stdcall;
    function GetVersion: WideString; stdcall;
    function GetDescription(language: WideString): WideString; stdcall;
    function GetEmail: WideString; stdcall;
    function GetHomepage: WideString; stdcall;
    function GetCopyright: WideString; stdcall;
    function GetMinAppVersion: WideString; stdcall;

    //------
    procedure PluginInit(_IDmInterface: IDmInterface); stdcall;
    procedure PluginConfigure(params: WideString); stdcall;
    procedure BeforeUnload; stdcall;

    function EventRaised(eventType: WideString; eventData: WideString): WideString; stdcall;
    property ID: WideString read getID;
  end;

implementation

end.

Виклик з VB.NET:

<Runtime.InteropServices.DllImport("C:\Program Files\Download Master\Plugins\dmtest_plugin.dll", SetLastError:=True, CharSet:=Runtime.InteropServices.CharSet.Unicode, CallingConvention:=Runtime.InteropServices.CallingConvention.StdCall)> _
Public Sub StartDownload(ByVal url$, ByVal save$)
End Sub

Sub Main()
  StartDownload("http://myurl", "c:\dadas.exe")
  Console.ReadKey()
End Sub

Помилка:

AccessViolationException was unhandled. Attempt to read or write protected memory.

2

Re: Як ззвоні викликати DoAction плагіну Download master?

Тобто у вас є плагін, який працює всередині DM, і ви хочете з іншої програми почати завантаження, віддавши команду через плагін?

3

Re: Як ззвоні викликати DoAction плагіну Download master?

Так. Помилка вилазить саме через звернення до змінної myIDmInterface.

4

Re: Як ззвоні викликати DoAction плагіну Download master?

Вам треба прочитати про взаємодію між процесами. Зараз плагін у вас працює в процесі DM, а StartDownload ви викликаєте в процесі програми написаної на VB.NET. Воно не буде так працювати, бо ви ніяк не передаєте інформацію між процесами.
Як варіант можна додати в проект плагіна новий датамодуль, і кинути на нього компонент TIdCmdTCPServer. Він дозволяє отримувати команди по мережі, на певний порт. Відправляти команди можна іншою програмою за допомогою TIdTCPClient, або просто писати в порт будь-яким зручним способом.
Ось приклад датамодуля:

unit Unit2;

interface

uses
  System.SysUtils, System.Classes, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer,
  IdCmdTCPServer, IdCommandHandlers, IdURI, Unit1;

type
  TDataModule2 = class(TDataModule)
    IdCmdTCPServer1: TIdCmdTCPServer;
    procedure IdCmdTCPServer1CommandHandlers0Command(ASender: TIdCommand);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  DataModule2: TDataModule2;

implementation

{%CLASSGROUP 'System.Classes.TPersistent'}

{$R *.dfm}

procedure TDataModule2.IdCmdTCPServer1CommandHandlers0Command(ASender: TIdCommand);
begin
  StartDownload(TIdURI.URLDecode(ASender.Params.Values['url']),
    TIdURI.URLDecode(ASender.Params.Values['filename']));
end;

end.

Його форма у текстовому вигляді:

object DataModule2: TDataModule2
  Height = 716
  Width = 826
  PixelsPerInch = 192
  object IdCmdTCPServer1: TIdCmdTCPServer
    Active = True
    Bindings = <>
    DefaultPort = 4567
    CommandHandlers = <
      item
        CmdDelimiter = '?'
        Command = 'downloadurl'
        Disconnect = True
        ExceptionReply.Code = '500'
        Name = 'TIdCommandHandler0'
        NormalReply.Code = '200'
        NormalReply.Text.Strings = (
          'OK')
        ParamDelimiter = '&'
        ParseParams = True
        Tag = 0
        OnCommand = IdCmdTCPServer1CommandHandlers0Command
      end>
    ExceptionReply.Code = '500'
    ExceptionReply.Text.Strings = (
      'Unknown Internal Error')
    Greeting.Code = '200'
    HelpReply.Code = '100'
    HelpReply.Text.Strings = (
      'Help follows')
    MaxConnectionReply.Code = '300'
    MaxConnectionReply.Text.Strings = (
      'Too many connections. Try again later.')
    ReplyTexts = <>
    ReplyUnknownCommand.Code = '400'
    ReplyUnknownCommand.Text.Strings = (
      'Unknown Command')
    Left = 264
    Top = 320
  end
end

А ось приклад відправки команди:

  IdTCPClient1.Connect('127.0.0.1', 4567);
  IdTCPClient1.IOHandler.WriteLn('downloadurl?url=http%3A%2F%2Fmyurl&filename=c%3A%5Cdadas.exe');
  Memo1.Lines.Add(IdTCPClient1.IOHandler.ReadLn());
  Memo1.Lines.Add('');
  IdTCPClient1.Disconnect;

Навіть більше того, просте відкриття у браузері лінки http://127.0.0.1:4567/downloadurl?url=h … Cdadas.exe - Це також запис в порт, просто формат команд там трохи інший.

Подякували: javascriptIsLife1