2013-03-16 104 views
9

I'm宣佈MidasLib避免一些客戶造成MIDAS.DLL DLL地獄。MidasLib.dcu使應用程序變慢

以下代碼在2350ms左右運行。如果我在使用中刪除了MidaLib聲明,它將在45ms內開始運行!

data.xml文件的保存與TClientDataSet.SaveToFile方法,有5000條記錄,其大小約的600Kb。

有誰知道如何解釋這種怪異的行爲?

我可以證實在Delphi XE2 UPD 3和德爾福XE3 UPD 2.

感謝的問題。

program Loader; 

{$APPTYPE CONSOLE} 

{$R *.res} 

uses 
    MidasLib, 
    System.SysUtils, 
    Winapi.Windows, 
    Data.DB, 
    Datasnap.DBClient; 

var 
    cds : TClientDataSet; 
    start, stop : Cardinal; 
begin 
    cds := TClientDataSet.Create(nil); 
    try 
    start := GetTickCount; 
    cds.LoadFromFile('c:\temp\data.xml'); 
    stop := GetTickCount; 
    Writeln(Format('Time elapsed: %dms', [stop-start])); 
    finally 
    cds.Free; 
    end; 
end. 
+6

現有bug報告http://qc.embarcadero.com/wc/qcmain.aspx ?d = 109476,http://qc.embarcadero.com/wc/qcmain.aspx?d=107346 – bummi 2013-03-16 13:15:36

+0

哪個版本的Delphi? – 2013-03-16 13:37:25

+0

而正在使用Midas.dll的哪個版本? – afrazier 2013-03-16 13:53:12

回答

6
+0

