2014-12-04 2 views
2

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

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

+0

Потому что там, где я сейчас, они делают MiTM на HTTPS-трафика: http://stackoverflow.com/users/3990592/jeroen-pluimers-binck –

+0

OK, это имеет смысл !! –

ответ

6

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

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

Как вы можете видеть, оно захватывает событие FileNotification уведомления OTA при вызове с NotifyCode ofnProjectDesktopSave, который происходит сразу после того, как среда IDE сохранила файл .Dsk (сначала с расширением «. $$$», который я faile заметить при первом написании этого). Затем он считывает сохраненный файл и готовит обновленную версию, из которой удаляются все, кроме указанного списка разделов. Затем у пользователя есть возможность сохранить разреженный файл обратно на диск. Я использовал 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. 
+0

Ничего себе. Спасибо, очень умное решение. Я попробую его позже. Мне нравится простота: намного легче, чем я ожидал. –

+0

Спасибо за редактирование. Я удалил свой ответ после редактирования, как обсуждалось. +1 –

+1

@ JeroenPluimers-Binck: Мои извинения: похоже, что морщина в отношении расширения файла имени файла передается уведомителю - см. Раздел «Обновление» моего ответа. – MartynA

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