Delphi 2007: сохранить только параметры точки останова в файле DSK?

Возможно ли в Delphi просто сохранить точку останова в файле.DSK для проекта и других параметров рабочего стола?

Большая часть.DSK мешает, но неспособность сохранять контрольные точки отладки - настоящая боль (особенно когда они условно или действия прилагаются).

1 ответ

Я никогда не сталкивался с средством IDE, чтобы сохранить только параметры точки останова в файле.Dsk.

Для развлечения я подумал, что попытаюсь реализовать что-то через надстройку IDE, используя уведомления OTA. Приведенный ниже код отлично работает в пакете, установленном в D7, и среда IDE выглядит вполне счастливой, чтобы повторно открыть проект, файл которого был обработан им. Dsk (и точки останова установлены!).

Как вы можете видеть, оно захватывает событие FileNotification уведомления OTA при вызове с NotifyCode of ofProjectDesktopSave, который происходит сразу после того, как среда IDE сохранила файл.Dsk (первоначально с расширением ". $$$", который я могу заметить, когда сначала написав это). Затем он считывает сохраненный файл и готовит обновленную версию, из которой удаляются все, кроме указанного списка разделов. Затем у пользователя есть возможность сохранить разреженный файл обратно на диск. Я использовал TMemIniFile, чтобы выполнить большую часть обработки, чтобы свести к минимуму количество необходимого кода.

У меня был нулевой опыт написания уведомителя OTA, когда я читал ваш q, но ответы экспертов GE, упомянутые ниже, были чрезвычайно полезны, например, код исключения кода.

Обычно удаление файла.Dsk проекта является безобидным, но используйте этот код с осторожностью, поскольку он не подвергался стресс-тестированию.

Обновление: я заметил, что имя файла, полученное событием TIdeNotifier.FileNotification, фактически имеет расширение '. $$$'. Я не совсем уверен, почему это должно быть, но, похоже, событие вызывается до того, как файл будет переименован в xxx.Dsk. Я думал, что это потребует изменения в том, как сохранить разреженную версию, но, очевидно, нет.

Обновление № 2. Используя утилиту мониторинга папок, чтобы узнать, что происходит на самом деле, выясняется, что уведомление о сохранении рабочего стола, которое получает код, является только первым из нескольких операций, связанных с файлом.Dsk. Они включают переименование любой существующей версии файла.Dsk в виде файла. ~ Dsk и, наконец, сохранение файла $$$ в качестве нового файла.Dsk.

unit DskFilesu;

interface

{$define ForDPK} // undefine to test in regular app

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 Buttons, StdCtrls, IniFiles, TypInfo
{$ifdef ForDPK}
 , ToolsApi
{$endif}
 ;

{$ifdef ForDPK}

{
 Code for OTA TIdeNotifier adapted from, and courtesy of, the link on http://www.gexperts.org/open-tools-api-faq/#idenotifier
}

type
 TIdeNotifier = class(TNotifierObject, IOTANotifier, IOTAIDENotifier)
 protected
 procedure AfterCompile(Succeeded: Boolean);
 procedure BeforeCompile(const Project: IOTAProject; var Cancel: Boolean);
 procedure FileNotification(NotifyCode: TOTAFileNotification;
 const FileName: string; var Cancel: Boolean);
 end;
{$endif}

type
 TDskForm = class(TForm)
 edDskFileName: TEdit;
 SpeedButton1: TSpeedButton;
 OpenDialog1: TOpenDialog;
 lbSectionsToKeep: TListBox;
 lbDskSections: TListBox;
 moDskFile: TMemo;
 btnSave: TButton;
 procedure btnSaveClick(Sender: TObject);
 procedure FormCreate(Sender: TObject);
 procedure SpeedButton1Click(Sender: TObject);
 private
 procedure GetSectionsToKeep;
 function GetDskFileName: String;
 procedure SetDskFileName(const Value: String);
 function GetDskFile: Boolean;
 protected
 public
 DskIni : TMemIniFile;
 property DskFileName : String read GetDskFileName write SetDskFileName;
 end;

var
 NotifierIndex: Integer;
 DskForm: TDskForm;

{$ifdef ForDPK}
procedure Register;
{$endif}

implementation

{$R *.DFM}

{$ifdef ForDPK}
procedure Register;
var
 Services: IOTAServices;
begin
 Services := BorlandIDEServices as IOTAServices;
 Assert(Assigned(Services), 'IOTAServices not available');
 NotifierIndex := Services.AddNotifier(TIdeNotifier.Create);
end;
{$endif}

procedure DskPopUp(FileName : String);
var
 F : TDskForm;
begin
 F := TDskForm.Create(Application);
 try
 F.DskFileName := FileName;
 F.ShowModal;
 finally
 F.Free;
 end;
end;

function TDskForm.GetDskFileName: String;
begin
 Result := edDskFileName.Text;
end;

procedure TDskForm.SetDskFileName(const Value: String);
begin
 edDskFileName.Text := Value;
 if Assigned(DskIni) then
 FreeAndNil(DskIni);
 btnSave.Enabled := False;

 DskIni := TMemIniFile.Create(DskFileName);
 DskIni.ReadSections(lbDskSections.Items);
 GetSectionsToKeep;
end;

procedure TDskForm.btnSaveClick(Sender: TObject);
begin
 DskIni.UpdateFile;
end;

procedure TDskForm.FormCreate(Sender: TObject);
begin
 lbSectionsToKeep.Items.Add('watches');
 lbSectionsToKeep.Items.Add('breakpoints');
 lbSectionsToKeep.Items.Add('addressbreakpoints');

 if not IsLibrary then
 DskFileName := ChangeFileExt(Application.ExeName, '.Dsk');
end;

procedure TDskForm.GetSectionsToKeep;
var
 i,
 Index : Integer;
 SectionName : String;
begin
 moDskFile.Lines.Clear;
 for i := lbDskSections.Items.Count - 1 downto 0 do begin
 SectionName := lbDskSections.Items[i];
 Index := lbSectionsToKeep.Items.IndexOf(SectionName);
 if Index < 0 then
 DskIni.EraseSection(SectionName);
 end;
 DskIni.GetStrings(moDskFile.Lines);
 btnSave.Enabled := True;
end;

function TDskForm.GetDskFile: Boolean;
begin
 OpenDialog1.FileName := DskFileName;
 Result := OpenDialog1.Execute;
 if Result then
 DskFileName := OpenDialog1.FileName;
end;

procedure TDskForm.SpeedButton1Click(Sender: TObject);
begin
 GetDskFile;
end;

{$ifdef ForDPK}

procedure RemoveNotifier;
var
 Services: IOTAServices;
begin
 if NotifierIndex <> -1 then
 begin
 Services := BorlandIDEServices as IOTAServices;
 Assert(Assigned(Services), 'IOTAServices not available');
 Services.RemoveNotifier(NotifierIndex);
 end;
end;

function MsgServices: IOTAMessageServices;
begin
 Result := (BorlandIDEServices as IOTAMessageServices);
 Assert(Result <> nil, 'IOTAMessageServices not available');
end;

procedure TIdeNotifier.AfterCompile(Succeeded: Boolean);
begin
end;

procedure TIdeNotifier.BeforeCompile(const Project: IOTAProject; var Cancel: Boolean);
begin
 Cancel := False;
end;

procedure TIdeNotifier.FileNotification(NotifyCode: TOTAFileNotification;
 const FileName: string; var Cancel: Boolean);
begin
 Cancel := False;
 // Note: The FileName passed below has an extension of '.$$$'
 if NotifyCode = ofnProjectDesktopSave then
 DskPopup(FileName);
end;

initialization

finalization
 RemoveNotifier;
{$endif}

end.

licensed under cc by-sa 3.0 with attribution.