从另一个 C# 程序启动 C# 程序
Launching C# program from another C# program
由于我了解启动应用程序,我知道您可以通过多种方式在 C# .NET 中启动应用程序,但我 运行 遇到了尝试启动 SDL2 时出现的问题申请。
我尝试使用过程 class 进行以下操作:
- 启动构建的.exe文件。
- 使用“
cmd.exe /K
”或“cmd.exe /c
”启动应用程序,然后使用“exec
”或“call
”或“start
”通过“{path to file}
”或“{path to batch file to launch the application}
”。通过批处理文件和 CMD 启动应用程序工作正常。但是,每当我尝试启动该应用程序时(即使是在从 cmd.exe /? start cmd.exe ?params 启动的命令提示符的新实例中),它也不会产生任何结果。
我观察到的是应用程序尝试打开。启动到 Window 模式(启动 3D 环境)需要很长时间。超时后,它会在关闭之前渲染几帧空白 window 或在打开 window.
后立即关闭
所以我的问题是,有没有人成功地为用 C# .NET 编写的 SDL 应用程序制作了启动器应用程序?或者知道调试此行为的方法?因为不幸的是,该应用程序没有发出错误消息,并且由于 SDL 安全地关闭了该应用程序,我也无法观察到崩溃。
编辑#1
我没有对参数做任何花哨的事情,因为不应该有任何参数。我已经有另一个运行正常的 C# 应用程序,因为我的启动器需要打开 2 个程序。 1 个 SLD 应用程序,1 个 COM:VBA 控制应用程序。
鉴于:
string audioSpectrumProgram = "AudioSpectrum.exe";
string audioSpectrumBatchProgram = "AudioSpectrum.bat";
private void BtnLaunchPPTApp_OnClick()
{
//Powerpoint controlling application
pVBAApp = Process.Start(presenterProgram, $"\"{this.path}\" {this.audioFormatParams[0]} {((this.ckboxGenerate.Checked) ? "--create" : "")} lang={this.languageCodesParams[this.cboxLanguage.SelectedIndex]}");
}
方法一:
private void BtnLaunchSDLApp_OnClick()
{
pVizualizer = Process.Start(audioSpectrumProgram); //file launched from local path (is correct)
}
方法二:
pVizualizer = Process.Start(audioSpectrumBatchProgram); //file launched from local path (is correct)
方法三:
ProcessStartInfo info = new ProcessStartInfo("cmd.exe");
FileInfo spectrumFileInfo = new FileInfo(audioSpectrumProgram);
if (spectrumFileInfo.Exists)
info.Arguments = $"/c \"{spectrumFileInfo.FullName}\"";
pVizualizer = Process.Start(info);
方法四:
基于方法 3 的 senario。您不必使用 ProcessStartInfo 解析参数。
pVizualizer = Process.Start($"cmd.exe /K call \"{spectrumFileInfo.FullName}\"") //to observe what happens to the application
编辑#2
不受将 UseShellExecute 更改为 true
或 false
的影响
private void btnOpenVisualizer_Click(object sender, EventArgs e)
{
FileInfo spectrumFileInfo = new FileInfo(audioSpectrumProgram);
ProcessStartInfo info = new ProcessStartInfo(spectrumFileInfo.FullName);
info.UseShellExecute = true;
pVizualizer = new Process();
pVizualizer.StartInfo = info;
pVizualizer.EnableRaisingEvents = true;
pVizualizer.Exited += new EventHandler(myProcess_Exited);
pVizualizer.Start();
}
private void myProcess_Exited(object sender, System.EventArgs e)
{
Console.WriteLine(
$"Exit time : {pVizualizer.ExitTime}\n" +
$"Exit code : {pVizualizer.ExitCode}\n"
);
}
好的供将来参考:
文件的路径可能是正确的,一切都可能是有序的,但如果您使用 DLL 进行导入。更改进程的工作目录。
该项目将 运行,可以 "sometimes" 找到库,但可能会导致像这样的奇怪的未知错误。因此,运行使用 SDL 或任何其他类型的库连接另一个 C# 实例的最佳方式:
private void RunSDLProgram()
{
FileInfo spectrumFileInfo = new FileInfo("pathToFile.exe");
ProcessStartInfo info = new ProcessStartInfo(spectrumFileInfo.FullName);
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
info.UseShellExecute = false;
info.WorkingDirectory = spectrumFileInfo.DirectoryName;
pVizualizer = new Process();
pVizualizer.StartInfo = info;
pVizualizer.EnableRaisingEvents = true;
pVizualizer.Exited += new EventHandler(myProcess_Exited);
pVizualizer.Start();
}
private void myProcess_Exited(object sender, System.EventArgs e)
{
Console.WriteLine(
$"Exit time : {pVizualizer.ExitTime}\n" +
$"Exit code : {pVizualizer.ExitCode}\n" +
$"output : {pVizualizer.StandardOutput}\n" +
$"err : {pVizualizer.StandardError}\n"
);
}
运行 一个批处理文件会查看它自己的目录并将所有引用都放在本地,但它不会改变工作目录。 (我已经怀疑更改工作目录,但我没有看到在 process.start("cmd.exe");
中调用 2 个操作的方法)
分析启动问题的一般方法是使用SysInternals Process Monitor。
记录未正常启动的应用程序。为您的应用程序使用过滤器。然后遍历结果列中没有 SUCCESS
的所有项目。通常您希望自下而上执行此操作,因为最后一个错误会阻止您的应用程序加载。
这样您会发现常见的启动问题,例如:
- 缺少 DLL 或其他依赖项
- 旧 DLL 或从错误位置加载的 DLL(例如已注册的 COM 组件)
- 错误的工作目录,例如访问不存在的配置文件
由于我了解启动应用程序,我知道您可以通过多种方式在 C# .NET 中启动应用程序,但我 运行 遇到了尝试启动 SDL2 时出现的问题申请。
我尝试使用过程 class 进行以下操作:
- 启动构建的.exe文件。
- 使用“
cmd.exe /K
”或“cmd.exe /c
”启动应用程序,然后使用“exec
”或“call
”或“start
”通过“{path to file}
”或“{path to batch file to launch the application}
”。通过批处理文件和 CMD 启动应用程序工作正常。但是,每当我尝试启动该应用程序时(即使是在从 cmd.exe /? start cmd.exe ?params 启动的命令提示符的新实例中),它也不会产生任何结果。
我观察到的是应用程序尝试打开。启动到 Window 模式(启动 3D 环境)需要很长时间。超时后,它会在关闭之前渲染几帧空白 window 或在打开 window.
后立即关闭所以我的问题是,有没有人成功地为用 C# .NET 编写的 SDL 应用程序制作了启动器应用程序?或者知道调试此行为的方法?因为不幸的是,该应用程序没有发出错误消息,并且由于 SDL 安全地关闭了该应用程序,我也无法观察到崩溃。
编辑#1
我没有对参数做任何花哨的事情,因为不应该有任何参数。我已经有另一个运行正常的 C# 应用程序,因为我的启动器需要打开 2 个程序。 1 个 SLD 应用程序,1 个 COM:VBA 控制应用程序。 鉴于:
string audioSpectrumProgram = "AudioSpectrum.exe";
string audioSpectrumBatchProgram = "AudioSpectrum.bat";
private void BtnLaunchPPTApp_OnClick()
{
//Powerpoint controlling application
pVBAApp = Process.Start(presenterProgram, $"\"{this.path}\" {this.audioFormatParams[0]} {((this.ckboxGenerate.Checked) ? "--create" : "")} lang={this.languageCodesParams[this.cboxLanguage.SelectedIndex]}");
}
方法一:
private void BtnLaunchSDLApp_OnClick()
{
pVizualizer = Process.Start(audioSpectrumProgram); //file launched from local path (is correct)
}
方法二:
pVizualizer = Process.Start(audioSpectrumBatchProgram); //file launched from local path (is correct)
方法三:
ProcessStartInfo info = new ProcessStartInfo("cmd.exe");
FileInfo spectrumFileInfo = new FileInfo(audioSpectrumProgram);
if (spectrumFileInfo.Exists)
info.Arguments = $"/c \"{spectrumFileInfo.FullName}\"";
pVizualizer = Process.Start(info);
方法四: 基于方法 3 的 senario。您不必使用 ProcessStartInfo 解析参数。
pVizualizer = Process.Start($"cmd.exe /K call \"{spectrumFileInfo.FullName}\"") //to observe what happens to the application
编辑#2
不受将 UseShellExecute 更改为 true
或 false
private void btnOpenVisualizer_Click(object sender, EventArgs e)
{
FileInfo spectrumFileInfo = new FileInfo(audioSpectrumProgram);
ProcessStartInfo info = new ProcessStartInfo(spectrumFileInfo.FullName);
info.UseShellExecute = true;
pVizualizer = new Process();
pVizualizer.StartInfo = info;
pVizualizer.EnableRaisingEvents = true;
pVizualizer.Exited += new EventHandler(myProcess_Exited);
pVizualizer.Start();
}
private void myProcess_Exited(object sender, System.EventArgs e)
{
Console.WriteLine(
$"Exit time : {pVizualizer.ExitTime}\n" +
$"Exit code : {pVizualizer.ExitCode}\n"
);
}
好的供将来参考: 文件的路径可能是正确的,一切都可能是有序的,但如果您使用 DLL 进行导入。更改进程的工作目录。
该项目将 运行,可以 "sometimes" 找到库,但可能会导致像这样的奇怪的未知错误。因此,运行使用 SDL 或任何其他类型的库连接另一个 C# 实例的最佳方式:
private void RunSDLProgram()
{
FileInfo spectrumFileInfo = new FileInfo("pathToFile.exe");
ProcessStartInfo info = new ProcessStartInfo(spectrumFileInfo.FullName);
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
info.UseShellExecute = false;
info.WorkingDirectory = spectrumFileInfo.DirectoryName;
pVizualizer = new Process();
pVizualizer.StartInfo = info;
pVizualizer.EnableRaisingEvents = true;
pVizualizer.Exited += new EventHandler(myProcess_Exited);
pVizualizer.Start();
}
private void myProcess_Exited(object sender, System.EventArgs e)
{
Console.WriteLine(
$"Exit time : {pVizualizer.ExitTime}\n" +
$"Exit code : {pVizualizer.ExitCode}\n" +
$"output : {pVizualizer.StandardOutput}\n" +
$"err : {pVizualizer.StandardError}\n"
);
}
运行 一个批处理文件会查看它自己的目录并将所有引用都放在本地,但它不会改变工作目录。 (我已经怀疑更改工作目录,但我没有看到在 process.start("cmd.exe");
中调用 2 个操作的方法)
分析启动问题的一般方法是使用SysInternals Process Monitor。
记录未正常启动的应用程序。为您的应用程序使用过滤器。然后遍历结果列中没有 SUCCESS
的所有项目。通常您希望自下而上执行此操作,因为最后一个错误会阻止您的应用程序加载。
这样您会发现常见的启动问题,例如:
- 缺少 DLL 或其他依赖项
- 旧 DLL 或从错误位置加载的 DLL(例如已注册的 COM 组件)
- 错误的工作目录,例如访问不存在的配置文件