Translate

2015/03/30

TIWDBAsyncNavigator 圖片無法顯示的問題

IntraWeb version: V14.2.3
TMS IntraWeb version: TMS IntraWeb Component Pack Pro Script Edition V5.4.1.1

在使用 TIWDBAsyncNavigator 元件時,實際執行的畫面如下:
TIWDBAsyncNavigator 的圖片無法顯示
沒有指定按鈕圖片時,IWDBAsyncNavigator預設會載入 IWDBNavigator 的圖片。

網頁原始碼比較:

IWDBAsyncNavigator 圖示路徑
IWDBNavigator 圖示路徑
檔名相同,但 IWDBAsyncNavigator 路徑缺少根目錄符號(/)。不知道是什麼原因造成,於是進入 IWDBAsyncNavigator.pas 來檢查。

在 LINE 1036 處修改如下:
{$IFDEF TMSIW11}
    {$IF FALSE}
    if url = '' then
      url := '$/gfx/DBNAV_' + Action + '.gif';
    if urld = '' then
      urld := '$/gfx/DBNAV_' + Action + 'Disabled.gif';
    {$ELSE}
    if url = '' then
      url := 'gfx/DBNAV_' + Action + '.gif';
    if urld = '' then
      urld := 'gfx/DBNAV_' + Action + 'Disabled.gif';
    {$IFEND}
{$ELSE}
    if url = '' then
      url := '/gfx/DBNAV_' + Action + '.gif';
    if urld = '' then
      urld := '/gfx/DBNAV_' + Action + 'Disabled.gif';
{$ENDIF}


IWDBAsyncNavigator  圖示終於可以正確顯示


參考資料:IWDBAsyncNavigator images

2015/03/28

Firebird Embedded 連線注意的地方

Delphi的DBX一直都無法連線到Firebird 1.5。

老是出現「DBX Error: Driver could not be properly. Client may be misiing, not installed properly, of the wrong version, or thr driver may be misiing from the system path.」

原來是DBX Driver不只是單認system path,連VendorLib也強迫認「fbclient.dll」。

難怪我就算把VendorLib設為「[DirPath]\fbembed.dll」也完全連接不上Firebird Embedded。

結論:
1.把Firebird的fbembed.dll複製到Delphi安裝目錄\Bin。
2.fbembed.dll改名為fbclient.dll

連結成功!

2015/03/10

IntraWeb使用ClientDataSet的注意事項


Working with ClientDataSets裡是這麼寫的:
If you are using a ClientDataSet component and you get an Access Violation when exiting the application, you need to add the DBClient unit in the application uses clause before IWMain.
The reason for the access violation is that if DBClient is not included in project file uses clause, it's internal interfaces are freed before all sessions are closed and when IW closes it's sessions it will try to free ClientDataSet component, and you will get the access violation.
When DBClient is placed before IWMain IW will free sessions before DBClient interfaces are freed.
這章節在描述TClientDataSet可能會在Session釋放前就先被清除(Freed),然後在Session要釋放時又再被釋放一次,進而發生 Access Violation。

解決的方法就是在 IWMain 前的 uses 加入 DBClient,讓釋放的順序正確,Access Violation的問題才能獲得解決。





Delphi XE7使用Indy 10.6.1連結Gmail SMTP

我在KTOP中回答「xe6 使用gmail的問題」這個主題,因為程式碼編排有問題,故在這裡另外轉貼。

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdExplicitTLSClientServerBase, IdSMTP, IdSSLOpenSSL,
  IdMessage, IdAttachmentFile, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    function SendEmail(sendTo: string;
                    subject: string;
                    body: string;
                    attachFiles: TStringList;
                    smtpHost: string;
                    smtpPort: Integer;
                    smtpUser: string;
                    smtpPass: string;
                    tls: TIdUseTLS): boolean;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
  SendEmail( 'mybuddy@example.com', // 目的地E-Mail
                    'This is the subject',
                    'This is the body of the email....',
                    nil,
                    'smtp.gmail.com',
                    587,
                    'myusername@gmail.com', // 登入帳號
                    'mypassword'{ 登入密碼 }, utUseExplicitTLS);
end;

function TForm1.SendEmail(sendTo, subject, body: string;
  attachFiles: TStringList; smtpHost: string; smtpPort: Integer; smtpUser,
  smtpPass: string; tls: TIdUseTLS): boolean;
var
    smtp: TIdSmtp;
    ssl: TIdSSLIOHandlerSocketOpenSSL;
    msg: TIdMessage;
    i: Integer;
