简体   繁体   English

从另一个C#程序启动C#程序

[英]Launching C# program from another C# program

Due to me having knowledge of launching apps I am aware that you have multiple ways of launching an application in C# .NET, but I'm running into a issue that occurs when attempting to launch a SDL2 application. 由于我具有启动应用程序的知识,因此我知道您可以通过多种方式在C#.NET中启动应用程序,但是在尝试启动SDL2应用程序时遇到了一个问题。

I have attempted the following using the Process class to: 我尝试使用Process类进行以下操作:

  • Start the .exe file of the build. 启动生成的.exe文件。
  • Start the application using " cmd.exe /K " or " cmd.exe /c " followed by " exec " or " call " or " start " followed by " {path to file} " or " {path to batch file to launch the application} ". 使用“ cmd.exe /K ”或“ cmd.exe /c ”启动应用程序,然后使用“ exec ”或“ call ”或“ start ”,然后使用“ {path to file} ”或“ {path to batch file to launch the application} Launching the application via a batch file and CMD works fine. 通过批处理文件和CMD启动应用程序可以正常工作。 But, whenever I attempt to even launch the application (even in a new instance of Command-Prompt launched from cmd.exe /? start cmd.exe ?params) it will yield no result. 但是,每当我尝试启动应用程序时(即使在从cmd.exe /?启动cmd.exe?params启动的命令提示符的新实例中),也都不会产生任何结果。

What I can observe is that the application tries to open. 我可以观察到的是该应用程序尝试打开。 It takes forever to launch into the Window mode (starting the 3D environment). 永远需要进入Window模式(启动3D环境)。 After a timeout it will either, render a couple of frames of a blank window before closing or close immediately after opening the window. 超时后,它将在关闭前渲染空白窗口的几帧,或者在打开窗口后立即关闭。

So my question is, does anyone have succesfully made a launcher application for a SDL app written in C# .NET? 所以我的问题是,是否有人成功为用C#.NET编写的SDL应用程序创建了启动器应用程序? Or knows a way to debug this behaviour? 还是知道一种调试此行为的方法? Because unfortunately, the app does not send out a error message and since SDL safely closes the application I can't observe a crash either. 不幸的是,由于该应用程序不会发出错误消息,并且由于SDL安全地关闭了该应用程序,所以我也无法观察到崩溃。

Edit #1 编辑#1

I'm not doing anything fancy with parameters as there shouldn't be any. 我对参数没有任何幻想,因为应该没有任何参数。 I already have another one functioning that launches a normal C# application as my launcher requires to open 2 programs. 我已经有另一个功能可以启动普通的C#应用​​程序,因为启动器需要打开2个程序。 1 SLD application, 1 COM:VBA controlling application. 1个SLD应用程序,1个COM:VBA控制应用程序。 Given: 鉴于:

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]}");
}

Method 1: 方法1:

private void BtnLaunchSDLApp_OnClick()
{
    pVizualizer = Process.Start(audioSpectrumProgram); //file launched from local path (is correct)
}

Method 2: 方法2:

pVizualizer = Process.Start(audioSpectrumBatchProgram); //file launched from local path (is correct)

Method 3: 方法3:

ProcessStartInfo info = new ProcessStartInfo("cmd.exe");
FileInfo spectrumFileInfo = new FileInfo(audioSpectrumProgram);
if (spectrumFileInfo.Exists)
   info.Arguments = $"/c \"{spectrumFileInfo.FullName}\"";
pVizualizer = Process.Start(info);

Method 4: based on senario of method 3. You don't have to parse arguments using ProcessStartInfo. 方法4:基于方法3的方法。您不必使用ProcessStartInfo解析参数。

pVizualizer = Process.Start($"cmd.exe /K call \"{spectrumFileInfo.FullName}\"") //to observe what happens to the application

Edit #2 编辑#2

Not affected by changing the UseShellExecute to true or false 不受UseShellExecute更改为truefalse

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"
            );
    }

A general way of analyzing startup issues is to use SysInternals Process Monitor . 分析启动问题的一般方法是使用SysInternals Process Monitor

Record the application that is not starting up properly. 记录未正确启动的应用程序。 Use a filter for your application. 为您的应用程序使用过滤器。 Then go through all items which don't have SUCCESS in the result column. 然后在结果栏中浏览所有没有SUCCESS项目。 Typically you want to do that bottom-up, since the last error is the one stopping your application from loading. 通常,您要自下而上进行操作,因为最后一个错误是阻止您的应用程序加载的错误。

Like this you'll find common startup issues like: 这样,您会发现常见的启动问题,例如:

  • missing DLLs or other dependencies 缺少DLL或其他依赖项
  • old DLLs or DLLs loaded from wrong location (eg registered COM components) 旧的DLL或从错误位置加载的DLL(例如注册的COM组件)
  • wrong working directory, eg access to non-existent config files 工作目录错误,例如访问不存在的配置文件

Ok For Future reference: Pathing to the files can be correct and everything might be in order but if you are using DLLs for imports. 好的,供将来参考:到文件的路径可能是正确的,并且所有操作都可以进行,但是如果您使用DLL进行导入。 Change the process's working directory. 更改进程的工作目录。

The project will run, libs can "sometimes" be found but can cause a weird unknown bug like this one. 该项目将运行,可以“有时”找到库,但可能导致类似这样的奇怪的未知错误。 So the most optimal way of running another C# instance with SDL or any other kind of library: 因此,使用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" 
            );
    }

Running a batch file will look at it's own directory and makes all references local, but it won't alter the working directory. 运行批处理文件将查看它自己的目录,并使所有引用都成为本地文件,但不会更改工作目录。 (already had my suspicions about changing the work directory but I didn't see a way to call 2 opperations in process.start("cmd.exe"); ) (我已经怀疑要更改工作目录,但是我没有看到在process.start("cmd.exe");调用2个操作的方法process.start("cmd.exe");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM