Dll C# no Delphi 7

Asked

Viewed 2,883 times

6

I need to generate a file ".ini" in the briefcase "C: Windows Temp USB.ini" containing information from the printers installed for another prehistoric program to consume. I created the following (gambiarra) dll in c# :

    [ClassInterface(ClassInterfaceType.None),     
     Guid("C92C5DDA-7766-4CBC-8141-6817DDE97B6F")]    
public class Solucoes 
{
    public Solucoes()
    {
    }

    public void getPrinters()
    {
        string line = "";
        string passaDireto = "";

        FileIOPermission f2 = new FileIOPermission(FileIOPermissionAccess.AllAccess, @"C:\Windows\Temp\");

        if (File.Exists(@"C:\Windows\Temp\USB.ini"))
        {
            System.IO.StreamReader file = new System.IO.StreamReader(@"C:\Windows\Temp\USB.ini");
            while ((line = file.ReadLine()) != null)
            {
                if ((line.ToUpper().Contains("PASSADIRETO="))) passaDireto = line;
            }
            file.Close();
            File.Delete(@"C:\Windows\Temp\USB.ini");
        }
        File.Create(@"C:\Windows\Temp\USB.ini").Close();
        TextWriter arquivo = System.IO.File.AppendText(@"C:\Windows\Temp\USB.ini");
        arquivo.WriteLine("[Porta]");

        ManagementObjectSearcher printers = new ManagementObjectSearcher("SELECT * from Win32_Printer");
        foreach (ManagementObject item in printers.Get())
        {
            string print = "", port = "";
            if ((bool)item.GetPropertyValue("Shared"))
            {
                print = (string)item.GetPropertyValue("ShareName");
            }
            else print = (string)item.GetPropertyValue("Name");
            port = (string)item.GetPropertyValue("PortName");

            if (print.Length > 44) arquivo.WriteLine(string.Concat(print.Substring(0, 43), "=", port));
            else arquivo.WriteLine(string.Concat(print, "=", port));
        }

        if (!string.IsNullOrEmpty(passaDireto))
        {
            arquivo.WriteLine("[Opcoes]");
            arquivo.WriteLine(passaDireto);
        }
        arquivo.Close();                            
    }
}

I left the dll as COM visible and registered as well. To register I used regasm.exe SolucoesClassLibrary.dll /tlb /codebase

I created her Unit at Delphi 7 and tried to make the call:

var
    Impressora: ISolucoes;

begin
    Impressora.getPrinters();
end;

When I run it launches this Exception just in time I call the dll routine done in c#. Exception EAccessViolation in module USB.exe at 0006B3BA. Access violation at address 0046B3BA in module 'USB.exe'. Read of address 000000 00.

Someone can help me?

  • Configure DLL to be COM Visible, add DLL as Activex Control in Delphi

  • I already did that, the problem is that I can’t call the getInstalledPrinters function

2 answers

5


I use a "cake recipe" that always works for me.

Follows:

Create an interface:

namespace EscreveINI
{
    using System.Runtime.InteropServices;

    [InterfaceType(ComInterfaceType.InterfaceIsDual), Guid("80911B7A-608D-4A54-B51B-CF09E512CAD4")]
    public interface IEscreveIniClass
    {
        void Escrever();
    }
}

And a class:

namespace EscreveINI
{
    using System.IO;
    using System.Runtime.InteropServices;

    [ClassInterface(ClassInterfaceType.None), Guid("C77906F8-59A9-4187-B818-2F6CABF1A2AF")]
    public class EscreveIniClass : IEscreveIniClass
    {
        public void Escrever()
        {
            File.Create(@"C:\Windows\Temp\USB.ini").Close();
        }
    }
}

Mark in the Assembly Information of the Classlibrary the option "Make Assembly COM-Visible"

And in the build check the "Register for COM Interop"

After that copy the DLL to the desired location along with the tlb file and run the command the following registry command:

set path="%path%";C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319
regasm /tlb:EscreveINI.tlb EscreveINI.dll /codebase

Next in Delphi go to Project, Import Type Library and search for tlb and click Create Unit.

Then just use it like this:

procedure TForm1.Button1Click(Sender: TObject);
var
  lEscreveArquivo: IEscreveIniClass;
begin
  lEscreveArquivo := CoEscreveIniClass.Create();
  lEscreveArquivo.Escrever;
end;

0

Once I needed to work with Delphi 5 XML. Dai made a dll in C# and created a Unit in Delphi to serve interface.

I’ll give a code stop, it’s kind of big and has many functions to call the methods that were created in my class . Net

I basically carry the dll and keep it in memory in a static class. You can ignore 90% of the code that is used to manipulate an array (of arrays) of strings and "simulate" a pseudo xml.

Check out the part where Progid da dll is!

//****************************************************************************//
//***  Unit para servir de interface para                                  ***//
//***  a DLL útil implementada em .Net                                     ***//
//***                                                                      ***//
//***  28/04/2010                                                          ***//
//***  by Jean Charles Bulinckx                                            ***//
//****************************************************************************//
unit uUtil;

interface
uses
  ComObj, ComCtrls;

type
  // XML serializado retornado pela DLL
  tArrayNos = Array of Array of String;

  // estrutura que representa o XML DEsSerializado pelo Delphi
  tNo = class
     nome:String;
     valor:String;
     id:String;
     idPai:String;
     filhos:Array of tNo;
  end;

  tArrNo = Array of tNo;