begin
    smtp:=TIdSmtp.Create(nil);
    ssl:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
    msg:=TIdMessage.Create(nil);
    try

        try
            smtp.Host:=smtpHost;
            smtp.Port:=smtpPort;
            smtp.Username:=smtpUser;
            smtp.Password:=smtpPass;

            //smtp.OnConnected :=IdSMTP1Connected;
            //smtp.OnDisconnected :=IdSMTP1Disconnected;
            //smtp.OnFailedRecipient :=IdSMTP1FailedRecipient;
            //smtp.OnStatus :=IdSMTP1Status;
            //smtp.OnTLSNotAvailable :=IdSMTP1TLSNotAvailable;
            //smtp.OnWork :=IdSMTP1Work;

            if not (tls=utNoTLSSupport) then begin
                ssl.Destination:=smtpHost + ':' + IntToStr(smtpPort);
                ssl.Host:=smtpHost;
                ssl.Port:=smtpPort;
                ssl.SSLOptions.Method:=sslvTLSv1;

                //ssl.OnStatusInfo:=IdSSLIOHandlerSocketOpenSSL1StatusInfo;
                //ssl.OnGetPassword:=IdSSLIOHandlerSocketOpenSSL1GetPassword;
                //ssl.OnStatus:=IdSSLIOHandlerSocketOpenSSL1Status;

                smtp.IOHandler:=ssl;
                smtp.UseTLS:=tls;
            end;

            msg.Recipients.EMailAddresses := sendTo;
            msg.Subject:=subject;
            msg.Body.Text:=body;

            if(Assigned(attachFiles)) then begin
                for i := 0 to attachFiles.Count - 1 do begin
                   if FileExists(attachFiles[i]) then
                        TIdAttachmentFile.Create(msg.MessageParts, attachFiles[i]);
                end;
            end;

            smtp.Connect;
            smtp.Send(msg);
            smtp.Disconnect;

            result:=true;
        finally
            msg.Free;
            ssl.Free;
            smtp.Free;
        end;
    except
       result:=false;
    end;
end;

end.

結論:
上述程式可以正確發出和收到信件,在XE7下驗證無誤。


參考資料來源:Sending email with attachments using Delphi, Indy 10.5.5 and GMail




2015/03/09

ADO 是個好東西,不用嗎?

ADO--ActiveX Data Object
在RAD Studio裡被歸類在「ADO Express」元件盤中,RAD Studio 2006後則改名為「dbGo」。

ADO架構
圖片來源:MSDN Microsoft Data Development Technologies: Past, Present, and Future
ADO的缺點在於,全世界的作業系統中,只有Windows才有具備Ole Provider。

換言之,ADO只能運行在Windows的世界。

然而在深入了解ADO後,發現ADO的核心概念和DataSnap幾乎一樣,透過Windows平台內建的OleDB engine,要單層開發、兩層開發,有狀態還是無狀態形式的公事包開發都不是問題,一切只需要一個ADO元件就可以完成。

ADO是個好東西,不用嗎?

單機,對於Access、Excel都有非常多的範例和很極佳的效能。
兩層,對於SQL Server的連線效能極佳,又額外提供其它資料庫的Ole Provider可以擴充。

無狀態的儲存,我們可以採用「公事包」的方式,把ADODataSet的Data另存為實體檔案,待網路順暢時再行傳輸。

「公事包」這名詞,微軟是這麼說的:

使用公事包同步 -- Windows 7說明
您可以使用 [公事包] 來讓兩部不同電腦之間的檔案保持同步,即使電腦不在相同的網路上。 如果電腦不在相同的網路上,您可以使用卸除式媒體從一部電腦將檔案複製到另一部電腦,再使用另一部電腦處理那些檔案,然後使用 [公事包] 對原始電腦進行變更同步。

ADO裡的LockType中,ltBatchOptimistic參數便是對應公事包特性。
更淺碟一點的說法,就是「離線編輯」。

實際的範例用法如下:
dfm:
object ADOConnection1: TADOConnection
  Connected = True
  ConnectionString =
    'Provider=SQLOLEDB.1;Persist Security Info=False;User ID=root;' +
    'Initial Catalog=AdventureWorks;Data Source=127.0.0.1;password=0000'
  KeepConnection = False
  LoginPrompt = False
  Mode = cmReadWrite
  Provider = 'SQLOLEDB.1'
  Left = 60
  Top = 34
end
object DBNavigator1: TDBNavigator
  Left = 42
  Top = 25
  Width = 240
  Height = 25
  DataSource = DataSource1
  TabOrder = 0