注意[QualityCentral現在已經關閉] (https://community.embarcadero.com/blogs/entry/quality-keeps-moving-forward),所以你不能訪問'qc.embarcadero.com'鏈接了。如果您需要訪問舊的QC數據,請查看[QCScraper](http://www.uweraabe.de/Blog/2017/06/09/how-to-save-qualitycentral/)。 – 2017-06-09 17:20:42

0

我不知道爲什麼你認爲你需要使用MidasLib來「避免DLL地獄」。

當RTL調用TCustomClientDataSet.CreateDSBase時,這會在DSIntf.Pas中調用CheckDbClient。這是通過檢查註冊表來確定哪個實例的Midas.Dll加載的例程。

所以,你可以確保MIDAS.DLL的特定實例用來通過確保註冊表反映其位置CheckDbClient被調用之前。 HK_Classes_Root\CLSId\{9E8D2FA1-591C-11D0-BF52-0020AF32BD64}下的註冊表設置爲InProcServer32。它可以通過調用指定Midas路徑和文件名的RegisterComServer進行更新,當然,必須滿足必要的註冊表訪問權限。

+0

好吧,他確實有過這樣的情況:有些程序或者用自己的DLL覆蓋系統全局DLL,或者在卸載時刪除了庫。 也有非Borland的實現,基於vgLib的早期工作,儘管它們只與一個人分發並且他的項目不是盒子產品,所以我猜想遇到它的機會是無限小的 – 2017-05-17 16:26:46

+0

@ Arioch'The。謝謝。其實,我發佈這個的原因是,前一段時間我被第三方軟件包絆住了,安裝了一個過時的Midas.Dll,並且花了我很長時間才找到問題的根源,直到我意識到已經發生過。 vgLib?我隱約記得在D5/D7時代附近有一個第三方的Midas克隆;我想知道它是否相關。 – MartynA 2017-05-17 16:41:39

+0

最有可能。弗拉基米爾Gaitanov退出德爾福,他雖然在此之前銷售他的克隆(vgLib 1是FLOSS,vgLib 2,這個midas是商業)。至少有一個人在退出時並沒有停下來,並繼續維護和更新他的克隆。但他當然只能使用它,不要放棄或開放它。 – 2017-05-17 16:44:44

0

我們只是使用邁達斯DLL的本地副本,無論是什麼安裝在系統中,只有回落到全球性的,如果當地的一個也沒有找到。

我們使用XE2 upd4 HF1,我們後來改用XE4的邁達斯DLL(主要項目仍與XE2製造)

// based on stock MidasLib unit 

unit MidasDLL; 

interface 

implementation 

uses Winapi.Windows, Winapi.ActiveX, Datasnap.DSIntf, SysUtils, Registry; 

// function DllGetDataSnapClassObject(const CLSID, IID: TGUID; var Obj): HResult; stdcall; external 'Midas.DLL'; 
//var DllGetDataSnapClassObject: function(const CLSID, IID: TGUID; var Obj): HResult; stdcall; //external 'Midas.DLL'; 
var DllGetDataSnapClassObject: pointer; //external 'Midas.DLL'; 

const dllFN = 'Midas.DLL'; dllSubN = 'DllGetDataSnapClassObject'; 
var DllHandle: HMODULE = 0; 

function RegisteredMidasPath: TFileName; 
const rpath = '\SOFTWARE\Classes\CLSID\{9E8D2FA1-591C-11D0-BF52-0020AF32BD64}\InProcServer32'; 
var rry: TRegistry; 
begin 
    Result := ''; 
    rry := TRegistry.Create(KEY_READ); 
    try 
    rry.RootKey := HKEY_LOCAL_MACHINE; 
    if rry.OpenKeyReadOnly(rpath) then begin 
     Result := rry.ReadString(''); 
     if not FileExists(Result) then 
      Result := ''; 
    end; 
    finally 
    rry.Destroy; 
    end; 
end; 

procedure TryFindMidas; 
var fPath, msg: string; 
    function TryOne(const fName: TFileName): boolean; 
    const ver_16_0 = 1048576; // $00060001 
    var ver: Cardinal; ver2w: LongRec absolute ver; 
    begin 
    Result := false; 
    ver := GetFileVersion(fName); 
    if LongInt(ver)+1 = 0 then exit; // -1 --> not found 
    if ver < ver_16_0 then begin 
     msg := msg + #13#10 + 
       'Obsolete version found: '+IntToStr(ver2w.Hi) + '.' + IntToStr(ver2w.Lo) + ' in library file ' + fName; 
     exit; 
    end; 
    DllHandle := SafeLoadLibrary(fName); 
    if DllHandle = 0 then begin 
     msg := msg + #13#10 + 
       'Failure loading library ' + fName + '. Maybe this was Win64 DLL or some other reason.'; 
     exit; 
    end; 
    DllGetDataSnapClassObject := GetProcAddress(DllHandle, dllSubN); 
    if nil = DllGetDataSnapClassObject then begin // не найдена 
     msg := msg + #13#10 + 
       'Incompatible library loaded ' + fName + '. Missed function ' + dllSubN; 
     FreeLibrary(DllHandle); 
     DllHandle := 0; 
    end; 
    Result := true; 
    end; 
    function TryTwo(const fName: TFileName): boolean; // seek in the given folder and its immediate parent 
    begin 
    Result := TryOne(fName + dllFN); 
    if not Result then 
     Result := TryOne(fName + '..\' + dllFN); // 
    end; 
begin 
    fPath := ExtractFilePath(ParamStr(0)); 
    if TryTwo(fPath) then exit; 

    fPath := IncludeTrailingBackslash(GetCurrentDir()); 
    if TryTwo(fPath) then exit; 

    fPath := RegisteredMidasPath; 
    if fPath > '' then 
    if TryOne(fPath) then exit; 

    msg := 'This program needs the library ' + dllFN + ' version 16.0 or above.'#13#10 + 
     'It was not found, thus the program can not work.'#13#10 + #13#10 + msg; 
    Winapi.Windows.MessageBox(0, PChar(msg), 'Launch failure!', 
     MB_ICONSTOP or MB_TASKMODAL or MB_DEFAULT_DESKTOP_ONLY or MB_TOPMOST); 
    Halt(1); 
end; 


initialization 
// RegisterMidasLib(@DllGetDataSnapClassObject); -- static linking does not work for utilities in sub-folders 

    TryFindMidas; // immediately terminates the application if not found 
    RegisterMidasLib(DllGetDataSnapClassObject); 
finalization 
    if DllHandle <> 0 then 
    if FreeLibrary(DllHandle) then 
     DllHandle := 0; 
end.