  tUtil = class
  private
     // Mantém a DLL em memória
     DLL: Variant;
  public
     // Metódos que chamam a dll
     function Importar(servico, arquivo, login, senha: String):String;
     function LeXML(arquivo:String):tArrayNos;
     function Criptografar(dados:String; descriptar:Boolean):String;
     // Métodos para ler/montar árvore
     function EncontrarFilho(nome: String; raiz: tNo):tNo;
     function EncontrarFilhos(nome: String; raiz: tNo):tArrNo;
     function EncontrarRaiz(id: String; xml: tArrayNos):tNo;
     function MontarFilhos(raiz:tNo; xml: tArrayNos):tNo;
     function DeSerializarArvore(xml: tArrayNos):tNo;
     function ReSerializarArvore(no: tNo):tArrayNos;
  published
     Constructor Inicializar();
  end;

  // ProgId da DLL
Const
  NomeClasse:String = 'Xpto.Util';

implementation

function InstanciaClasse(strClasse: String):Variant;
begin
   result := CreateOleObject(strClasse);
end;

// Função que retorna uma instância da classe
Constructor tUtil.Inicializar();
begin
   inherited;
   self.DLL := InstanciaClasse(NomeClasse);
end;    

// ********************************
// *** Funções que chamam a DLL ***
// ********************************
function tUtil.Importar(servico, arquivo, login, senha: String):String;
begin
   result := self.DLL.ChamarWSB(servico,arquivo, login, senha, false);
end;

function tUtil.LeXML(arquivo:String):tArrayNos;
begin
   result := self.DLL.LerXML(arquivo);
end;

function tUtil.Criptografar(dados:String; descriptar:Boolean):String;
begin
   result := self.DLL.Criptografar(dados, descriptar);
end;
// ********************************
// *** Funções que chamam a DLL ***
// ********************************

// *****************************************************
// *** Funções para "ler" a árvore de nós (tags) xml ***
// *****************************************************

// Encontra o filho pelo nome
function tUtil.EncontrarFilho(nome: String; raiz: tNo):tNo;
var no:tNo;
 i:integer;
begin
   no := tNo.Create();
   for i := 0 to Length(raiz.filhos) - 1
   do begin
      if (raiz.filhos[i].nome = nome)
      then begin
         no := raiz.filhos[i];
      end;
   end;
   result := no;
end;

// Encontrar uma coleção de filhos pelo nome
function tUtil.EncontrarFilhos(nome: String; raiz: tNo):tArrNo;
var arrNo:tArrNo;
 i,l:integer;
begin
   for i := 0 to Length(raiz.filhos) - 1
   do begin
      if (raiz.filhos[i].nome = nome)
      then begin
         l := Length(arrNo);
         SetLength(arrNo,l+1);
         arrNo[l] := raiz.filhos[i];
      end;
   end;
   result := arrNo;
end;

// Acha quem é a raiz (quem não tem pai)
function tUtil.EncontrarRaiz(id: String; xml: tArrayNos):tNo;
var no:tNo;
 i:integer;
 id2:String;
begin
   no := tNo.Create();
   for i := 0 to Length(xml) - 1
   do begin
      id2 := xml[i,3];// id do pai
      if (id=id2)
      then begin
         no.nome := xml[i,0];
         no.valor := xml[i,1];
         no.id := xml[i,2];
         no.idPai := xml[i,3];
      end;
   end;
   result := no;
end;

// Monta um ramo de árvore recursivamente
function tUtil.MontarFilhos(raiz:tNo; xml: tArrayNos):tNo;
var
 no:tNo;
 i,l:integer;
 idPai:String;
begin
   for i := 0 to Length(xml) - 1
   do begin
      idPai := xml[i,3];//id do pai
      if (idPai = raiz.id)
      then begin
         no := tNo.Create();
         no.nome := xml[i,0];
         no.valor := xml[i,1];
         no.id := xml[i,2];
         no.idPai := xml[i,3];
         no := MontarFilhos(no,xml);
         l:=Length(raiz.filhos);
         SetLength(raiz.filhos,l+1);
         raiz.filhos[l]:=no;
      end;
   end;
   result := raiz;
end;

// Remonta numa estrutura em memória o .XML serializado pela DLL
function tUtil.DeSerializarArvore(xml: tArrayNos):tNo;
var raiz:tNo;
begin
   raiz := EncontrarRaiz('00000000-0000-0000-0000-000000000000', xml);

   // Monta os filhos recursivamente
   raiz := MontarFilhos(raiz, xml);

   // Retorna a árvore em memória
   result := raiz;
end;

// ReSerializa uma árvore para um Array of Arrays of String
function tUtil.ReSerializarArvore(no: tNo):tArrayNos;
var xml,ramo:tArrayNos;
i,j,lenPai,lenFilho,lenNeto:integer;
begin
   ramo := nil;
   if no <> nil
   then begin
      SetLength(xml,1,4);
      xml[0,0] := no.nome;
      xml[0,1] := no.valor;
      xml[0,2] := no.id;
      xml[0,3] := no.idPai;
      // recursão
      lenFilho := Length(no.Filhos);
      for i := 0 to lenFilho - 1
      do begin
         ramo := ReSerializarArvore(no.Filhos[i]);
         lenNeto := Length(ramo);
         lenPai := Length(xml);
         SetLength(xml,lenPai+lenNeto,4);
         for j := 0 to lenNeto - 1
         do begin
            xml[lenPai + j] := ramo[j];
         end
      end
   end;
   result := xml;
end;
// *****************************************************
// *** Funções para "ler" a árvore de nós (tags) xml ***
// *****************************************************
end.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.