C# 从delphi执行Win表单可执行文件。启动后任务不工作
我正试图从Codegear Delphi 2007中编写的代码启动一个可执行文件。我已经成功地做到了这一点,但一旦启动可执行文件(winforms应用程序),它就不会启动它所编程的C# 从delphi执行Win表单可执行文件。启动后任务不工作,c#,delphi,winapi,C#,Delphi,Winapi,我正试图从Codegear Delphi 2007中编写的代码启动一个可执行文件。我已经成功地做到了这一点,但一旦启动可执行文件(winforms应用程序),它就不会启动它所编程的任务 以下是我用于从Delphi启动流程的代码: procedure TfrmMain.OpenDatabase1Click(Sender: TObject); var filename: string; var parameters: string; var sei: TShellExecuteInfo;
任务
以下是我用于从Delphi启动流程的代码:
procedure TfrmMain.OpenDatabase1Click(Sender: TObject);
var filename: string;
var parameters: string;
var
sei: TShellExecuteInfo;
ExitCode: DWORD;
begin
if (OpenDatabaseDialog.Execute)then begin
//Connect to mysql, check for new data and insert data into sdb file before opening.
filename := 'C:\mysqlhelper\SSOAP Mysql Helper.exe';
parameters := '"' + OpenDatabaseDialog.FileName + '"';
ZeroMemory(@sei, SizeOf(sei));
sei.cbSize := SizeOf(TShellExecuteInfo);
sei.fMask := SEE_MASK_FLAG_DDEWAIT or SEE_MASK_FLAG_NO_UI or SEE_MASK_NOCLOSEPROCESS;
sei.lpVerb := PChar('runas');
sei.lpFile := PChar(filename); // PAnsiChar;
if parameters <> '' then
sei.lpParameters := PChar(parameters); // PAnsiChar;
sei.nShow := SW_SHOWNORMAL; //Integer;
if ShellExecuteEx(@sei) then begin
repeat
Application.ProcessMessages;
GetExitCodeProcess(sei.hProcess, ExitCode) ;
until (ExitCode <> STILL_ACTIVE) or Application.Terminated;
end;
OpenDatabase(OpenDatabaseDialog.Filename);
end;
end;
procedure TfrmMain.OpenDatabase1Click(发送方:TObject);
var文件名:字符串;
var参数:字符串;
变量
sei:TShellExecuteInfo;
出口代码:DWORD;
开始
如果是(OpenDatabaseDialog.Execute),则开始
//连接到mysql,检查新数据并在打开之前将数据插入sdb文件。
文件名:=“C:\mysqlhelper\SSOAP Mysql Helper.exe”;
参数:='“'+OpenDatabaseDialog.FileName+'”;
零内存(@sei,SizeOf(sei));
sei.cbSize:=SizeOf(TShellExecuteInfo);
sei.fMask:=查看屏蔽标志等待或查看屏蔽标志否UI或查看屏蔽标志否关闭流程;
sei.lpVerb:=PChar('runas');
sei.lpFile:=PChar(文件名);//潘斯卡尔;
如果参数为“”,则
sei.lpParameters:=PChar(参数);//潘斯卡尔;
sei.nShow:=SW_SHOWNORMAL//整数;
如果ShellExecuteEx(@sei),则开始
重复
Application.ProcessMessages;
GetExitCode进程(sei.hProcess,ExitCode);
直到(退出代码仍处于活动状态)或应用程序终止;
结束;
OpenDatabase(OpenDatabaseDialog.Filename);
结束;
结束;
以下是C#中的代码,它作为一个独立程序运行良好:
public Form1()
{
InitializeComponent();
//get command line arguments (should be ssoap database filename
string[] args = Environment.GetCommandLineArgs();
//open connections
OpenMySQLConnection();
OpenAccessConnection(args[1]);
//init the lists for FM's and RG's
flowMeters = new List<FlowMeter>();
rainGauges = new List<RainGauge>();
Task t = new Task(new Action(DoWork));
t.Start();
}
public Form1()
{
初始化组件();
//获取命令行参数(应为ssoap数据库文件名
字符串[]args=Environment.GetCommandLineArgs();
//开放连接
OpenMySQLConnection();
OpenAccessConnection(args[1]);
//初始化FM和RG的列表
流量计=新列表();
雨量计=新列表();
任务t=新任务(新操作(DoWork));
t、 Start();
}
我对它进行了调试,只觉得任务没有启动。我将MessageBox.Show()
贯穿其中,它构成了t.Start();
任务的一部分
为了澄清,我的问题是,为什么我可以启动可执行文件,给它它期望的参数,而它却不启动任务?从Delphi程序启动进程和作为独立应用程序启动进程之间最明显的区别是工作目录的状态
在Delphi代码中,您没有指定工作目录。因此,新进程继承其父进程的工作目录,即您的Delphi程序。您没有说明Delphi程序的工作目录是什么,因此我们无法确定
在Delphi程序之外启动C#程序时,工作目录将由启动C#程序的方式决定。您没有说明如何启动C#程序,因此我们无法再次说明工作目录是什么
我建议您向C#程序添加一些诊断代码,以显示工作目录是什么。如果运行程序的两种方式不同,请在调用ShellExecuteEx
时指定工作目录
如果这证明了工作目录是问题所在,那么您需要弄清楚为什么程序依赖于工作目录。这是故意的吗?如果是,那么您需要注意指定它。更有可能的是,程序不应该依赖于工作目录
差异的另一个可能原因是传递给程序的参数。再次使用诊断输出检查程序在两种启动模式下是否确实接收到相同的参数
最后,我注意到您使用了Delphi代码中的runas
动词。也许这就是问题所在。也许您不应该提升
两个旁白:
您在Delphi程序中的忙循环是浪费。您应该等待进程句柄,而不是运行忙循环。您可能希望为此运行一个单独的线程以保持UI活动
您泄漏了进程句柄
是什么让你认为任务
没有执行?向我们展示DoWork
方法在调用执行任务之前放置一个MessageBox.Show(“Blah”)
。放置与DoWork()的第一行相同的内容
方法不起作用。该方法太大,无法在此处发布,我认为这与此无关。我不太喜欢您在Delphi程序中的繁忙循环,但这是您的问题。同样,您泄漏的进程句柄。我想知道在独立运行C#应用程序时如何启动它。我相信您会使用“以管理员身份运行"与您从Delphi程序启动它的方式相匹配。我对Delphi非常陌生,这是我能够找到的唯一等待另一个程序执行完成的方法。我完全愿意接受更好实践的建议。是的,我以管理员身份和正常运行两者。结果相同。您为什么使用runas
然后呢?你搞定了,伙计。在读了几行你的答案后,它就是工作目录。我在C应用程序中使用了一个相对路径来指向我正在解析的文本文件。file.ReadAllLines(“C:\\mysqlhelper\\mapping.txt”)
暂时修复了它,尽管它们最终都将驻留在同一个目录中。啊,这总是很愚蠢。但是,你的“旁白”。我对Delphi非常陌生。你能建议如何重写它或提供一个链接吗?对于第1项,你可以创建一个线程,并使用WaitForSingleObject
传递进程句柄和INFINITE
超时。然后让线程在完成后向主线程发出信号。或者使用WaitForSingleObject
通过短时间超时并调用处理消息
,所有消息都在一个循环中.Ugh!或使用MsgWaitForMultipleObjects