2012-05-28 3 views
0

Я работаю над приложением, которое использует FastMM4, от sourceforge.net. Итак, я добавил FastMM4.pas в предложение uses в начале. В приложении мне нужно запустить batch файл после FinalizeMemoryManager; в finalization из unit FastMM4; как этотdelphi 7, FastMM4 не может установить работу

initialization 
     RunInitializationCode; 

    finalization 
     {$ifndef PatchBCBTerminate} 
     FinalizeMemoryManager; 
     RunTheBatFileAtTheEnd; //my code here..calling a procedure 
     {$endif} 

end. 

тогда мой код RunTheBatFileAtTheEnd является:

procedure RunTheBatFileAtTheEnd; 
begin 
//some code here.... 
    sFilePaTh:=SysUtils.ExtractFilePath(applicaTname)+sFileNameNoextension+'_log.nam'; 
ShellExecute(applcatiOnHAndle,'open', pchar(sExeName),pchar(sFilePaTh), nil, SW_SHOWNORMAL) ; 
end; 

Для этого мне нужно использовать SysUtils,shellapi в пункт использования блока fastmm4. Но используя их это сообщение приходит enter image description here

Но если я удалить SysUtils,shellapi из использует это работает. Мне все еще нужны все функции fastmm4, но с SysUtils,shellapi, fastmm4 не установлен

У меня есть свой блок, но его завершение выполняется до завершения fastmm4.

может кто-нибудь сказать мне, как решить эту проблему?

Edit- 1

unit FastMM4; 
//... 
... 
implementation 

uses 
    {$ifndef Linux}Windows,{$ifdef FullDebugMode}{$ifdef Delphi4or5}ShlObj,{$else} 
    SHFolder,{$endif}{$endif}{$else}Libc,{$endif}FastMM4Messages,SysUtils,shellapi; 

мое приложение

program memCheckTest; 
    uses 
     FastMM4, 

EDIT-2:

(после @SertacAkyuz ответа), я удалил SysUtils, и она работала, но Мне все же нужно запустить командный файл, чтобы открыть внешнее приложение через RunTheBatFileAtTheEnd. Причина состоит в том, что я хочу, чтобы внешнее приложение запускалось только после FastMM4, как из finalization. sExeName - приложение, которое будет запускать файл sFilePaTh (.nam). может ли кто-нибудь сказать, как это сделать? без uninstalling FastMM4.

+0

Какой пункт использует? Если в интерфейсе вы заставляете FastMM4 зависеть от них, они будут сначала инициализированы, включая любые единицы, от которых они зависят. Любое выделение памяти сделало бы это. Вы пробовали переместить два блока в пункт реализации? Это должно изменить порядок зависимостей. –

+0

@MarjanVenema: я добавил новый код для предложения uses, 'SysUtils, shellapi;' находятся в 'реализации' – PresleyDias

+0

Вы должны обойтись без 'sysutils'. Раздел в разделе инициализации «sysutils» требует выделения памяти, поэтому диспетчер памяти должен быть установлен. –

ответ

4

FastMM проверяет, установлен ли менеджер памяти по умолчанию перед установкой его собственным вызовом функции IsMemoryManagerSet в 'system.pas'. Если установлен менеджер памяти по умолчанию, он отклоняет настройку своего собственного менеджера памяти и отображает сообщение, указанное в вопросе.

Инструкция в этом сообщении о «fastmm4.pas» должна быть первым элементом в файле .dpr проекта. имеет предположение, что сам «fastmm4.pas» не изменяется.

При изменении предложения uses «fastmm4.pas», если какой-либо из блоков, включенных в предложение uses, имеет раздел initialization, то этот раздел кода должен быть запущен до раздела инициализации «fastmm4.pas» ». Если этот код требует выделения/удержания памяти через RTL, тогда устанавливается менеджер памяти по умолчанию.

Следовательно, вам нужно позаботиться о том, чтобы изменить «fastmm4.pas», чтобы не включать в это предложение ни одно такое подразделение, например «sysutils.pas».


Ниже пример кода (без проверки ошибок, файл проверки и т.д ..) показывает, как вы можете запустить файл журнала FastMM с Notepad (при условии, что лог-файл существует) без выделения каких-либо памяти:

