简体   繁体   English

C#Process.Start和Process.StartInfo错误

[英]C# Process.Start and Process.StartInfo errors

I was trying to open an application (.exe) with a button click on a form using: 我试图使用以下命令在窗体上单击按钮以打开应用程序(.exe):

System.Diagnostics.Process.Start("C:\\Games\\GameDir\\Game.exe");

and the application executed and displayed the error message "can't find background.jpg, application will now quit." 并且应用程序执行并显示错误消息“找不到background.jpg,应用程序将立即退出”。

The .jpg in question was located outside the .exe in a folder called "data" (same directory, ie, C:/Games/GameDir/data). 所涉及的.jpg位于.exe外部的一个名为“数据”的文件夹中(相同目录,即C:/ Games / GameDir / data)。 So, I tried using: 因此,我尝试使用:

System.Diagnostics.ProcessStartInfo pInfo = new System.Diagnostics.ProcessStartInfo();
pInfo.WorkingDirectory = "C:\\Games\\GameDir\\";

//Also tried pInfo.WorkingDirectory = "C:\\Games\\GameDir"; without ending slashes
pInfo.FileName = "Game.exe";
pInfo.UseShellExecute = false;
System.Diagnostics.Process.Start(pInfo);

and the project wouldn't build, because "the system can't find the file specified" (error on Process.Start(pInfo)). 并且该项目无法生成,因为“系统找不到指定的文件” (Process.Start(pInfo)上的错误)。

I had to create a shortcut to the executable, and Start that: 我必须创建可执行文件的快捷方式,然后启动该快捷方式:

System.Diagnostics.Process.Start("C:\\Games\\GameDir\\Game.exe - Shortcut");

And that finally worked. 终于成功了。

My question is - why in the world pInfo.WorkingDirectory didn't work? 我的问题是-为什么世界上的pInfo.WorkingDirectory无法正常工作? What is so different about the shortcut's "Start in" property of "C:/Games/GameDir" than pInfo.WorkingDirectory = "C:/Games/GameDir"? 快捷方式的“ C:/ Games / GameDir”的“开始于”属性与pInfo.WorkingDirectory =“ C:/ Games / GameDir”有何不同? Are they not the same thing? 他们不是同一回事吗?

WorkingDirectory is only used when UseShellExecute = true . 仅当UseShellExecute = true时才使用WorkingDirectory。 Otherwise, the property is ignored all together and the Filename full path is used. 否则,将一起忽略该属性,并使用“文件名”完整路径。 From Microsoft's documentation : 从Microsoft的文档中

When UseShellExecute is false, the WorkingDirectory property is not used to find the executable. 如果UseShellExecute为false,则不使用WorkingDirectory属性查找可执行文件。 Instead, its value applies to the process that is started and only has meaning within the context of the new process. 相反,它的值适用于已启动的流程,并且仅在新流程的上下文中具有含义。

To get it working, just delete the working directory assignment and use the path in your filename. 要使其正常工作,只需删除工作目录分配并使用文件名中的路径即可。

System.Diagnostics.ProcessStartInfo pInfo = new System.Diagnostics.ProcessStartInfo();
pInfo.FileName = "C:\\Games\\GameDir\\Game.exe";
pInfo.UseShellExecute = false;
System.Diagnostics.Process.Start(pInfo);

Many programs suffer from the exact same bug your program died on. 许多程序都遭受与您的程序相同的错误。 They'll have a statement similar to this one in their code: 他们的代码中将有一条与此语句类似的语句:

  var backImage = Image.FromFile(@"data\background.jpg");

That's a relative path name. 那是相对路径名。 As opposed to a full path name, like @"c:\\games\\gamedir\\data\\background.jpg. When the operating system is forced to deal with a relative path name then it must use the default drive and the default directory to find a file. Environment.CurrentDirectory in a .NET program. 与完整路径名相反,例如@“ c:\\ games \\ gamedir \\ data \\ background.jpg。当操作系统被迫处理相对路径名时,它必须使用默认驱动器和默认目录来查找.NET程序中的文件Environment.CurrentDirectory。

So when you used "Game.exe", the operating system was forced to used your default directory to create a full path name. 所以,当你使用“的Game.exe”,操作系统被迫使用默认目录下创建一个全路径名。 To come up with something like "c:\\users\\margot\\documents\\visual studio 2013\\projects\\gamestarter\\bin\\debug\\game.exe". 提出类似“ c:\\ users \\ margot \\ documents \\ visual studio 2013 \\ projects \\ gamestarter \\ bin \\ debug \\ game.exe”的文件。 Kaboom, it isn't located there. Kaboom,它不在那儿。

The notion of the default working directory is very, very evil and has crashed many a program. 默认工作目录的概念非常邪恶,并且使许多程序崩溃。 It is the worst global variable you can imagine. 这是您可以想象的最差的全局变量。 And has all the problems associated with a global variable, it can change without you noticing and crash your app when you rely on it. 并且具有与全局变量相关的所有问题,它可以在不通知您的情况下发生更改,并且依赖于它会使您的应用程序崩溃。 Just calling a chunk of code that you didn't write can get it changed. 只需调用未编写的代码即可更改它。 The most notorious example in .NET is the OpenFileDialog class. .NET中最臭名昭著的示例是OpenFileDialog类。 Forgetting to set its RestoreDirectory property to true is a standard bug. 忘记将其RestoreDirectory属性设置为true是一个标准错误。

The notion of a default directory comes from the 1970s, back in the days when everybody started programs by typing their name in a command line interface shell program. 默认目录的概念来自1970年代,那时候每个人都通过在命令行界面外壳程序中键入其名称来启动程序。 Which made it very clear where the default directory was located. 这很清楚地显示了默认目录的位置。 You can still see this when you run Cmd.exe, you see the "DOS prompt". 您在运行Cmd.exe时仍然可以看到此消息,您会看到“ DOS提示符”。 But it is pretty evil in a GUI operating system, you can't see it anymore. 但是在GUI操作系统中这是非常邪恶的,您再也看不到它了。

There probably isn't anything you can do to get that game fixed. 要修复该游戏,可能您无能为力。 You found the proper workaround, setting ProcessStartInfo.WorkingDirectory is required to keep it happy. 您找到了适当的解决方法,需要设置ProcessStartInfo.WorkingDirectory才能保持满意。

In your own code, just keep the golden rule in mind: never use relative paths when you refer to files in your code. 在您自己的代码中,请谨记黄金法则:在代码中引用文件时, 切勿使用相对路径。 In your program, that should be a configuration setting since you cannot assume that the game will always be installed to c:\\games\\gamedir. 在您的程序中,这应该是一个配置设置,因为您不能假定游戏将始终安装到c:\\ games \\ gamedir。 Sooner or later, somebody is going to recognize that it belongs in c:\\program files :) 迟早,有人会认识到它属于c:\\ program文件:)

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

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