end
object ADODataSet1: TADODataSet
  Active = True
  Connection = ADOConnection1
  CursorType = ctStatic
  LockType = ltBatchOptimistic
  CommandText = 'select * from Emp'
  Parameters = <>
  Left = 60
  Top = 86
end
object DataSource1: TDataSource
  DataSet = ADODataSet1
  Left = 58
  Top = 136
end
object DBGrid1: TDBGrid
  Left = 12
  Top = 62
  Width = 379
  Height = 171
  DataSource = DataSource1
  TabOrder = 1
  TitleFont.Charset = DEFAULT_CHARSET
  TitleFont.Color = clWindowText
  TitleFont.Height = -11
  TitleFont.Name = 'Tahoma'
  TitleFont.Style = []
end
object TrackBar1: TTrackBar
  Left = 464
  Top = 13
  Width = 79
  Height = 32
  Max = 1
  Position = 1
  TabOrder = 2
  OnChange = TrackBar1Change
end
object Label1: TLabel
  Left = 406
  Top = 23
  Width = 52
  Height = 13
  Caption = 'Connected'
end
object CheckBox1: TCheckBox
  Left = 406
  Top = 56
  Width = 97
  Height = 17
  Caption = 'Offline Mode'
  TabOrder = 3
  OnClick = CheckBox1Click
end
object Button1: TButton
  Left = 410
  Top = 86
  Width = 75
  Height = 25
  Caption = 'ApplyUpdate'
  TabOrder = 4
  OnClick = Button1Click
end
object Button2: TButton
  Left = 410
  Top = 122
  Width = 101
  Height = 25
  Caption = 'Save Package'
  TabOrder = 5
  OnClick = Button2Click
end
object Button3: TButton
  Left = 410
  Top = 153
  Width = 101
  Height = 25
  Caption = 'Load Package'
  TabOrder = 6
  OnClick = Button3Click
end

Pas:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, Grids, DBGrids, DB, ADODB, ExtCtrls, DBCtrls;

type
  TForm1 = class(TForm)
    ADOConnection1: TADOConnection;
    DBNavigator1: TDBNavigator;
    ADODataSet1: TADODataSet;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    TrackBar1: TTrackBar;
    Label1: TLabel;
    CheckBox1: TCheckBox;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure TrackBar1Change(Sender: TObject);
    procedure CheckBox1Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  ADODataSet1.Connection := ADOConnection1;
  ADODataSet1.UpdateBatch;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ADODataSet1.SaveToFile('OfflinePackage.data');
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  ADODataSet1.Close();
  ADODataSet1.LoadFromFile('OfflinePackage.data');
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
  ADODataSet1.Connection := nil;
end;

procedure TForm1.TrackBar1Change(Sender: TObject);
begin
  ADOConnection1.Connected := (TrackBar1.Position = 1);
  ADODataSet1.Active       := ADOConnection1.Connected;
end;

end.

成果圖:
ADO 公事包範例

故可從以上得知,ADO真的是很棒的架構。

公司採用SQL Server,以及沒有跨平台需求的專案,ADO真的可以完全符合需求。

安全性則可以透過VPN和NAT來解決。


DataSnap好像又不是這麼必要了。是嗎?

對 dbExpress 的誤會

dbExpress是個「單向」和「唯讀」的資料集,嚴格來說,它只是個「游標」,連資料集都不算,有什麼好期待的?

按過往的批評dbExpress的文章來看,大部份比較的對象都是BDE和ADO。

然而,dbExpress本身就不負責BDE和ADO內三分之二的工作,要說它爛是不是有點搞錯對象。

dbExpress提供的是「架構」層面的思考,和BDE、ADO本身要求速效的概念,是先天上的不同。

深入推廣的DataSnap才是dbExpress的戰略目標。


只是戰技(Driver)和戰術(3rd Party)搭配的實在是不高明,領教過的開發者應該很明白這件事。

戰技缺點多,Driver的相容性和臭蟲不少,官方修正力道很微弱。
戰術閉塞不開,3rd Party在dbExpress官方的臭蟲影響下,也很難有伸展的空間。

甚至Devart的Document是這麼寫的:
We tried to include maximal support of server-specific features in both dbExpress drivers and DACs. However, the nature of dbExpress technology has some restrictions that cannot be overcome.

話雖如此,dbExpress概念是良好的,因為中間層的確是不需要太多狀態的資訊存在,而dbExpress也確實做到這一點,所以dbExpress的簡易和輕量化在這訴求下是必需的。

