2

我只是偶然发现了一些非常奇怪的东西。参考这个截图:

项目选项 > 表格

为什么它显示$R *.res在可用表单列表中?这个项目只有两个表格和一个附加单元,这里是项目的主文件源:

program MyProgram;

uses
  Forms,
  uMain in 'uMain.pas' {fMain},
  uEmail in 'uEmail.pas' {frmEmail},
  Vcl.Themes,
  Vcl.Styles,
  Other.Unit in 'Other.Unit.pas';

{$R *.res}

begin
  Application.Initialize;
  TStyleManager.TrySetStyle('Iceberg Classico');
  Application.Title := 'My Program Title';
  Application.CreateForm(TfMain, fMain);
  Application.Run;
end.

PS - 这是稍微修改过的代码,唯一改变的是程序名称、程序标题和其中一个单元的名称 ( Other.Unit.pas),我知道这是一个不好的例子,因为Unit它是一个保留字。但是原始单元名称有一个命名空间前缀,例如这个。

更新

我遵循了将这个 RES 引用移到 uses 子句之前的建议。在 dong 之后(并清理所有临时文件,重新启动 IDE 等),它仍然显示在列表中。但令我惊讶的是,IDE 实际上已经添加了这个 RES 引用!

所以现在IDE它自己已经把它变成了:

UpdateUnit in 'UpdateUnit.pas' {$R *.res};

(UpdateUnit 是我给它起的一个新名字,所以我不会泄露内部信息)

因此,我打开了 DPROJ 文件并进行了搜索*.res,果然找到了:

<ItemGroup>
        ....
        <DCCReference Include="UpdateUnit.pas">
            <Form>$R *.res</Form>
        </DCCReference>
4

2 回答 2

10

如所写,我无法重现这个......但是,如果我在“Other.Unit in 'Other.unit.pas'”行之后删除了尾随分号(“;”),则会出现“$R *.res”在项目选项中。

据我所知,这不是错误。由于您的评论表明提供的代码与您正在使用的代码不同,因此很难诊断。我将尝试解释正在发生的事情;如果您查看 uMain 和 uEmail 单元,每个单元旁边都有一个注释,即表单名称。由于这些单元可能实际上并未在 IDE 中打开,因此无法知道是否存在与该单元关联的表单。uMain.dfm 的存在并不能保证 uMain.pas 实际上有一个表单(它可能是剩余的)。IDE 将这个简单的注释放在该单元的 uses 子句中,以便告诉项目经理该单元有一个表单。

通过删除“;”,解析器将下一个注释标记视为 {$R *.res}。然后它得出结论,Other.Unit.pas 必须包含一个名为“$R *.res”的表单。它不验证名称,甚至不尝试打开该单元。它仅采用该评论的原始内容并假定它是表单名称。

您可以安全地将 {$R *.res} 移动到 uses 子句之前,以便项目解析器不会将该指令注释混淆为表单。

编辑:根据我上面的评论:

可能发生的事情是这样的;在某些时候,您可能已经编辑了 .dpr 文件,导致解析器误以为“$R *.res”是表单名称。然后,您在该状态下保存了它,这也将该信息注入到 .dproj 文件中。IDE 尝试使这两个东西保持同步,有时会将 .dproj 文件作为“主”文件并更新 .dpr 文件以匹配。您应该能够安全地从 dproj 文件中删除 $R *.res。

于 2013-05-22T17:18:45.483 回答
4

这不会在 Delphi XE2 Update 4 中重现(见下文)。
更准确地说:您发布的代码不会重现。

但是您在评论中描述的情况确实如此:如果.dproj被软管,IDE 会将不正确的信息重新添加到您的.dpr. 请参阅下面的进一步说明。

在这个答案的最后,一个编辑显示你在客户端发生了一个事件:Delphi XE2 可能会以某种方式混淆到内部状态出错,它会写回错误.dproj.dpr文件。

如果您发布的代码与失败的代码不同,请用失败的代码更正您的问题(并对我的答案发表评论,以便我收到通知并更新 QC 条目;在当前表格中,您的 QC 条目将被标记为“无法复制”然后关闭)。

在 AV 之后,或者当 .pas 或 .dpr 文件中的行结尾不是 CRLF 时,或者在手动编辑 .DPR 文件时,我已经看到 IDE 在各个地方(包括项目选项)出现混淆。

当您重新启动 IDE 时,这些问题通常会消失。有时您甚至需要清理一些文件(使用 .DCU、.local 等扩展名)。

最坏的情况是 IDE 变得如此混乱,以至于 .DPR 和 .DPROJ 都包含错误的信息(因此我的评论),这似乎是您的情况(感谢您编辑的问题)。您可以手动编辑 .DPROJ 和 .DPR 文件来解决此问题。确保有备份,因为很容易破坏 .DPROJ 文件的 XML 格式

