2012-05-28 2 views
0

Je travaille sur une application qui utilise FastMM4, de sourceforge.net. J'ai donc ajouté le FastMM4.pas à la clause uses dès le début. Dans l'application que je dois exécuter un fichier batch après FinalizeMemoryManager; dans le finalization de unit FastMM4; comme celui-cidelphi 7, FastMM4 ne peut pas installer de travail autour de

initialization 
     RunInitializationCode; 

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

end. 

alors mon code pour RunTheBatFileAtTheEnd est:

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

Pour cela, je dois utiliser SysUtils,shellapi dans la clause uses de l'unité fastmm4. Mais les utiliser ce message vient enter image description here

Mais si je retire SysUtils,shellapi de l'utilise cela fonctionne. J'ai encore besoin de toutes les fonctionnalités de fastmm4 installées mais avec SysUtils,shellapi, fastmm4 n'est pas installé

J'ai une unité à part, mais sa finalisation est exécutée avant la finalisation fastmm4.

quelqu'un peut-il me dire comment résoudre ce problème?

EDIT- 1

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

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

ma demande

program memCheckTest; 
    uses 
     FastMM4, 

EDIT-2:

(après @SertacAkyuz réponse), je l'ai enlevé SysUtils et cela a fonctionné, mais J'ai encore besoin d'exécuter le fichier batch pour ouvrir une application externe via RunTheBatFileAtTheEnd. La raison est .. je veux qu'une application externe s'exécute seulement après que FastMM4 ait été sur le finalization. Le sExeName est l'application qui va exécuter le fichier sFilePaTh (.nam). quelqu'un peut-il dire comment faire cela? sans uninstalling FastMM4.

+0

Qui utilise la clause? Si dans l'interface, vous faites dépendre FastMM4 d'eux et ils seront initialisés en premier incluant toutes les unités dont ils dépendent. Toute allocation de mémoire effectuée ici provoquerait cela. Avez-vous essayé de déplacer les deux unités à la clause de mise en œuvre? Cela devrait changer l'ordre de dépendance. –

+0

@MarjanVenema: j'ai ajouté un nouveau code pour la clause uses, 'SysUtils, shellapi;' est dans la 'implementation' – PresleyDias

+0

Vous devez faire sans 'sysutils'. Le code dans la section d'initialisation de 'sysutils' doit allouer de la mémoire, par conséquent le gestionnaire de mémoire doit être défini. –

Répondre

4

FastMM vérifie si le gestionnaire de mémoire par défaut est défini avant d'installer le sien par un appel à IsMemoryManagerSet dans 'system.pas'. Si le gestionnaire de mémoire par défaut est défini, il refuse de définir son propre gestionnaire de mémoire et affiche le message affiché dans la question.

L'instruction dans ce message à propos de 'fastmm4.pas' devrait être la première unité du fichier .dpr du projet. a l'hypothèse que 'fastmm4.pas' lui-même n'est pas modifié. Lorsque vous modifiez la clause uses de 'fastmm4.pas', si l'une des unités incluses dans la clause uses a une section initialization, cette section de code doit être exécutée avant la section d'initialisation de 'fastmm4.pas '. Si ce code nécessite d'allouer ou d'enregistrer de la mémoire via RTL, le gestionnaire de mémoire par défaut est défini.

Par conséquent, vous devez faire attention à changer 'fastmm4.pas' pour ne pas inclure une telle unité dans la clause uses, comme 'sysutils.pas'.


Ci-dessous un exemple de code (pas de contrôle d'erreur, la vérification de fichiers etc ..) montre comment pouvez-vous lancer le fichier journal de FastMM avec le Bloc-notes (à condition que le fichier journal existe) sans allouer de la mémoire:

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

je dois avoir le' sFilePaTh: = SysUtils.ExtractFilePath (applicaTname) 'que je ne peux pas obtenir sans le' SysUtils' donc il n'y a aucun moyen d'obtenir le chemin du fichier de l'application? (même 'application.exe '). – PresleyDias

+0

ok..lettez moi de cette façon .. 'Sertac Akyuz' = 'Genius' – PresleyDias

+0

ok..Question: 'Notepad '' mon nom d'application est 'tracker.exe' comment l'écris-je à la place de' Notepad' ' ? – PresleyDias

1

Je suis d'accord avec la réponse de Sertac, mais je voudrais aussi donner une recommandation, si vous insistez pour utiliser SysUtils.pas. La réponse est de ne pas l'utiliser, d'extraire ce dont vous avez besoin et de le mettre dans votre propre copie. Voici ce que vous auriez besoin ci-dessous - ExtractFilePath utilisé LastDeliminator, qui a utilisé StrScan, et aussi 2 constantes, donc je les ai copiés dans cette nouvelle unité et l'ai appelé MySysUtils.pas.

Ceci est également largement utilisé pour les personnes qui ne veulent pas avoir un tas de code supplémentaire compilé qu'ils n'utiliseront jamais (vous devez être absolument sûr qu'il n'est pas utilisé dans n'importe quelle unité).

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, bon truc super. mais qu'en est-il du 'Application.ExeName' utilise' forms.pas' et j'aurai toujours le même problème de Fastmm4 ne s'installant pas, alors que faire dans ce cas? pour obtenir le 'Application.ExeName' – PresleyDias

+1

ParamStr (0)? ça ira? – PresleyDias

+1

@Presley - Vous pouvez utiliser 'GetModuleFileName' car c'est ce que VCL utilise pour ParamStr (0). Voir [cette réponse] (http://stackoverflow.com/questions/10763243/get-the-name-of-the-program-executable-as-in-paramstr0-but-get-it-as-a-unico/ 10765429 # 10765429) pour un exemple d'implémentation (vous pouvez utiliser la version ansi de la fonction). –