dbExpress最初立意是良好的,只是Borland手上的好牌被玩爛了,這實在是非戰之罪。

現在在行動裝置上,DataSnap也漸漸復活了,當初採用dbExpress的開發者應該開始嚐到一點開發甜頭了吧!

2015/03/08

現在是開發兩層還是三層?

dbExpress的開發畫面大概是這個樣子:
 

DataSnap的開發畫面大概是這個樣子:
Server端設計畫面
Client端設計畫面

好像有點一樣,又好像有點不一樣。
如果dbExpress改一下,就變成下面的畫面:
增加建立一個DataModule放dbExpress元件

ClientDataSet還在原來的位置,只是ProviderName會是DataModule.DataSetProvider1
相較之下,dbExpress好像只差了一個TDCOMConnection元件外,和DataSnap長相簡直一模一樣。

也難怪dbExpress要被人說閒話了,這複雜難用的神馬東西。

說易用沒有BDE來得自動化:TQuery + TUpdateSQL,BDE小小調整一下,收工。
說功能沒有ADO來得全面:光是ADOConnection的Properties內容就可以談上十餘頁A4紙;ADOQuery幾乎把BDE元件所有功能包完。

反觀dbExpress,Driver Params就只有幾項,光產出的元件就比BDE多,程式的所有細節居然還全都要人工硬嗑,就算不寫程式碼,需要看的資料也絕對不下於ADO。

那dbExpress的架構到底是什麼?Borland開發這個是拿磚頭砸自己的腳嗎?(是的,它是)


用到現在,我終於參悟了dbExpress到底是什麼,算得上是三層嗎?



如果只能用一句話來描述dbExpress的層數,那我想我會說:





「兩層以上,三層未滿」(友達以上,戀人未滿)


2015/03/05

該放棄Web還是C++ Builder?

回補一下關於Delphi/C++ Builder在Web上的開發方案,我整理了以下的簡圖:
WebBroker, Internet Express, WebSnap and IntraWeb concept


不論是WebBroker、Internet Express還是WebSnap,最大的問題在於「HTML、CSS、JavaScript」等Browser Client的糾結。對於已經習慣VCL元件的開發者,勢必又是另一個頭痛的戰場。

直接看一下沒有HTML和CSS概念下,所產出畫面:
Internet Express能提供標準HTML標籤
再來看現在新版JQuery UI基本款可以做到什麼樣的畫面:
JQuery UI提供的GridView
圖片來源:Jquerygridview.com
雖說美感是見人見智,但大多數人應不滿意標準HTML的表現,不然也不會有JQuery UI的產生。

只是忙於商業邏輯就無力分身的開發員,還要學習Browser Client技術,VCL的優勢明顯派不上用場。

此時VCL for Web,也就是現在的IntraWeb,解決的就是這個問題。

原有Win Form的開發概念可以照搬上Web Form來進行開發。

IW有個最大的優點,也是最大的缺點--RunTime時期針對不同呼叫的Browser,產出配合Browser的HTML。

也就是說,原Win Form的開發者不再需要考慮Browser版面的處理,完全交由IW做自動最佳化的處理。

這是優點,反過來說也是缺點,對於Browser版本的限制,導致必須隨著Browser升級,或變更時,也要跟著升級IW。

另一方面,IW是版權軟體,當時的相容性又堪慮。在這種花錢還受罪的場合下,綜合得出C++ Builder沒有更為合適的Web開發的解決方案。

砍掉C++ Builder重練是否為最好的選擇?

再談Web化
會採用Web化的原因是,現在所有的作業系統中,一定會有瀏覽器,所以就沒有軟體安裝的問題,Web的安全性也相對得要比Win Form要來得好一點。
2014蔚為流行的瀏覽器綁架事件之一
圖片來源:Google 圖片

但事實上,如果Web安全性這麼高,就不需要防毒軟體存在。

從瀏覽器被綁架的事件滋生不斷中就可以得出,Web安全性也有它的漏洞存在。

被封裝好的執行檔(EXE)就一定不安全嗎?

在人手一機,還必備防毒軟體的現況下,執行檔有個什麼閃失就容易被防毒軟體抓去「收容」,執行檔就必不安全?

執行檔還有另一問題,就是部署了。

Inno Setup、InstallAware和InstallShield等都是解決部署問題的方法。

那麼執行檔變Portable(免安裝)化不可以嗎?

要讓使用者享受物聯網服務,就只有Web可以選擇?

說穿了,最終就只是載具問題罷了。

