- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
如何在给定 IOTAProject
的情况下获取目标可执行文件的名称?
来自GExpert's OpenTools API FAQ :
How can I determine the filename of the binary/exe/dll/bpl/ocx/etc. generated by a compile or build?
- For Delphi 8 or greater, useIOTAProjectOptions.TargetName
.
- For earlier releases, the method is a lot more complex to implement because it involves potentially scanning for the $E directive that specifies the executable file extension for the project, and then looking for the binary file on the path specified by the "OptputDir" project option, or the project directory if that option is blank (among many other possibilities and complexities). The best way to implement such a tool might be to start with the sample code in CodeGear CodeCentral sample ID 19823.
就我而言,我属于后者。给定一个 IOTAProject 接口(interface),其核心内容是:
function GetTargetName(Project: IOTAProject): TFilename;
begin
//todo
end;
<小时/>
如果是 Delphi 8 或更高版本,(未经测试的)答案是:
{$I compilers.inc}
function GetTargetName(Project: IOTAProject): TFilename;
begin
{$IFDEF COMPILER_8_UP}
Result := Project.ProjectOptions.TargetName;
{$ELSE}
raise Exception.Create('Not yet implemented');
{$ENDIF}
end;
但更困难的是 Delphi 8 之前的复杂版本。
Jedi JCL 内部 TJclOTAExpert
中有十几个方法,可以一起用来模拟:
Project.ProjectOptions.TargetName
我将努力完成该代码。几周后,我希望能够发布我自己的问题的答案。
但与此同时,我会打开它,让其他人因能够回答我的问题而获得声誉。
最佳答案
link据我所知,您提到的对于 Delphi 8 之前的版本运行良好。您只需复制 GetTargetFileName
函数及其使用的一些函数即可。
编辑:感谢 Premature Optimization我现在知道 Delphi 6+ $LibPrefix
和相关指令在源代码中使用时会被此函数错过/忽略。不过,这在 Delphi 5 中应该不会造成任何问题。
该函数执行以下操作:
$(...)
变量引用(如果有)代码应该为您提供在 Delphi 5 到 7 中获取项目的正确目标文件名所需的一切。
编辑:这是代码(从 link 复制+粘贴):
{$IFDEF VER130}
{$DEFINE DELPHI_5_UP}
{$ENDIF}
{$IFDEF VER140}
{$DEFINE DELPHI_5_UP}
{$DEFINE DELPHI_6_UP}
{$ENDIF}
{$IFDEF VER150}
{$DEFINE DELPHI_5_UP}
{$DEFINE DELPHI_6_UP}
{$DEFINE DELPHI_7_UP}
{$ENDIF}
{$IFNDEF DELPHI_5_UP}
Delphi 5 or higher required.
{$ENDIF}
{$IFNDEF DELPHI_6_UP}
function ExcludeTrailingPathDelimiter(const S: string): string; forward;
function IncludeTrailingPathDelimiter(const S: string): string; forward;
{$ENDIF}
// get Delphi root directory
function GetDelphiRootDirectory: string;
{$IFNDEF DELPHI_7_UP}
var
Registry: TRegistry;
{$ENDIF}
begin
{$IFDEF DELPHI_7_UP}
Result := (BorlandIDEServices as IOTAServices).GetRootDirectory;
{$ELSE}
Registry := TRegistry.Create(KEY_READ);
try
if Registry.OpenKeyReadOnly((BorlandIDEServices as IOTAServices).GetBaseRegistryKey) then
Result := Registry.ReadString('RootDir');
finally
Registry.Free;
end;
{$ENDIF}
end;
// get Delphi environment variables (name-value pairs) from the registry
procedure GetEnvVars(Strings: TStrings);
var
Registry: TRegistry;
I: Integer;
begin
Registry := TRegistry.Create(KEY_READ);
try
Registry.RootKey := HKEY_CURRENT_USER;
if Registry.OpenKeyReadOnly((BorlandIDEServices as IOTAServices).GetBaseRegistryKey + '\Environment Variables') then
begin
Registry.GetValueNames(Strings);
for I := 0 to Strings.Count - 1 do
Strings[I] := Strings[I] + '=' + Registry.ReadString(Strings[I]);
end;
finally
Registry.Free;
end;
end;
// get output directory of a project
function GetProjectOutputDir(const Project: IOTAProject): string;
begin
if Project.ProjectOptions.Values['GenPackage'] then // package project
begin
// use project options if specified
Result := Project.ProjectOptions.Values['PkgDllDir'];
// otherwise use environment options
if Result = '' then
Result := (BorlandIDEServices as IOTAServices).GetEnvironmentOptions.Values['PackageDPLOutput'];
end
else // non-package project, use project options
Result := Project.ProjectOptions.Values['OutputDir'];
// default is the project's path
if Result = '' then
Result := ExtractFilePath(Project.FileName);
Result := IncludeTrailingPathDelimiter(Result);
end;
// get project source editor
function GetProjectSourceEditor(const Project: IOTAProject): IOTASourceEditor;
var
I: Integer;
begin
Result := nil;
for I := 0 to Project.GetModuleFileCount - 1 do
if Supports(Project.GetModuleFileEditor(I), IOTASourceEditor, Result) then
Break;
end;
// get system environment variables
procedure GetSysVars(Strings: TStrings);
var
P: PChar;
begin
P := GetEnvironmentStrings;
try
repeat
Strings.Add(P);
P := StrEnd(P);
Inc(P);
until P^ = #0;
finally
FreeEnvironmentStrings(P);
end;
end;
function GetTargetExtOverride(const Project: IOTAProject): string; overload; forward;
// get target extension
function GetTargetExt(const Project: IOTAProject): string;
begin
// use {$E ...} override if specified
Result := GetTargetExtOverride(Project);
// otherwise use defaults
if Result = '' then
begin
if Project.ProjectOptions.Values['GenPackage'] then // package
Result := '.bpl'
else if Project.ProjectOptions.Values['GenDll'] then // DLL
Result := '.dll'
else // application
Result := '.exe';
end;
end;
// read {$E ...} directive from project source
function GetTargetExtOverride(const ProjectSource: string): string; overload;
var
P: PChar;
procedure SkipComment(var P: PChar);
begin
case P^ of
'{':
begin
while not (P^ in [#0, '}']) do
Inc(P);
if P^ = '}' then
Inc(P);
end;
'/':
if (P + 1)^ = '/' then
begin
while not (P^ in [#0, #10, #13]) do
Inc(P);
while (P^ in [#10, #13]) do
Inc(P);
end;
'(':
if (P + 1)^ = '*' then
repeat
Inc(P);
case P^ of
#0:
Break;
'*':
if (P + 1)^ = ')' then
begin
Inc(P, 2);
Break;
end;
end;
until False;
end;
end;
procedure SkipStringLiteral(var P: PChar);
begin
if P^ <> '''' then
Exit;
Inc(P);
repeat
case P^ of
#0:
Break;
'''':
begin
Inc(P);
if P^ = '''' then
Inc(P)
else
Break;
end;
else
Inc(P);
end;
until False;
end;
procedure SkipNonDirectives(var P: PChar);
begin
repeat
case P^ of
#0:
Break;
'''':
SkipStringLiteral(P);
'/':
case (P + 1)^ of
'/':
SkipComment(P);
else
Inc(P);
end;
'(':
case (P + 1)^ of
'*':
SkipComment(P);
else
Inc(P);
end;
'{':
begin
case (P + 1)^ of
'$':
Break;
else
SkipComment(P);
end;
end;
else
Inc(P);
end;
until False;
end;
begin
P := PChar(ProjectSource);
repeat
SkipNonDirectives(P);
case P^ of
#0:
Break;
'{':
if StrLIComp(P, '{$E ', 4) = 0 then
begin
Inc(P, 4);
Result := '.';
while P^ = ' ' do
Inc(P);
while not (P^ in [#0, '}']) do
begin
if P^ <> ' ' then
Result := Result + P^;
Inc(P);
end;
Break;
end
else
SkipComment(P);
end;
until False;
end;
// read {$E ...} directive from project source module
function GetTargetExtOverride(const Project: IOTAProject): string; overload;
const
BufferSize = 1024;
var
SourceEditor: IOTASourceEditor;
EditReader: IOTAEditReader;
Buffer: array[0..BufferSize - 1] of Char;
Stream: TStringStream;
ReaderPos, CharsRead: Integer;
begin
SourceEditor := GetProjectSourceEditor(Project);
if Assigned(SourceEditor) then
begin
EditReader := SourceEditor.CreateReader;
Stream := TStringStream.Create('');
try
ReaderPos := 0;
repeat
CharsRead := EditReader.GetText(ReaderPos, Buffer, BufferSize - 1);
Inc(ReaderPos, CharsRead);
Buffer[CharsRead] := #0;
Stream.WriteString(Buffer);
until CharsRead < BufferSize - 1;
Result := GetTargetExtOverride(Stream.DataString);
finally
Stream.Free;
end;
end;
end;
// get project target file name (with path), resolve $(...) macros if used
function GetTargetFileName(const Project: IOTAProject): string;
var
PStart, PEnd: PChar;
EnvVar, Value, FileName, Ext, S: string;
EnvVars, SysVars: TStringList;
I: Integer;
begin
EnvVars := nil;
SysVars := nil;
try
Result := GetProjectOutputDir(Project);
PStart := StrPos(PChar(Result), '$(');
while PStart <> nil do
begin
Value := '';
PEnd := StrPos(PStart, ')');
if PEnd = nil then
Break;
SetString(EnvVar, PStart + 2, PEnd - PStart - 2);
if CompareText(EnvVar, 'DELPHI') = 0 then // $(DELPHI) macro is hardcoded
Value := GetDelphiRootDirectory
else
begin
// try Delphi environment variables from the registry
if not Assigned(EnvVars) then
begin
EnvVars := TStringList.Create;
GetEnvVars(EnvVars);
end;
for I := 0 to EnvVars.Count -1 do
if CompareText(EnvVar, EnvVars.Names[I]) = 0 then
begin
{$IFDEF DELPHI_7_UP}
Value := ExcludeTrailingPathDelimiter(EnvVars.ValueFromIndex[I]);
{$ELSE}
Value := ExcludeTrailingPathDelimiter(EnvVars.Values[EnvVars.Names[I]]);
{$ENDIF}
Break;
end;
if Value = '' then
begin
// try system environment variables
if not Assigned(SysVars) then
begin
SysVars := TStringList.Create;
GetSysVars(SysVars);
end;
for I := 0 to SysVars.Count - 1 do
if CompareText(EnvVar, SysVars.Names[I]) = 0 then
begin
{$IFDEF DELPHI_7_UP}
Value := ExcludeTrailingPathDelimiter(SysVars.ValueFromIndex[I]);
{$ELSE}
Value := ExcludeTrailingPathDelimiter(SysVars.Values[SysVars.Names[I]]);
{$ENDIF}
Break;
end;
end;
end;
I := PStart - PChar(Result) + 1;
Delete(Result, I, Length(EnvVar) + 3);
Insert(Value, Result, I);
PStart := StrPos(PChar(Result), '$(');
end;
Ext := GetTargetExt(Project);
FileName := ChangeFileExt(ExtractFileName(Project.FileName), '');
// include prefix/suffix/version for DLL and package projects
if Project.ProjectOptions.Values['GenDll'] then
begin
S := Project.ProjectOptions.Values['SOPrefix'];
if Project.ProjectOptions.Values['SOPrefixDefined'] then
FileName := S + FileName;
S := Project.ProjectOptions.Values['SOSuffix'];
if (S <> '') then
FileName := FileName + S;
FileName := FileName + Ext;
S := Project.ProjectOptions.Values['SOVersion'];
if S <> '' then
FileName := FileName + '.' + S;
end
else
FileName := FileName + Ext;
Result := Result + FileName;
finally
EnvVars.Free;
SysVars.Free;
end;
end;
{$IFNDEF DELPHI_6_UP}
function ExcludeTrailingPathDelimiter(const S: string): string;
begin
Result := ExcludeTrailingBackslash(S);
end;
function IncludeTrailingPathDelimiter(const S: string): string;
begin
Result := IncludeTrailingBackslash(S);
end;
{$ENDIF}
关于德尔福开放工具API : How to get target exe name?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7972393/
这个问题在这里已经有了答案: Android ADT version required 20.0.0 and above (10 个答案) 关闭 9 年前。 我刚刚安装了 Eclipse Juno
按照 This page from codeplex 上的指南进行操作后,我无法在我的工具/选项窗口中看到 Python 选项。我认为我与指南的唯一偏差是: 发行版:没有安装 activestate
我有一个非常大的 .sql 脚本。我将此脚本添加到 Visual Studio 2013 下的 SQL Server 项目中。当我尝试构建它时,我收到此错误消息 This T-SQL script e
当我在SpringBoot项目中想加个依赖,但是不确定现有依赖的依赖的依赖.....有没有添加过这个依赖,怎么办呢?如果添加过了但是不知道我需要的这个依赖属于哪个依赖的下面,怎么查呢? IDEA中提供
我正在做一个项目来减少 PDF 的大小,压缩它们。我想知道市场上是否有任何非常好的工具/库(.NET)。 我确实尝试了一些像 Onstream Compression 这样的工具,但结果并不令人满意。
我想从我的源代码编译一个安卓内核。 但我想使用工具或类似的东西。 所以我只需单击一个按钮并获得一个可闪存的 zip 文件... 有工具吗? 我可以用脚本来做吗? 谢谢! 最佳答案 这取决于您从哪里获得
我们生成 pdf 文件,其中包含有关数万名客户每月财务余额的数据。在高峰期(年底有 100.000 个文件),使用在 5 台服务器之间分配负载,该过程可能需要长达 5 天的时间才能完成。工作负载的分配
模块:xmllib xmllib 是一个非验证的低级语法分析器。应用程序员使用的 xmllib 可以覆盖 XMLParser 类,并提供处理文档元素(如特定或类属标记,或字符实体)的方法。从 Py
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 3 年前。
我在一家医疗保健公司工作,拥有有关患者位置(地址、城市、州、 zip )的信息。我试图确定有多少百分比的患者住在离 5 个特定位置最近的地方。我正在寻找的答案是“25% 的患者住在离#1 地点最近的地
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 4年前关闭。 我们不允许在 Stack Overflow 上提出有关通用计算硬件和软件的问题。您可以编辑问
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be
请问我在哪里可以得到 SvcTraceViewer 工具? 我尝试下载并安装许多 SDK。 我查看了程序文件的垃圾箱。 我需要它来跟踪我的 WCF 调用出了什么问题。 最佳答案 您可以通过下载 Win
我正在尝试在我最喜欢的编辑器中设置适当的代码完成功能,我们将其称为AnEditor,以避免互联网上充斥着特定于程序的答案。 (您知道语言是ALanguage。)编辑器具有两个我喜欢的功能:它既可以在控
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
当 merge 的两个分支对同一文件有更改时,Mercurial 是否总是使用外部 merge 工具? 或者它是否首先查看它是否可以 merge 文件本身,如果不能,则仅转向外部工具? 我问的原因是我
我正在为我使用的编辑器编写 Scala 插件,该插件将突出显示所有未使用的代码路径(可能未使用 defs 、 vals 、 classes 和 implicits ),并为用户提供一个选项以将它们从.
我有 jquery 工具滚动器...我喜欢它只为 swipeLeft swipeRight 实现触摸选项。 当我使用 touch: true 时,它也会在向上/向下滑动时旋转.. 我按照此处的说明
我已经尝试了一些用于构建 UML(对象/依赖图)的 Eclipse 工具,但我真正需要的是一个工具来生成这样的代码外 UML。 (反之亦然) 我更喜欢一个简单的 UML 工具,它易于安装并且没有任何依
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我是一名优秀的程序员,十分优秀!