.NET Core 2.0中的Process.Start抛出“指定的可执行文件不是此OS平台的有效应用程序”异常

109
我需要让一个.reg文件和一个.msi文件在用户的Windows上自动执行,使用与这两种文件类型相关联的任何可执行文件。 .NET Core 2.0 Process.Start(string fileName)文档说: “文件名不需要代表一个可执行文件。它可以是任何已经与系统上安装的应用程序关联的文件类型。”
然而,
using(var proc = Process.Start(@"C:\Users\user2\Desktop\XXXX.reg")) { } //.msi also

给我

System.ComponentModel.Win32Exception (0x80004005): The specified executable is not a valid application for this OS platform.
   at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
   at System.Diagnostics.Process.Start()
   at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
   at System.Diagnostics.Process.Start(String fileName)

使用错误代码和HResult为-2147467259,以及本机错误代码193。

相同的代码在.NET Framework 3.5或4控制台应用程序中工作。

我无法指定确切的exe文件路径作为方法的参数,因为用户的环境是不同的(包括Windows版本),并且超出了我的控制范围。这也是为什么我需要将程序移植到.NET Core,尝试将其作为SCD控制台应用程序运行,以便不需要安装特定的.NET Framework或.NET Core版本。

异常在Visual Studio调试运行和发布为win-x86 SCD时都会抛出。我的PC是Win7 64位,我确定.reg和.msi与常规程序一样关联。

是否有解决方案?感谢任何帮助。

6个回答

202

你也可以将ProcessStartInfoUseShellExecute属性设置为true。

var p = new Process();
p.StartInfo = new ProcessStartInfo(@"C:\Users\user2\Desktop\XXXX.reg")
{ 
    UseShellExecute = true 
};
p.Start();

此处记录,.Net Core 似乎有所变化。

另请参阅破坏性变更


3
将UseShellExecute从false更改为true对我有用 :-) - Greg Trevellick
2
请查看Microsoft的“破坏性更改文档”,链接在此处:https://learn.microsoft.com/en-us/dotnet/core/compatibility/fx-core - Steve
我曾经因为调用本地HTML文件的Process.Start()方法无法正常工作而苦恼不已,尽管其他人都声称它可以。这个解决方案解决了这个问题。 - Vincent La
这对我有用,但为什么它能与“Open width”一起工作? “旧的方式”System.Diagnostics.Process.Start("rundll32.exe", "shell32.dll, OpenAs_RunDLL " + item.FileName); - Wolfgang Schorge

54

您可以将UseShellExecute设置为true,并在ProcessStartInfo对象中包括此路径:

Process.Start(new ProcessStartInfo(@"C:\Users\user2\Desktop\XXXX.reg") { UseShellExecute = true });

1
将一个应用程序从net48转换为netcoreapp3.1,需要在dotnetcore(运行在Windows上)上使用“UseShellExecute = true”。 - huzle
我使用了.msg文件但无法打开。我收到了以下错误信息:“System.ComponentModel.Win32Exception: '系统找不到指定的文件。'” - Kumar Shanmugam

25

如果这也让你感到困扰:

对于我们这些习惯于只需调用 Process.Start(fileName); 的人来说,上面的语法可能会让我们感到焦虑... 那么我可以补充一下,你可以把它写成一行代码。

new Process { StartInfo = new ProcessStartInfo(fileName) { UseShellExecute = true } }.Start();

3
这应该是被接受的答案,非常好用。 - dgxhubbard
我同意@dgxhubbard的观点,因为这个答案可以抑制命令窗口,而被接受的答案则不能(当应用程序打开时,命令窗口会显示)。 - J Weezy

20

你需要执行 cmd.exe

var proc = Process.Start(@"cmd.exe ",@"/c C:\Users\user2\Desktop\XXXX.reg")

别忘了 /c


4
这种方法虽然可行,但是会一直保留命令提示符窗口,直到打开的应用程序关闭。例如,如果我想打开一个文档文件,命令提示符窗口会一直保持打开状态,直到我关闭 Word。更好的方法是使用 UseShellExecute 来避免这个问题。 - Álvaro García
3
这不应该被认为是正确答案。使用ProcessStartInfo和UseShellExecute = true更好。 - Paul Williams

-1
            string itemseleccionado = lbdatos.SelectedItem.ToString();
            var p = new Process();
            p.StartInfo = new ProcessStartInfo(itemseleccionado)
            {
                UseShellExecute = true
            };
            p.Start();

3
请记住,Stack Overflow不仅旨在解决即时问题,还旨在帮助未来的读者找到类似问题的解决方案,这需要理解底层代码。这对于我们社区中的初学者尤为重要,他们可能不熟悉语法。因此,请问,您能否修改您的答案,包括解释您正在做什么以及为什么您认为这是最好的方法? - Jeremy Caney
变量 (Variables) - Antonio Rodríguez

-1

使用此代码打开文件

new ProcessStartInfo(@"C:\Temp\1.txt").StartProcess();

需要这个扩展方法

public static class UT
{
    public static Process StartProcess(this ProcessStartInfo psi, bool useShellExecute = true)
    {
        psi.UseShellExecute = useShellExecute;
        return Process.Start(psi);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接