0

我正在开发一个使用FastMM4来自sourceforge.net的应用程序。所以我FastMM4.pas在开头就添加了uses子句。在应用程序中,我需要像这样运行一个batch文件FinalizeMemoryManager;finalizationunit 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 单元的使用条款中使用。但是使用它们这个消息来了 在此处输入图像描述

但是,如果我SysUtils,shellapi从用途中删除它就可以了。我仍然需要安装 fastmm4 的所有功能,但是SysUtils,shellapi没有安装 fastmm4

我有一个自己的单元,但它的最终化是在 fastmm4 最终化之前执行的。

谁能告诉我如何解决这个问题?

编辑- 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,

编辑-2:

(在@SertacAkyuz 回答之后),我删除SysUtils了它并且它工作了,但我仍然需要运行批处理文件来打开外部应用程序RunTheBatFileAtTheEnd。原因是..我希望外部应用程序仅在 FastMM4 退出finalization. 这sExeName是将运行文件sFilePaTh(.nam) 的应用程序。任何人都可以告诉如何做到这一点?没有uninstalling FastMM4

4

2 回答 2

5

IsMemoryManagerSetFastMM 通过调用“system.pas”中的函数来检查是否设置了默认内存管理器,然后再安装它自己的。如果设置了默认内存管理器,它会拒绝设置自己的内存管理器并显示问题中显示的消息。

该消息中关于“fastmm4.pas”的说明应该是项目 .dpr 文件中的第一个单元,假设“fastmm4.pas”本身没有被修改。

当你修改“fastmm4.pas”的uses子句时,如果uses子句中包含的任何单元都有一个initialization部分,那么该部分代码必须在“fastmm4.pas”的初始化部分之前运行。如果该代码需要通过 RTL 分配/使用内存,则设置默认内存管理器。

因此,您必须注意将“fastmm4.pas”更改为不在uses 子句中包含任何此类单元,例如“sysutils.pas”。


下面的示例代码(无错误检查、文件检查等)显示了如何在不分配任何内存的情况下使用记事本启动 FastMM 的日志文件(假设日志文件存在):

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.
于 2012-05-28T13:35:43.127 回答
1

我同意 Sertac 的回答,但如果您坚持使用SysUtils.pas. 答案是不要使用它,并从中提取您需要的内容并将其放入您自己的副本中。下面是您需要的 - ExtractFilePathused LastDeliminator、 usedStrScan和 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.
于 2012-05-29T08:55:45.870 回答