如果我将 RES 声明移到分号之前,我可以重现它:这是 IDE 期望的格式,因此它可以解析 .DPR 的 Forms、DataModules 和 Frames(以及可能的其他设计表面):

  Unit1 in 'Unit1.pas' {DataModule1: TDataModule},
  Unit2 in 'Unit2.pas' {Frame2: TFrame};
  Unit3 in 'Unit3.pas' {Form3};

基本上,您不应该编辑 .DPR 文件:IDE 拥有它并将重写它,例如当您向项目添加新单元、更改程序图标、更改应用程序标题等时。

不复现的主程序:

program MyProgram;

uses
  Vcl.Forms,
  uMain in 'uMain.pas' {fMain},
  uEMail in 'uEMail.pas' {frmEmail},
  Vcl.Themes,
  Vcl.Styles,
  Other.Module in 'Other.Module.pas';

{$R *.res}

begin
  Application.Initialize;
  TStyleManager.TrySetStyle('Iceberg Classico');
  Application.Title := 'My Program Title';
  Application.CreateForm(TfMain, fMain);
  Application.Run;
end.

选项对话框:

在此处输入图像描述

确实重现的主程序(注意 RES 的位置):

program MyProgram;

uses
  Vcl.Forms,
  uMain in 'uMain.pas' {fMain},
  uEMail in 'uEMail.pas' {frmEmail},
  Vcl.Themes,
  Vcl.Styles,
  Other.Module in 'Other.Module.pas' {$R *.res};

begin
  Application.Initialize;
  TStyleManager.TrySetStyle('Iceberg Classico');
  Application.Title := 'My Program Title';
  Application.CreateForm(TfMain, fMain);
  Application.Run;
end.

编辑 20130616

在下面的客户端遇到这个问题是前后的差异.dpr.dproj一些名称已匿名)。

Delphi XE2 不知何故感到困惑:导致此问题的不是 .dpr 中的编辑。

我怀疑有两件事:

  • 某处的访问冲突覆盖了某些内部状态,导致内部项目结构被损坏(该项目依赖于要安装的大量 3rd 方包,所有这些包都在同一个 BDS 进程中)
  • .dpr 中有很多代码可能会混淆内部项目结构

我已将所有 .dpr 代码重构为一个单独的模块。希望这是原因,并且不会再发生这种情况。

旧 .dpr 片段:

program Server;

uses
  ShareMem,
  SysUtils,
  Forms,
  SvcMgr,
  WebReq,
  uMain in 'uMain.pas' {fMain},
//...
  uDBOrm in 'uDBOrm.pas',
  uWinProxySettings in '..\..\..\Server\trunk\Server\uWinProxySettings.pas',
  GpStuff in 'GpStuff.pas',
  DSiWin32 in 'DSiWin32.pas';

{$R *.res}

function IsServiceApp: Boolean;
begin
//...
end;

begin
  if IsServiceApp = True then
  begin
//...
  end else
  begin // GUI Interface
    if Assigned(Application) then
       FreeAndNil(Application);
    Forms.Application.Initialize;
    Forms.Application.MainFormOnTaskbar := True;
    ReportMemoryLeaksOnShutdown := True;
    Forms.Application.CreateForm(TfMain, fMain);
    Forms.Application.Run;
  end;
end.

新的 .dpr 片段:

program Server;

uses
  ShareMem,
  SysUtils,
  Forms,
  SvcMgr,
  WebReq,
  uMain in 'uMain.pas' {fMain},
//...
  uDBOrm in 'uDBOrm.pas' {$R *.res},
  uWinProxySettings in '..\..\..\Server\trunk\Server\uWinProxySettings.pas',
  GpStuff in 'GpStuff.pas',
  DSiWin32 in 'DSiWin32.pas';

{$R *.res}

function IsServiceApp: Boolean;
begin
//...
end;

begin
  if IsServiceApp = True then
  begin
//...
  end else
  begin // GUI Interface
    if Assigned(Application) then
       FreeAndNil(Application);
    Forms.Application.Initialize;
    Forms.Application.MainFormOnTaskbar := True;
    ReportMemoryLeaksOnShutdown := True;
    Forms.Application.CreateForm(TfMain, fMain);
    Forms.Application.Run;
  end;
end.

旧 .dproj 片段:

        <DCCReference Include="uDBOrm.pas"/>
        <DCCReference Include="..\..\..\Server\trunk\Server\uWinProxySettings.pas"/>

新的 .dproj 片段:

        <DCCReference Include="uDBOrm.pas">
            <Form>$R *.res</Form>
        </DCCReference>
        <DCCReference Include="..\..\..\Server\trunk\Server\uWinProxySettings.pas"/>
于 2013-05-22T17:24:34.577 回答