var 
    CmdLine: array [0..300] of Char; // increase as needed 
    Len: Integer; 
    SInfo: TStartupInfo; 
    PInfo: TProcessInformation; 

initialization 
    ... // fastmm code 

finalization 
{$ifndef PatchBCBTerminate} 
    FinalizeMemoryManager;  // belongs to fastmm 

    // Our application is named 'Notepad' and the path is defined in AppPaths 
    CmdLine := 'Notepad "'; // 9 Chars (note the opening quote) 
    Len := windows.GetModuleFileName(0, PChar(@CmdLine[9]), 260) + 8; 

    // assumes the executable has an extension. 
    while CmdLine[Len] <> '.' do 
    Dec(Len); 

    CmdLine[Len] := #0; 
    lstrcat(CmdLine, '_MemoryManager_EventLog.txt"'#0); // note the closing quote 

    ZeroMemory(@SInfo, SizeOf(SInfo)); 
    SInfo.cb := SizeOf(SInfo); 
    CreateProcess(nil, CmdLine, nil, nil, False, 
       NORMAL_PRIORITY_CLASS, nil, nil, sInfo, pInfo); 

{$endif} 

end. 
+0

Мне нужно иметь' sFilePaTh: = SysUtils.ExtractFilePath (applicaTname) ', который я не могу получить без' SysUtils', так что есть ли способ получить путь к файлу приложения? (даже 'application.exe '). – PresleyDias

+0

ok..let me put this way .. 'Sertac Akyuz' = 'Genius' – PresleyDias

+0

ok..Question: 'Notepad '' мое имя приложения 'tracker.exe', как я пишу его вместо' Notepad' '' ? – PresleyDias

1

Я согласен с ответом Сертака, но также хотел бы дать рекомендацию, если вы настаиваете на использовании SysUtils.pas. Ответ не использует его и извлекает все, что вам нужно, и помещает его в свою собственную копию. Вот то, что вам нужно ниже - ExtractFilePathLastDeliminator, который использовал StrScan, а также 2 константы, поэтому я скопировал их в новый блок и назвал его MySysUtils.pas.

Это также широко используется для людей, которые не хотят иметь кучу дополнительного кода, который они никогда не будут использовать (вы должны быть абсолютно уверены, что он нигде не используется ни в каких единицах).

unit MySysUtils; 

interface 

const 
    PathDelim = '\'; 
    DriveDelim = ':'; 

implementation 

function StrScan(const Str: PWideChar; Chr: WideChar): PWideChar; 
begin 
    Result := Str; 
    while Result^ <> #0 do begin 
    if Result^ = Chr then 
     Exit; 
    Inc(Result); 
    end; 
    if Chr <> #0 then 
    Result := nil; 
end; 

function LastDelimiter(const Delimiters, S: string): Integer; 
var 
    P: PChar; 
begin 
    Result := Length(S); 
    P := PChar(Delimiters); 
    while Result > 0 do begin 
    if (S[Result] <> #0) and (StrScan(P, S[Result]) <> nil) then 
     Exit; 
    Dec(Result); 
    end; 
end; 

function ExtractFilePath(const FileName: string): string; 
var 
    I: Integer; 
begin 
    I := LastDelimiter(PathDelim + DriveDelim, FileName); 
    Result := Copy(FileName, 1, I); 
end; 

end. 
+0

+ 1, эй отличный трюк. !! но как насчет 'Application.ExeName' использует' forms.pas', и я все равно буду иметь ту же проблему, что и Fastmm4, не устанавливая, так что делать в этом случае? получить «Application.ExeName» – PresleyDias

+1

ParamStr (0)? Сделаю? – PresleyDias

+1

@Presley - Вы можете использовать 'GetModuleFileName', как это VCL использовать для ParamStr (0). См. [Этот ответ] (http://stackoverflow.com/questions/10763243/get-the-name-of-the-program-executable-as-in-paramstr0-but-get-it-as-a-unico/ 10765429 # 10765429) для примера реализации (вы можете использовать версию функции ansi). –

Смежные вопросы