Announcement

Collapse
No announcement yet.

MAPI (Portation von Delphi7 -> VB.NET)

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • MAPI (Portation von Delphi7 -> VB.NET)

    Hallo!

    Wiedermal eine Delphi->VB.NET Portations-Frage von mir...

    Delphi-Beispiel:<pre>function SendMail(const ATitle, AMsg: String; ARecips,
    AFiles: TStrings; AStyle: TMAPIStyle; Aply: Boolean): Boolean;
    [...]
    var
    MMessage: TMapiMessage;
    begin
    [...]
    MMessage.ulReserved := 0;
    MMessage.lpszSubject := PChar(ATitle);
    MMessage.lpszNoteText := PChar(AMsg);
    MMessage.lpszMessageType := nil;
    MMessage.lpszDateReceived := nil;
    MMessage.lpszConversationID := nil;
    MMessage.flFlags := 0;
    MMessage.lpOriginator := nil;
    MMessage.nRecipCount := nRecipCount;
    MMessage.lpRecips := PMapiRecipDesc(PRecipDescList);
    MMessage.nFileCount := nFileCount;
    MMessage.lpFiles := PMapiFileDesc(PFileDescList);

    case AStyle of
    msLogon: EError := MapiSendMail(0, 0, MMessage, MAPI_LOGON_UI, 0);
    msDialog: EError := MapiSendMail(0, 0, MMessage, MAPI_LOGON_UI or MAPI_DIALOG, 0);
    msHidden: EError := MapiSendMail(0, 0, MMessage, 0, 0);
    end;

    case EError of
    [...]
    end;
    Result := (EError = SUCCESS_SUCCESS);
    end;</pre>...mit diesem Beispiel kann ich einfach eine eMail an das Standard-eMail-Programm übergeben und auf Wunsch automatisch über die Default-Adresse verschicken ohne das der Anwender eine zusätzliche Bestätigungsanforderung erhält.

    Wie kann ich das unter VB.NET umsetzen bzw. auf anderem Wege realisieren?!?

    Vielen Dank<br>
    &nbsp;&nbsp;&nbsp;Nico Stöckigt<br>
    <br>

  • #2
    Hallo,

    für das Zustellen einer eMail gibt es verschiedene Alternativen

    1. Klasse <b>System.Web.Mail</b>
    <pre>
    Imports System.Text
    Imports System.Web.Mail

    ...
    Private Sub ButtonSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSend.Click
    Dim oMail = New MailMessage()
    oMail.To = Me.TextBoxTo.Text.Trim()
    oMail.From = &quot;<a href="mailto:[email protected]">[email protected]</a>&quot;
    oMail.Subject = Me.TextBoxSubject.Text.Trim()
    oMail.BodyFormat = MailFormat.Html
    Dim oSB = New StringBuilder()
    oSB.Append(&quot;&lt;html&gt;&lt;head&gt;&lt;title &gt;ASP.NET + eMail&lt;/title&gt;&lt;/head&gt;&quot
    oSB.Append(&quot;&lt;body style='font-family: Verdana'&gt;&quot
    oSB.Append(&quot;&lt;h1&gt;&lt;font color='#800080'&gt;ASP.NET verschickt eine eMail&lt;/font&gt;&lt;/h1&gt;&quot
    oSB.Append(&quot;&lt;tr&gt;&lt;td width='150' valign='top'&gt;&lt;table&gt;&quot
    oSB.Append(Me.TextBoxBody.Text)
    oSB.Append(&quot;&lt;p&gt;&quot
    oSB.Append(&quot;&lt;p&gt;Version 1.0&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;&quot
    oMail.Body = oSB.ToString()
    SmtpMail.SmtpServer = &quot;192.168.10.1&quot;
    SmtpMail.Send(oMail)
    End Sub
    </pre>
    2. Standard-eMail-Client wird übber den <b>mailto:</b>-Weg aufegrufen und teilweise ausgefüllt angezeigt
    <pre>
    System.Text.StringBuilder aSB = <b>new</b> System.Text.StringBuilder();
    aSB.AppendFormat(@<font color="#9933CC">&quot;mailto:{0}&quot;</font>, labelAutorMail.Text);
    <b>if</b> (! ClassConnectionString.IsOutlookMailClient())
    {
    aSB.Append(@<font color="#9933CC">&quot;?cc=&quot;</font>);
    }
    aSB.AppendFormat(@<font color="#9933CC">&quot;&amp;subject=Honorar für den Artikel »{0}«&quot;</font>, labelArtikel.Text);
    aSB.AppendFormat(@<font color="#9933CC">&quot;&amp;body={0}, &quot;</font>, labelAutorTextAnrede.Text);
    aSB.Append(@<font color="#9933CC">&quot;%0a%0a&quot;</font>);
    aSB.Append(@<font color="#9933CC">&quot;bitte stellen Sie eine Rechnung für die folgenden Abrechnungsdaten für den o.g. Artikel:&quot;</font>);
    aSB.Append(@<font color="#9933CC">&quot;%0a%0a&quot;</font>);
    aSB.AppendFormat(@<font color="#9933CC">&quot;Posten-Nummer: {0} mit dem Honorar-Betrag {1} EUR&quot;</font>, sPostenNr, dHonorar);
    aSB.Append(@<font color="#9933CC">&quot;%0a%0a&quot;</font>);
    aSB.Append(<font color="#9933CC">&quot;Mit freundlichen Grüßen&quot;</font>);
    System.Diagnostics.Process aMailApp = <b>new</b> System.Diagnostics.Process();
    aMailApp.StartInfo.FileName = aSB.ToString();
    aMailApp.StartInfo.UseShellExecute = <b>true</b>;
    aMailApp.StartInfo.RedirectStandardOutput = <b>false</b>;
    aMailApp.Start();
    aMailApp.Dispose();
    statusBarHonorarMail.Text = <font color="#9933CC">&quot;eMail wurde übergeben.&quot;</font>;
    }
    </pre>
    3. Die alte Delphi-Implementierung wird als Win32-DLL ausgelagert und über P/Invoke eingebunden

    Comment


    • #3
      <p>Quote:<br><span style="background-color: lightgrey">&nbsp;&nbsp;&nbsp;3. Die alte Delphi-Implementierung
      wird als Win32-DLL ausgelagert und über P/Invoke eingebunden.</span></p>
      Genau diese Methode wäre am interessantesten, nur hab' ich leider keine Ahnung wie ich das anfangen soll.<br>Wie lager' ich die alte Implementierung (damit ist doch 'TMAPIMessage' gemeint !?!) als Win32-dll aus???<br>Wie lautet der Syntax zu P/Invoke - Beispiel?!<br><br>Wiedermal TDank!<br>&nbsp;&nbsp;&nbsp;Nico Stöckig

      Comment


      • #4
        Hallo Nico,

        &gt;Wie lagere ich die alte Implementierung ...

        der "alte" Delphi-Code wird dazu in ein DLL-Projekt kopiert und über eine im <b>export</b>-Abschnitt der DLL aufgelistete Schnittstellenprozedur veröffentlicht:
        <pre>
        <b>library</b> DelphiDLL;
        <br>
        <b>uses</b>
        SysUtils, Classes, Windows;
        <br>
        <font color="#003399"><i>{$R *.res}</i></font>
        <br>
        <b>function</b> OSGetThreadID: Integer; <b>stdcall</b>;
        <b>begin</b>
        Result := GetCurrentThreadID;
        <b>end</b>;
        <br>
        <b>var</b>
        szUserName : <b>array</b>[0..99] <b>of</b> Char;
        <br>
        <b>function</b> OSGetUserName: PChar; <b>stdcall</b>;
        <b>var</b>
        dwLen : DWORD;
        <b>begin</b>
        dwLen := SizeOf(szUserName);
        FillChar(szUserName, dwLen, #0);
        GetUserName(szUserName, dwLen);
        Result := @szUserName;
        <b>end</b>;
        <br>
        <b>exports</b>
        OSGetThreadID <b>index</b> 1,
        OSGetUserName <b>index</b> 2;
        <br>
        <b>begin</b>
        <b>end</b>.
        </pre>
        Unter VB.NET stehen im Gegensatz zu C# gleich 2 Wege zur Verfügung, um eine "alte" Win32-DLL über P/Invoke einzubinden:<br>
        a) Uralt-Weg a la Visual Basic 6: <b>Declare Funktion xyz Lib</b> <br>
        b) .NET-Weg über <b>DllImport</b> (Methode muss als Shared gekennzeichnet werden)

        <pre>
        Imports System.Runtime.InteropServices
        </pre>
        <pre>
        Declare Function OSGetThreadID Lib "DelphiDLL.dll" () As Integer
        <br>
        <DllImport("DelphiDLL.dll", EntryPoint:="#2")> _
        Public Shared Function OSGetUserName() As String
        ' bleibt Leer
        End Function
        <br>
        Private Sub ButtonThreadID_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonThreadID.Click
        Label1.Text = OSGetThreadID.ToString()
        StatusBar1.Text = "OSThreadID aufgerufen"
        End Sub
        <br>
        Private Sub ButtonUserName_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonUserName.Click
        Label2.Text = OSGetUserName()
        StatusBar1.Text = "OSUserName aufgerufen"
        End Sub
        </pre&gt

        Comment


        • #5
          Soweit hab ich's verstanden! Nur tue ich mich etwas schwer, da im Fall MAPI ein TYPE "exportiert" werden müsste... ich finde einfach keinen Weg den TYPE TMapiMessage mit all seinen Methoden und Properties freizugeben.

          Sorry für mein Unwissen und meine fehlende Creativität - vielleicht komm' ich ja doch noch alleine drauf..

          Comment


          • #6
            Hallo,

            &gt;...TMapiMessage mit all seinen Methoden und Properties freizugeben.

            das würde auch keinen Sinn machen, da sich die Situation dann ja nicht verbessern würde. Statt dessen stellt die Schnittstellenprozedur nur das "Interface" für die <b>Funktionalität</b> zur Verfügung, so dass die DLL als Black-Box genutzt wird. Das könnte dann so aussehen:
            <pre>
            function SendMail(ATitle, AMsg, ARecips, AFiles: PChar; Aply: Boolean): Boolean;
            </pre>
            Das VB.NET-Programm übergibt für <i>ARecips</i> und <i>AFiles</i> nur eine Zeichenkette, die im Fall von mehreren Einträgen intern ein vereinbartes Separator-Zeichen nutzt, damit die Delphi-DLL intern das als Stringliste umwandeln kann

            Comment


            • #7
              Hallo (Andreas)!

              ich stehe so ein wenig auf dem Schlauch... wie oben angegeben habe ich das jetzt umgesetzt, nur verstehe ich das mit der "Weiterleitung noch nicht ganz bzw. erfasse ich die Möglichkeiten und Zusammenhänge noch nicht vollständig.<pre><b>Imports</b> System.Runtime.InteropServices

              <b>Public Class</b> DMAPI

              <font color="grey">'function SendMail(const ATitle, AMsg: String; ARecips, AFiles: TStrings; AStyle: TMAPIStyle; Aply: Boolean): Boolean;</font>

              <DllImport(<font color="blue">"DMAPI.dll"</font>, EntryPoint:=<font color="blue">"#1"</font>)> _
              <b>Public Shared Function</b> SendMail(<b>ByVal</b> ATitle <b>AS String</b>, <b>ByVal</b> AMsg <b>AS String</b>, <b>ByVal</b> ARecips <b>AS String</b>, <b>ByVal</b> AFiles <b>AS String</b>,
              AStyle <b>AS Integer</b> <b>ByVal</b> Aply <b>AS Boolean</b>) <b>As String</b>
              <font color="grey">' bleibt Leer</font> <font color="red">&lt;- bleibt leer (s.o.) ?!? - immer? kommt hier nicht meine "Umsetzung" von VB-&gt;Delphi rein?</font>
              <b>End Function</b>

              <font color="grey">'TMAPIStyle = (msLogon, msDialog, msHidden);</font>
              <b>public enum</b> eMAPIStyle
              msLogon
              msDialog
              msHidden
              <b>end enum</b>

              <b>End Class</b></pre>
              Vielen Dank<br>
              &nbsp;&nbsp;&nbsp;Nico Stöckigt<br>
              <br&gt

              Comment


              • #8
                Hallo!

                Ich hab da ein kleines Problem und zwar einem fehlenden Objektverweis...
                <p>Interface-Klasse in Delphi</p>
                <table border="0" cellpadding="2" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber2">
                <tr>
                <td width="20">&nbsp;</td>
                <td bgcolor="#D4D4D4">
                <pre>library DMAPI;

                //================================================== ============================

                uses
                SysUtils,
                Classes,
                Dialogs,
                MAPI,
                FNC; // enthält div. eigene Funktionen u.a. auch 'SendMail()' für MAPI

                //================================================== ============================

                function MAPISendMail(const ATitle, AMsg, ARecips, AFiles: PChar;
                AStyle: Integer; Aply: Boolean): Boolean;
                var
                sDummy: String;
                lRecips, lFiles: TStrings;
                lStyle: TMAPIStyle;
                nIdx: Integer;
                begin
                lRecips := TStringList.Create;
                lFiles := TStringList.Create;

                sDummy := '';
                for nIdx := 0 to Length(ARecips) - 1 do
                begin
                if (ARecips[nIdx] = ';')
                then begin
                lRecips.Add(sDummy);
                sDummy := '';
                end
                else begin
                sDummy := sDummy + ARecips[nIdx];
                end;
                end;

                sDummy := '';
                for nIdx := 0 to Length(AFiles) - 1 do
                begin
                if (AFiles[nIdx] = ';')
                then begin
                lFiles.Add(sDummy);
                sDummy := '';
                end
                else begin
                sDummy := sDummy + AFiles[nIdx];
                end;
                end;

                case AStyle of
                0: lStyle := msLogon;
                1: lStyle := msDialog;
                2: lStyle := msHidden;
                else lStyle := msDialog;
                end;

                Result := SendMail(ATitle, AMsg, lRecips, lFiles, lStyle, Aply); // included in FNC (s.o.)
                end;

                //================================================== ============================

                exports
                MAPISendMail index 1;

                end.</pre></td>
                </tr>
                </table>
                <p><br>
                Interface-Klasse in VB.NET</p>
                <table border="0" cellpadding="2" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber1">
                <tr>
                <td width="20">&nbsp;</td>
                <td bgcolor="#D4D4D4">
                <pre>Imports System.Runtime.InteropServices

                Public Class MAPI32_INTERFACE

                'function SendMail(const ATitle, AMsg: String; ARecips, AFiles: TStrings; AStyle: TMAPIStyle; Aply: Boolean): Boolean;
                &lt;DllImport("DMAPI.dll", EntryPoint:="#1")&gt; _
                Public Shared Function MAPISendMail(ByVal ATitle As String, ByVal AMsg As String, ByVal ARecips As String, _
                ByVal AFiles As String, ByVal AStyle As Integer, ByVal Aply As Boolean) As Boolean
                ' bleibt Leer
                End Function

                End Class</pre>
                </td>
                </tr>
                </table>
                <p><br>
                Verwendung in VB.NET</p>
                <table border="0" cellpadding="2" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" id="AutoNumber3">
                <tr>
                <td width="20">&nbsp;</td>
                <td bgcolor="#D4D4D4">
                <pre> Public Shared Function SendMail(ByVal ATitle As String, ByVal AMsg As String, ByVal ARecips As IList, ByVal AFiles As IList, ByVal AStyle As eMAPIStyle, ByVal Aply As Boolean) As Boolean
                Dim lRecips, lFiles As String
                Dim lMAPI As xMAPI.MAPI32_INTERFACE

                lRecips = ListToString(ARecips, ";")
                lFiles = ListToString(AFiles, ";")

                lMAPI = New xMAPI.MAPI32_INTERFACE
                Return lMAPI.MAPISendMail(ATitle, AMsg, lRecips, lFiles, CInt(AStyle), Aply) <font color="#FF0000"><b>&lt;- Objektverweis wurde nicht auf eine Objektinstanz festgelegt</b></font>
                End Function
                </pre>
                </td>
                </tr>
                </table>
                <p>Es ist bestimmt wieder banal, aber ich suche jetzt schon seit ein paar
                Stunden...</p>
                <p>Vielen Dank<br>
                &nbsp;&nbsp; Nico Stöckigt</p>
                <p>&nbsp;</p&gt

                Comment

                Working...
                X