Sourceverwaltung und PowerBuilder

Download Report

Transcript Sourceverwaltung und PowerBuilder

„Gesammelte Werke“
PowerBuilder Tipps und Tricks und
sonstiges aus der „normalen“ Client-Server
Entwicklung
Ludwin Feiten, Christoph Menken
Power People
Teil 2
Christoph Menken
• Tipps & Tricks im Web
• .net Komponente via
ComWrapper
• Powerbuilder in SAP
Business One
Fahrplan
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 2/36
Christoph Menken
•
•
•
•
•
•
•
•
•
•
•
•
powerbuilder.codexchange.sybase.com/
pbdj.sys-con.com/
www.pbdr.com/pbtips/
www.rgagnon.com/howto.html
www.softtreetech.com/hightech/tips.htm
www.topwizprogramming.com/
www.devx.com/getHelpOn/Door/11957
www.teamsybase.com/
members.cox.net/bdick/PbStuff.htm
s.webring.com/hub?ring=pbring
www.teamsybase.com/webring/webring.html
www.powerpeople.de
Tipps & Tricks im Web (Auszug)
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 3/36
Christoph Menken
• Neue Klassenbibliothek
(Class Library) erzeugen
.net Komponente via ComWrapper
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 4/36
Christoph Menken
• Klasse und alle
zugehörigen Referenzen
umbenennen
.net Komponente via ComWrapper
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 5/36
Christoph Menken
.net Komponente via ComWrapper
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 6/36
Christoph Menken
.net Komponente via ComWrapper
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 7/36
Christoph Menken
.net Komponente via ComWrapper
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 8/36
Christoph Menken
.net Komponente via ComWrapper
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 9/36
Christoph Menken
set dnf=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
set sdk=D:\Programme\Microsoft Visual Studio 8\SDK\v2.0\Bin
%dnf%\regasm $(TargetFileName) /regfile:$(TargetName).reg
%sdk%\gacutil /i "$(TargetPath)"
.net Komponente via ComWrapper
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 10/36
Christoph Menken
using
using
using
using
System;
System.Collections.Generic;
System.Text;
System.Net.Mail;
namespace DotNetSMTP
{
public class DotNetSMTP
{
private String senderName;
public String SenderName
{
get { return senderName; }
set { senderName = value; }
}
private String senderEmail;
private String smtpServer;
private String recipientEmail;
private String subject;
private String ccEmail = "";
private String bccEmail = "";
private bool isHTML = false;
private String messageText;
.net Komponente via ComWrapper
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 11/36
Christoph Menken
public void sendMail()
{
SmtpClient smtpClient = new SmtpClient();
MailMessage message = new MailMessage();
MailAddress fromAddress = new
MailAddress(senderEmail, senderName);
smtpClient.Host = smtpServer;
smtpClient.Port = 25;
message.From = fromAddress;
message.To.Add(recipientEmail);
message.Subject = subject;
if (!ccEmail.Equals(""))
{
message.CC.Add(ccEmail);
}
if (!bccEmail.Equals(""))
{
message.Bcc.Add(ccEmail);
}
message.IsBodyHtml = isHTML;
message.Body = messageText;
smtpClient.Send(message);
}
}
}
.net Komponente via ComWrapper
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 12/36
Christoph Menken
•
•
DLL erstellen
Registryeintrag hinzufügen
REGEDIT4
[HKEY_CLASSES_ROOT\DotNetSMTP.DotNetSMTP]
@="DotNetSMTP.DotNetSMTP"
[HKEY_CLASSES_ROOT\DotNetSMTP.DotNetSMTP\CLSID]
@="{43C9C58D-A6F4-3D41-A65D-6E0D23EE4249}"
[HKEY_CLASSES_ROOT\CLSID\{43C9C58D-A6F4-3D41-A65D-6E0D23EE4249}]
@="DotNetSMTP.DotNetSMTP"
[HKEY_CLASSES_ROOT\CLSID\{43C9C58D-A6F4-3D41-A65D-6E0D23EE4249}\InprocServer32]
@="mscoree.dll"
"ThreadingModel"="Both"
"Class"="DotNetSMTP.DotNetSMTP"
"Assembly"="DotNetSMTP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7090f4c6a1c37793"
"RuntimeVersion"="v2.0.50727"
[HKEY_CLASSES_ROOT\CLSID\{43C9C58D-A6F4-3D41-A65D6E0D23EE4249}\InprocServer32\1.0.0.0]
"Class"="DotNetSMTP.DotNetSMTP"
"Assembly"="DotNetSMTP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7090f4c6a1c37793"
"RuntimeVersion"="v2.0.50727"
[HKEY_CLASSES_ROOT\CLSID\{43C9C58D-A6F4-3D41-A65D-6E0D23EE4249}\ProgId]
@="DotNetSMTP.DotNetSMTP"
[HKEY_CLASSES_ROOT\CLSID\{43C9C58D-A6F4-3D41-A65D-6E0D23EE4249}\Implemented
Categories\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}]
.net Komponente via ComWrapper
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 13/36
Christoph Menken
• Testprogramm in C# erstellen
.net Komponente via ComWrapper
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 14/36
Christoph Menken
• Die DotNetSMTP.dll als
Referenz hinzufügen
.net Komponente via ComWrapper
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 15/36
Christoph Menken
•
•
Einen Button hinzufügen
Im clicked-Event folgenden Code hinzufügen:
DotNetSMTP.DotNetSMTP smtpclient = new
DotNetSMTP.DotNetSMTP();
smtpclient.SenderName = "Christoph Menken";
smtpclient.SenderEmail = "[email protected]";
smtpclient.SmtpServer = "smtp.gmx.de";
smtpclient.RecipientEmail = "[email protected]";
smtpclient.MessageText = "This is a test, this is only a test.";
smtpclient.Subject = "Dot Net via COM is cool";
smtpclient.sendMail();
.net Komponente via ComWrapper
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 16/36
Christoph Menken
• Im Powerbuilder:
integer li_rc
oleobject lole_smtp
lole_smtp = CREATE oleobject
li_rc = lole_smtp.ConnectToNewObject ( "DotNetSMTP.DotNetSMTP" )
if li_rc = 0 then
lole_smtp.SenderName = "Christoph Menken"
lole_smtp.SenderEmail = "[email protected]"
lole_smtp.RecipientEmail = "[email protected]"
lole_smtp.SmtpServer = "smtp.gmx.de"
lole_smtp.MessageText = "This is a test, this is only a test."
lole_smtp.Subject = "Dot Net via COM is cool"
else
MessageBox( parent.title, &
"Error calling DotNetSMTP via COM: " + string(li_rc) )
end if
.net Komponente via ComWrapper
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 17/36
Christoph Menken
• Kundenauftrag der Be.as GmbH
• Be.as ist eine Erweiterung des
SAP Business One (SBO)
• Vorteile:
– Look&Feel wie SBO
– Verwendung derselben Datenbank
und der SBO DI-API
– Leichte Erweiterungsmöglichkeit
durch eigene PSR-basierte
Skriptsprache
• Problem: Extra Programm
PB als Add-On
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 18/36
Christoph Menken
• Lösung: SBO UI-API
– COM+Objekt
– Add-On in SBO
– Integration in die SBO
Eventsteuerug
• Problem:
PB als Add-On
PBUGG
Frankfurt 21.05.2007
Powerbuilder
unterstüzt keine Implementation
der Events, wie z.B. VisualBasics
„with events“
Tipps & Tricks 2
Folie 19/36
Christoph Menken
SAP Business One
• Lösung: PBNI
SBO UI API
Triggert Events
Registrierung
PBNI-COMObjekt
Erstellen eines PBNI COMObjekt, welches das SBO-UICOM-Objekt verwendet und die
Events in PB zur Verfügung
stellt
PB
PB als Add-On
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 20/36
Christoph Menken
• Beispiel: PBNIOLEObject
– Einfaches exemplarisches
Beispiel
– Integration eines PBProgramms in MS Word
– von Bruce Armstrong
PB als Add-On
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 21/36
Christoph Menken
PBXEXPORT LPCTSTR PBXCALL
PBX_GetDescription()
{
static const TCHAR desc[] = {
"class n_cpp_oleobject from oleobject\n"
"function integer CaptureEvents() \n"
"function integer ReleaseEvents() \n"
"event startup pbm_custom01 \n"
"event quit pbm_custom02 \n"
"event documentchange pbm_custom03 \n"
"end class \n"
};
return desc ;
}
PB als Add-On
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 22/36
Christoph Menken
PBXEXPORT PBXRESULT PBXCALL PBX_CreateNonVisualObject(
IPB_Session*
pbsession,
pbobject
pbobj,
LPCSTR
className,
IPBX_NonVisualObject
**obj
)
{
if ( strcmp( className, "n_cpp_oleobject" ) == 0 )
{
*obj = new COLEObject() ;
return PBX_OK ;
};
*obj = NULL ;
return PBX_E_NO_SUCH_CLASS ;
}
PB als Add-On
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 23/36
Christoph Menken
BEGIN_DISPATCH_MAP(CEventSink, CCmdTarget)
DISP_FUNCTION(CEventSink, "Startup", Startup, VT_EMPTY, VTS_NONE)
DISP_FUNCTION(CEventSink, "Quit", Quit, VT_EMPTY, VTS_NONE)
DISP_FUNCTION(CEventSink, "DocumentChange", DocumentChange,
VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()
static const GUID IID_ICEventSink =
{0x000209f7,0x000,0x0000,{0xc0,0x00,0x0,0x00,0x00,0x00,0x00,0x46 } };
BEGIN_INTERFACE_MAP(CEventSink, CCmdTarget)
INTERFACE_PART(CEventSink, IID_ICEventSink, Dispatch)
END_INTERFACE_MAP()
PB als Add-On
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 24/36
Christoph Menken
void CEventSink::Startup()
{
//We'll never get this one, it happens before we capture the events
#ifdef _DEBUG
MessageBox( NULL, "Startup", "Message", MB_ICONEXCLAMATION | MB_OK );
#endif
pbclass clz = m_userdata->session->GetClass(m_userdata->object);
pbmethodID mid = m_userdata->session->GetMethodID(clz, "startup", PBRT_EVENT, "LUL" );
PBCallInfo ci;
m_userdata->session->InitCallInfo(clz, mid, &ci);
m_userdata->session->TriggerEvent(m_userdata->object, mid, &ci);
m_userdata->session->FreeCallInfo(&ci);
}
PB als Add-On
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 25/36
Christoph Menken
void CEventSink::Quit()
{
#ifdef _DEBUG
MessageBox( NULL, "Quit", "Message", MB_ICONEXCLAMATION | MB_OK );
#endif
pbclass clz = m_userdata->session->GetClass(m_userdata->object);
pbmethodID mid = m_userdata->session->GetMethodID(clz, "quit", PBRT_EVENT, "LUL" );
PBCallInfo ci;
m_userdata->session->InitCallInfo(clz, mid, &ci);
m_userdata->session->TriggerEvent(m_userdata->object, mid, &ci);
m_userdata->session->FreeCallInfo(&ci);
}
PB als Add-On
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 26/36
Christoph Menken
void CEventSink::DocumentChange()
{
#ifdef _DEBUG
MessageBox( NULL, "DocumentChange", "Message", MB_ICONEXCLAMATION | MB_OK );
#endif
pbclass clz = m_userdata->session->GetClass(m_userdata->object);
pbmethodID mid = m_userdata->session->GetMethodID(clz, "documentchange", PBRT_EVENT, "LUL" );
PBCallInfo ci;
m_userdata->session->InitCallInfo(clz, mid, &ci);
m_userdata->session->TriggerEvent(m_userdata->object, mid, &ci);
m_userdata->session->FreeCallInfo(&ci);
}
PB als Add-On
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 27/36
Christoph Menken
Erzeugen der PBD
erase pbnioleobject.pbx
copy release\pbnioleobject.dll
pbnioleobject.pbx
"D:\Programme\Sybase\PowerBuilder
10.5\SDK\PBNI\pbx2pbd105.exe"
pbnioleobject.pbd pbnioleobject.pbx
pause
PB als Add-On
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 28/36
Christoph Menken
Verbindung herstellen
Integer
li_rc
SetPointer ( HourGlass! )
try
inv_word = CREATE n_cpp_oleobject_word_application
IF IsNull ( inv_word ) THEN Return
li_rc = inv_word.ConnectToNewObject ( "Word.Application.8" )
IF li_rc <> 0 THEN Return li_rc
inv_word.Visible = TRUE
li_rc = inv_word.CaptureEvents()
catch (Throwable MyError )
Return -1
end try
PB als Add-On
PBUGG
Frankfurt 21.05.2007
CHOOSE CASE li_rc
CASE 1
Return 1
CASE ELSE
Return li_rc
END CHOOSE
Tipps & Tricks 2
Folie 29/36
Christoph Menken
PB als Add-On
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 30/36
Christoph Menken
PB als Add-On
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 31/36
Christoph Menken
PB als Add-On
PBUGG
Frankfurt 21.05.2007
Tipps & Tricks 2
Folie 32/36
Christoph Menken
• Möglichkeiten der SBOUI-API:
– Reaktion auf SBO-Events
– Erzeugen von SBO-Objekten,
wie z.B. Form, Menü, Button,
Datenfelder
• Problem:
PB als Add-On
PBUGG
Frankfurt 21.05.2007
– Keine Verwendung von PBObjekte möglich
– Somit auch keine
Datawindows, bzw. PSRs
Tipps & Tricks 2
Folie 33/36
Christoph Menken
• Lösung:
PB als Add-On
PBUGG
Frankfurt 21.05.2007
– Erzeugen einer SBO-Form
– Erzeugen eines Childwindow in
PB
– Ermittlung der Handle beider
Fenster
– PB-Child als Child der SBOForm setzen
Tipps & Tricks 2
Folie 34/36
Christoph Menken
// Zunächst eine Form in SAP öffnen
ls_uid = 'beas_' + string(now(),"hhmmssffff")
ls_title = aw_window.title
li_top = UnitsToPixels(aw_window.y, YUnitsToPixels! )
li_left = UnitsToPixels(aw_window.x, XUnitsToPixels! )
li_width = UnitsToPixels(aw_window.width, XUnitsToPixels! )
li_height = UnitsToPixels(aw_window.height, YUnitsToPixels! )
ll_rc = this.of_sboform_add( ls_uid, "", this.ft_sizable, this.fbs_sizable, "", lole_form, ls_title, li_left,
li_width, li_top, li_height )
if not isvalid(lole_form) then return FAILURE
// Dann das Handle das SBO Fensters holen (Klasse: TMMDIChildClass)
SetNull( ls_WindowName )
setnull( ll_hStartingChild )
ll_hFrameWindow = FindWindowA( SBOFRAME_CLASS, ls_WindowName) // erst den Frame
…
ll_hClientWindow = FindWindowExA( ll_hFrameWindow, ll_hStartingChild, SBOCLIENT_CLASS,
ls_WindowName)
// dann den Client
…
ll_hChildWindow = FindWindowExA( ll_hClientWindow, ll_hStartingChild, SBOCHILD_CLASS, ls_WindowName)
// und dann das Child
…
// Fenster positionieren
aw_window.x = 0 // ganz nach links
aw_window.y = 0 // ganz nach oben
PB als
Add-On
PBUGG
Frankfurt 21.05.2007
// Das Handle des Childs bilden
ll_hPBWindow = handle(aw_window)
if isnull(ll_hPBWindow) then return FAILURE
// das Handle des SBO-Parents an das PB-Child übergeben
ll_hParentWindow = ll_hChildWindow
ll_rc = SetParent( ll_hPBWindow, ll_hParentWindow)
Tipps & Tricks 2
Folie 35/36
Christoph Menken
Sind noch Fragen offen?
Bei Rückfragen oder Anregungen bitte an:
Ludwin Feiten
Power People
Inh. Ludwin Feiten
Am Borsigturm 50
D-13507 Berlin
fon +49 (0)30 43032350
fax +49 (0)30 43032355
Kontakt
PBUGG
Frankfurt 21.05.2007
http://www.powerpeople.de
mailto:[email protected]
Tipps & Tricks 2
Folie 36/36
Christoph Menken