我在Delphi XE中编写了一个向导,它工作正常.但是,我还没有想出如何访问Delphi的OTA可以创建的生成的默认单元名称(或表单名称或项目名称).
在我的旧式向导中,我能够调用ToolServices.GetNewModuleName来发现在生成关联源文件时可以使用的可用单元和表单名称.今天的开放式工具API中的等价物是什么?
根据ToolsAPI单元注释,我应该从IOTAModuleCreator.GetImplFileName方法返回一个空白,让Delphi生成文件名.我从这个方法返回一个空字符串,但仍然无法看到我可以访问Delphi正在生成的文件名.
我正在使用 Internet Direct TIdTCPClient 组件与远程服务进行通信,以检索通常约为 5k 大小的消息。在典型的操作中,我会向服务发送大约 400 个请求,每个请求大约需要 1 秒才能完成。大多数时候一切正常。但是,大约有 1% 的时间请求需要 189 秒,而我根本没有收到任何数据。为了便于讨论,我将其称为失败。
我特别有兴趣了解发生故障时究竟发生了什么,以便我可以将我的证据提交给服务的发布者。首先,失败是不可重现的。如果我重新发送失败的请求,它很有可能(可能是 99%)会起作用。
我还捕获了发生故障时发送的请求,因此我能够确认请求格式正确。
我假设在失败期间我得到了一些数据,而不是全部。这是为什么。我的 IdTCPClient 有 30 秒的超时时间(我什至将其设置为 5 秒,但这并没有什么区别)。发生故障时,总是在 189 秒(加上大约 500 毫秒)后发生故障。
因此,我认为在发生故障期间,我的组件正在接收少量数据,这就是我的客户端没有超时的原因。而且,我假设服务断开连接,因为我的超时值都没有设置为 189 秒。另一方面,读取 IOHandler.AllData 不会引发异常(甚至不是 EIdConnClosedGracefully 异常)。我是否正确解释了这个证据?
我想要做的是在服务终止连接之前确认我正在获取一些数据,而不是全部数据。此外,我想知道部分数据是什么样的,因为我相信它可以帮助确定失败的根源。
目前,我的请求类似于以下内容:
//ExceptionName is a temporary global variable
//that I am using while trying to solve this issue
ExceptionName = 'no exception';
try
s := GetRequest(id);
IdTcpClient1.Host := Host;
IdTcpClient1.Port := StrToInt(Port);
IdTcpClient1.ReadTimeout := ReadTimeout;
try
IdTcpClient1.Connect;
except
on e: exception do
begin
ExceptionName …Run Code Online (Sandbox Code Playgroud) 我在MacBook Air上运行VirtualBox(最新版本,4.1.4)下的Windows 7 64位Ultimate.我在Mac上的用户文件夹下创建了一个共享文件夹.我已将此文件夹的读/写权限授予我的帐户.(我还为每个人配置了读/写访问权限,这没有什么区别.)
在VirtualBox下的Windows 7中,我已将该文件夹添加为共享文件夹.
在我的Windows 7 VM中,我可以使用Windows资源管理器查看此文件夹,在其中创建新文件夹和文件,以及读取文件夹和文件.
问题出在Delphi XE2上.如果我尝试打开项目或将项目保存到此共享文件夹,则从"保存"对话框中显示共享(我当前已映射到网络驱动器),并带有一个红色的X图标,表示它有问题.如果我单击此文件夹,Delphi将显示一个标题为"恢复网络连接"的对话框和一条消息"重新连接E:发生错误到\ VBOXSVR\Demos VirtualBox共享文件夹:请求不受支持.此连接没有已经恢复."
我无法在该共享文件夹中保存项目,这使我无法使用Delphi的dpr2xcode.exe实用程序轻松创建iOS应用程序并生成必要的Xcode文件夹.我需要做的是在本地创建项目文件夹,运行dpr2code.exe以生成Xcode项目,然后使用Windows资源管理器将本地文件夹的内容复制到共享文件夹,然后我可以在其中加载生成的在Xcode中编译,编译并运行它.
有谁知道我可以采取任何配置或步骤,以允许Delphi将共享文件夹视为有效文件夹?
为了记录,我在其他版本的Delphi中看到了与在Windows 7主机下运行的VMWare Workstation(8.0)中的Delphi安装的文件夹类似的问题.在这些情况下,Delphi根本不显示共享文件夹.
当底层数据集中的记录数大于时,是否可以从DBGrid的最顶行中获取从基础数据集显示的行号,而不是最顶行是当前选定的行. DBGrid中显示的行数,并且已滚动DBGrid.
这是我的问题.从附加到DBGrid的拖放事件处理程序,我可以使用MyGrid.MouseCoord(X,Y).Y确定drop事件与DBGrid的哪个可见行相关联.当基础数据集包含的记录数小于或等于DBGrid中显示的行数时,此值也是基础数据集中关联记录的行号.
当基础数据集包含的记录多于DBGrid中可见行数时,MyGrid.MouseCoord(X,Y).Y和TDataSet(MyGrid.DataSource.DataSet).RecNo仅在数据集的第一行出现时相同在网格的第一行.
有没有办法在没有选择DBGrid行的情况下识别DBGrid中最顶层显示记录的基础数据集(或偏移量)中的记录号?我知道如果我实际上选择了DBGrid的最顶行,那么我可以使用TDataSet(MyGrid.DataSource.DataSet).RecNo来获取底层数据集的当前记录号.但是,从DBGrid.OnDragOver或DBGrid.OnDragDrop事件我只有DBGrid和鼠标坐标的引用(我可以从中确定网格的哪一行是放置的目标).
例如,如果我可以确定DBGrid在网格的最顶行中的基础数据集中显示第三条记录,我的问题就解决了.同样,如果我可以读取特定行的底层TField(例如,最顶行)而没有选择该行,我就拥有了我需要的东西.但是,我看不到这样做的方法.
任何建议将不胜感激.
编辑:我之前发布了一篇关于拖放到DBGrid的博客.有了这个新信息,我可以解决以前已知的问题.我将在本周的某个时候更新该博客,并且一旦我这样做,就会在这里添加一个指向该博客的链接.
还有一个问题.当可见行的数量小于基础记录的数量时,我们还需要计算在最后一个可见行之后发生的下降.在最后一个可见行之后删除时,MouseCoord(x,y).Y返回-1.
以下是对Uwe代码的修改,以实现这一目的:
function TDBGridHelper.RecNoFromVisibleRow(Value: Integer): Integer;
begin
if Value = -1 then
begin
Result := DataSource.DataSet.RecNo - Row + TopRow + VisibleRowCount
end
else
begin
Result := DataSource.DataSet.RecNo - Row + TopRow + Value;
if dgTitles in Options then
Dec(Result);
end;
end;
Run Code Online (Sandbox Code Playgroud)
编辑:正如我在原始问题中提到的,我对这个答案很感兴趣,以便修复我的代码中实现拖放到DBGRid中的行为.有了这个答案,我已经更新了我的拖放行为,我在博客中写过这个更新.您可以在以下URL找到此讨论,包括原始博客文章的链接:拖放到DBGrid中重新访问
使用Delphi的DataSnap创建的RESTful服务基于HTTP方法类型为DataSnap服务器中公开的REST方法提供了前缀的默认映射.这些如下:
HTTP Method type Prefix Example
GET none MyValue
POST Update UpdateMyValue
PUT Accept AcceptMyValue
DELETE Cancel CancelMyValue
Run Code Online (Sandbox Code Playgroud)
文档声明"可以覆盖映射模式.用户可以根据类名和方法名参数覆盖每种类型的映射." 但是,我完全没有找到有关如何执行此操作的任何文档.我想将PUT的前缀从Accept更改为其他内容.我怎么做?
我应该注意到,StackOverflow上的另一个帖子(REST Datasnap覆盖URI映射)试图通过指出TDSHTTPService具有执行此映射的方法来回答这个问题.同一篇文章还引用了MarcoCantù的DataSnap白皮书,该白皮书据说也描述了如何做到这一点.该白皮书说:"您可以通过处理DSHTTPWebDispatcher组件的四个相应事件处理程序来自定义这些映射."
在RAD Studio XE中,TDSHTTPService和TDSHTTPWebDispather组件都有四个特定事件,对应于上面列出的四种HTTP方法,并且用于映射前缀.XE2及更高版本中不存在这些方法.
我注意到一些非常奇怪的事情.我在表单关闭时保持表单的top,left,width和height属性,并使用此信息通过使用以前存储的信息调用SetBounds再次打开表单时恢复表单的最后位置.这很有效,但前提是表单的Position属性在设计时设置为poDefault.如果设置为其他内容,例如poDesigned,poScreenCenter或poMainFormCenter,则SetBounds不会恢复表单的先前位置和大小.
这是奇怪的部分.看似重要的是在设计时将Position属性设置为什么.我可以在运行时将此属性的值更改为poDefault,并且对SetBounds的调用仍然无法正常工作.我尝试过类似下面的内容
if Self.Position <> poDefault then
Self.Position := poDefault;
Run Code Online (Sandbox Code Playgroud)
在表单的OnCreate事件处理程序中,以及从重写的构造函数(并在构造函数中将Position设置为poDefault,并在OnCreate事件处理程序中调用SetBounds).在所有情况下,在运行时将表单的Position属性更改为poDefault并不能解决我在SetBounds中观察到的问题.我发现的唯一一致模式是SetBounds只有在设计时表单的Position属性为poDefault才能正常工作.
当表单的Position属性在设计时未设置为poDefault时,还有其他一些我注意到SetBounds的工作原理.例如,如果调用SetBounds,则在设计时将Position属性设置为poScreenCenter的表单不一定会显示在屏幕的中心.但是,它不会出现在由SetBounds定义的左上角位置,也不会出现在调用SetBounds时指定的宽度和高度.但是,让我重复一遍,我在调用SetBounds之前将表单的Position属性设置为poDefault.我甚至在两个操作之间调用了Application.ProcessMessages,但这并没有解决问题.
我已经在Windows 10上运行Delphi 10.1 Berlin进行了广泛的测试.我还在Windows 7上使用Delphi XE6对其进行了测试.结果相同.
如果您有疑问,请创建一个包含四种表单的VCL应用程序.在第一个表单上放置三个按钮,并为每个按钮添加如下OnClick:
with TForm2.Create(nil) do
try
ShowModal;
finally
Release;
end;
Run Code Online (Sandbox Code Playgroud)
构造函数创建TForm2,然后TForm3和TForm4.
在表单2到4的OnCreate上,添加以下代码:
if Self.Position <> poDefault then
Self.Position := poDefault;
Self.SetBounds(500,500,500,500);
Run Code Online (Sandbox Code Playgroud)
在form2上,将Position设置为poDefault,在form3上将Position设置为poScreenCenter,并在form4上将Position设置为默认值poDefaultPosOnly.只有form2将出现在500,500,宽度为500,高度为500.
有没有人对这个结果有合理的解释?
我已经看了很久了,最后决定把问题放在这里.我有一些我需要维护的应用程序是用Delphi 2007 for .NET(ASP.NET 2.0)编写的.通常,我第一次运行应用程序(使用IIS)时,我得到了经典的"无法在Web服务器上启动调试.无法附加到ASP.NET工作进程"消息.我只需按F9(运行)再次运行.有时我必须尝试运行几次才能实际运行.
我正在运行Windows 7 64位(并且在Vista 64位上看到了相同的效果).我确实为ASP.NET配置了IIS,并且我的Web.config文件中有以下代码.
<system.webServer>
<modules>
<add name="DbgConnect" type="Borland.DbkAsp.DbkConnModule,Borland.dbkasp,Version=10.5.0.0,
Culture=neutral, PublicKeyToken=b0524c541232aae7" preCondition="managedHandler" />
</modules>
<validation validateIntegratedModeConfiguration="false" />
</system.webServer>
Run Code Online (Sandbox Code Playgroud)
关键是我最终可以在调试器中运行应用程序,有时甚至是第一次尝试.很多时候,当我遇到故障时,它会在我按下Run后大约15秒左右发生,有时甚至在我点击一两页(或三个)Web应用程序之后.并且,是的,当Delphi进入这种模式时,我可以简单地运行而无需调试,一切都很好(除非我真的想调试).并且,我可以继续尝试在调试器中运行,最终它将正常工作.
似乎Delphi的.NET调试器在某种程度上得到了应用程序无法运行的想法,然后放弃并停止进程(正如我所提到的那样,有时候显然正在运行).
我知道其他开发者也看到了这种行为.我的问题是,有谁知道如何阻止这种烦人的行为?
我正在尝试在Delphi XE DataSnap应用程序中实现授权.我将其分解为一个非常简单的示例,但仍然没有看到TRoleAuth属性对方法或类的影响.
这是一个简单的DSServerMethods类,它包含生成的示例方法.该课程已经装饰了客人和任何授权角色,以及不受欢迎的拒绝角色.ReverseString方法已使用readonly denied角色进行修饰:
type
[TRoleAuth('guest,anyone','unwelcome')]
TMyDSServerMethods = class(TDSServerModule)
DataSetProvider1: TDataSetProvider;
...
public
{ Public declarations }
function EchoString(Value: string): string;
[TRoleAuth('','readonly')]
function ReverseString(Value: string): string;
...
end;
Run Code Online (Sandbox Code Playgroud)
我在OnUserAuthenticate方法上分配角色.例如,我有一个用户,我将从OnUserAuthenticate中分配readonly角色,我相信该角色应该拒绝用户执行ReverseString函数的权限.
根据我的理解,我的代码应该将用户的角色与TDSAuthenticationManager的OnUserAuthorize方法中的EventObject.AuthorizedRoles和EventObject.DeniedRoles TStrings进行比较,并相应地设置此方法的有效形式参数.
这是我用于测试的简单OnUserAuthorize方法.当我使用调试器进入它以响应具有尝试调用ReverseString的只读角色的用户时,EventObject.AuthorizedRoles和EventObject.DeniedRoles都是nil,并且EventObject.Roles包含只读角色.
procedure TServerContainer1.DSAuthenticationManager1UserAuthorize(
Sender: TObject; EventObject: TDSAuthorizeEventObject;
var valid: Boolean);
begin
outputdebugstring(PChar(Eventobject.UserName));
if EventObject.UserRoles <> nil then
outputdebugstring(PChar(eventobject.UserRoles.Text));
if EventObject.AuthorizedRoles <> nil then
outputdebugstring(PChar(eventobject.AuthorizedRoles.Text));
if EventObject.DeniedRoles <> nil then
outputdebugstring(PChar(eventobject.DeniedRoles.Text));
valid := True;
end;
Run Code Online (Sandbox Code Playgroud)
我是否遗漏了这一点,或者是否需要设置某个属性以使TRoleAuth属性起作用?
= = = = = = = = = =编辑:Mat DeLong提供了答案.DSAuth单元(声明TRoleAuth自定义属性类)在定义了DSServerModule后代的单元的接口部分中丢失.
我正在尝试为 TJSONObject 或 TJSONValue 编写调试器可视化工具。我的大部分可视化工具都运行良好。我遇到的问题是获取对 TJSONObject 的引用,或者至少是对 TJSONObject 的 tostring() 值的引用。
根据我看到的示例,以及 Jeremy North 在http://edn.embarcadero.com/article/40268上发表的精彩帖子,我应该从 IOTADebuggerVisualizerExternalViewer 实现的 Show 方法中获得我需要的内容。具体来说,来自 Expression、TypeName 和 EvalResult 字符串参数。
据我了解,Expression 是被检查(可视化)的变量的名称,TypeName 是变量的类名,EvalResult 是变量的默认字符串表示形式。
为了进行简单的测试,我在我的 TFrame 后代上放置了一个 TMemo。从 IOTADebuggerVisualizerExternalViewer.Show 方法中,我调用 TFrame 的 ShowJSONObject 方法,并向该方法传递 Expression、TypeName 和 EvalResult。相关代码出现在这里:
function TDebuggerJSONVisualizer.Show(const Expression, TypeName, EvalResult: string;
SuggestedLeft, SuggestedTop: Integer):
IOTADebuggerVisualizerExternalViewerUpdater;
var
AForm: TCustomForm;
AFrame: TJSONViewerFrame;
VisDockForm: INTACustomDockableForm;
begin
VisDockForm := TJSONVisualizerForm.Create(Expression) as INTACustomDockableForm;
AForm := (BorlandIDEServices as INTAServices).CreateDockableForm(VisDockForm);
AForm.Left := SuggestedLeft;
AForm.Top := SuggestedTop;
(VisDockForm as IFrameFormHelper).SetForm(AForm);
AFrame …Run Code Online (Sandbox Code Playgroud) 我已经为IIS 7.x配置了ISAPI DLL多年,但这是我第一次尝试使用Windows 10,但它无法正常工作,我找不到任何有关如何成功完成的说明.我在Windows 10 Professional中工作,并安装了IIS和支持技术.
这是我过去所做的.首先,我打开Internet Information Services Manager控制台.然后,我选择默认Web站点并打开Handler Mappings.我在"禁用"部分右键单击"ISAPI-dll",选择"编辑功能权限",然后在"执行"旁边选中复选标记.
由于我的ISAPI DLL是32位DLL,并且我运行的是Windows 10 64位专业版,因此我在"连接"窗格中选择"应用程序池",右键单击"DefaultAppPool",然后选择"高级设置",然后将"启用32位应用程序"设置为真正.
最后,我打开ISAPI和CGI限制小程序.然后,我右键单击ISAPI和CGI限制窗格并选择编辑功能设置,然后在"允许未指定的ISAPI模块"旁边放置复选标记.
Handler Mappings applet不再具有禁用的ISAPI-dll条目.但是,打开Handler Mappings小程序后,我可以选择编辑功能权限,并在Execute旁边放置一个复选标记.我已经能够在默认应用程序池中允许32位应用程序,但ISAPI和CGI限制小程序无处可寻.
最终的结果是,尽管我已经成功执行了如上所述的配置,但仍然无法运行我的ISAPI DLL.我已将DLL放在与Windows 7安装程序相同的位置(在c:\ inetpub\wwwroot\appfolder下),并使用相同的URL.它在Windows 7中运行,但在Windows 10中不运行.
如何在Windows 10中配置IIS以运行此ISAPI DLL?
我想创建一个TService后代类,用作我的 Windows 服务实现的基础。在我的基类中,我引入了一个已发布的ServiceDescription属性,并且我正在使用AfterInstall事件处理程序将此描述写入 Windows 注册表中的适当位置。
请注意,由于TServer类(在 中声明Vcl.SvcMgr)是TDataModule后代,为了允许ServiceDescription属性在对象检查器中可见,有必要在设计时包中声明此基类,并使用对 的调用在 Delphi 中注册它RegisterCustomModule。此外,此基类的后代必须由 OTA(开放工具 API)向导或某种代码生成器(.pas 和 .dfm 文件)生成。没问题,我已经整理好了,如果您有兴趣,可以从 Marco Cantu 的书 ( http://www.marcocantu.com/ddh/ddh15/ddh15e.htm ) 中阅读更多相关信息。
我遇到的问题是我想使用AfterInstall基类中的事件处理程序写入注册表,然后将AfterUninstall其删除,但我想确保我的后代类也将支持AfterInstall和AfterUninstall事件。
我之前从 Ray Konopka 那里了解到,如果你想重新引入一个属性,你必须在后代类中使用访问器方法。因此,这里是一个代码段,代表我针对AfterInstall事件执行此操作的尝试:
private
// field to store method pointer for the descendant AfterInstall event handler
FFAfterInstall: TServiceEvent;
…
protected
function GetAfterInstall: TServiceEvent;
procedure SetAfterInstall( value: TServiceEvent );
…
published …Run Code Online (Sandbox Code Playgroud) 我正在与客户进行现场工作,我正在努力帮助他们解决一个复杂的问题.我希望Delphi中有一个工具或功能,我们可以用它来查看内部工作,以帮助我们找到问题所在.
以下是我们正在处理的问题的高级概述.这是一个商业应用程序,目前部署在Delphi 5中.在过去的一年中,该应用程序已迁移到Delphi XE.迁移几乎完成,但遇到了一些严重的错误.
应用程序本身非常庞大,有数百个单元和许多第三方和自定义组件.在我们遇到的一个特定情况中,创建主窗体,然后在显示主窗体之前终止应用程序.结果是在终止期间发生崩溃,因为单元正在最终确定.
调试器正在破坏kernel32的RaiseException函数,该函数由NotifyNonDelphiException调用.我们尝试设置一个非破坏断点,从NotifyNonDelphiException中记录调用堆栈,但这并没有给我们任何有用的东西.调用堆栈仅包含处理异常的方法,即RtlRaiseStatus和KUserExceptionDispatcher.
我们如何识别抛出NotifyNonDelphiException正在处理的原始异常的代码?
编辑:这是在一个异常实例后捕获的两个图像.第一个是引发异常,第二个描述异常对话框关闭后的CPU窗口.


新编辑:
我发布这个问题已经有一个多星期了,各种答案给我留下了深刻的印象.对最初问题的一些评论是最有价值的,但是一些答案本身非常有用.
我对该客户的访问已经结束,我将要求他们考虑已在此处发布的答案.虽然我们无法追踪错误的实际来源,但错误的原因显而易见.多年来在没有严重重构的情况下对用户界面进行调整,使应用程序的登录过程不稳定.当用户取消登录时,主表单处于部分初始化状态.当不允许此过程运行时,这是用户中止登录时发生的情况,存在非常严重的终结问题.
该公司购买了AQTime Pro以帮助识别未来的问题,但需要重新设计登录过程,并且从长远来看将解决问题.
有一次,我考虑删除这个问题,但我选择保留它,因为我相信其他人会发现许多优秀的建议,这些建议已经发布了信息.
目前,我接受了@Deltics的答案,因为我讨厌在没有答案的情况下留下问题.但是,我要求这个问题的观众也考虑所有其他答案和评论,它们同样有价值.
delphi ×11
delphi-xe ×5
datasnap ×2
asp.net ×1
dbgrid ×1
debugging ×1
delphi-2007 ×1
delphi-2010 ×1
delphi-xe2 ×1
delphi-xe7 ×1
delphi.net ×1
iis-10 ×1
indy ×1
isapi ×1
json ×1
kernel32 ×1
macos ×1
oop ×1
opentools ×1
position ×1
rest ×1
setbounds ×1
tcp ×1
tdataset ×1
tform ×1
virtualbox ×1
windows-10 ×1
wizard ×1