那穿透網際網路,執行檔直接穿透網際網路連接資料庫,光是安全性話題就足夠戰好幾回合,在這邊就不表了。

而C++ Builder有什麼可以跨網際網路的資料連結方案?

現成的概念就是MIDAS--分散式應用系統。




於是我就擁抱Delphi了。

2015/03/03

客戶的要求,Web化

其實這篇的內容比較和DataSnap沒有直接的關聯。

話說,客戶要求Web化的理由很簡單,就是希望能在出差的時候也能掌握設備的動態

這不就是互聯網的概念嗎!想法很先進,可惜太早了,Delphi引進物聯網概念也是2014年時的事情。

當時有考慮過IntraWeb,只是當時它的支援度很另人緊張——因為並不支援當時全球第一大瀏覽器:Internet Explorer 6。
Atozed Software - IntraWeb
圖片來源:Atozed

幾經試作後,IntraWeb的開發方式比較接近ASP.NET 1.0的網站絕對定位設計方法,甚至IntraWeb還可以做到不需要了解HTTP、CSS和JavaScript就能完成網站的架設。

你棒棒你,想不到這產品這麼威能。

可惜, 最後還是敗在不能提供IE6的網頁的缺陷下而被否決。

最後在當時個人實力有限的慘況下(另一說是IntraWeb花了太多時間練習),只好請功力深厚的同事操刀,最終拍案,採取PHP來進行網站後端程式開發。

而使用PHP開發,想當然爾,資料庫九成九一定會選擇MySQL,果真沒錯,就是MySQL。

兩種異質資料庫並行的情況下,資料同步又是另一個問題,而且又是要讓PHP讀取即時資料,採C++ Builder進行資料同步勢必還是有延遲時間。(事後回過頭來想,好像也沒有延遲多久,多慮了)

但才剛改成FireBird資料庫的我,還沒來得讓我思考PHP能不能連結FireBird,主管早搶一步表示案子進度已經燒屁股了,怎麼有膽量再去挑戰PHP和FireBird的相容性。



再把FireBird換回MySQL吧!


dbExpress經驗值 + 2。

RAD Studio 2015 Roadmap

以下內容雖是正式內容,但EMBT不做任何保證。

平台和編譯器方面:
增加iOS 64位元編譯程式。
Windows 32位元的C++編譯器:
基於LLVM工具集,以近似於C++ 64位元版本編譯器特色(含C++11)。
(LLVM based toolchain similar to the 64-bit Windows compiler language features, including C++11)


寫程式的開發環境(IDE):
提高對大量記憶體的系統下,開發環境的穩定性。
整合Library管理功能。
主要增強FireUI對多平台裝置的設計,也包含其預覽功能。

Windows 10
具體支援Windows10:
VCL和FireMonkey。
新增許多元件和Library。
封裝更多的API。
整合新的Windows 10平台技術。

VCL和Run-Time Library:
改善VCL表現風格,支援4K螢幕、大型文字和其它增強。
提供VCL(含FireMonkey)應用程式分析。
提供原生HTTP(S)用戶端程式庫給全部平台。

FireMonkey
擴充FireMonkey控制項,包括:
新的行動裝置元件,如Maps。
被遺忘的元件,如WebBrowser。
更多iOS平台控制項和更佳的視圖層(z-order)管理器(iOS限定)。

物聯網
更貼近行動裝置的整合,預計支援Beacon技術。
基於元件形式的模組化以連接不同的裝置,和控制異質API的小工具。
遠程端點(裝置)的資料收集和分析。

企業和多層架構
FireDAC:新的企業級資料庫驅動程式以強化效能。
InterBase XE7變更視圖(Views)項目。
更緊密的整合EMS(Enterprise Mobility Services)。
NoSQL資料庫支援。
EMS:推播訊息和數個擴充。
DataSnap 在核心Web技術上的清理和改善。

其它平台下的了解和調查
觀注2015年iOS和Android的走向。
研究Web Service 應用程式(如WebBroker, DataSnap和EMS)對Linux伺服器站支援。
選擇性支援Android Intel平台。
Mac OS X 的64位元工具集。

預計第一季釋出新的版本和其它廢話。

大致上沒有太亮眼的功能。
以上

資料來源:Delphi & C++Builder 移動開發FB社群

Delphi 自動化 JSON 格式相容性分析

Delphi 自動化產出的 JSON 格式一直被詬病著,因為它的 JSON 格式在起始處一定會強制寫入「Meta Data」,它看起來像是: "table":[["EmpNo",6,0,0,0,4,0,0,false,false,...