Exception when using System.Diagnostics.Process.Start to open an EML file - c#

If you save an email to a file on disk with an EML extension, you can open it in Outlook on Windows just by double-clicking the file. I'm hoping to do something similar as my application can encounter EML files that it needs to open.
I have some crude test code that has:
using System;
using System.Diagnostics;
using System.IO;
and then:
System.Diagnostics.Process.Start(#"C:\temp\test.eml");
When I run the code I get the following exception:
System.ComponentModel.Win32Exception: 'An error occurred trying to
start process 'C:\temp\test.eml' with working directory
'C:\Users\me\source\repos\TestProj\TestProj\bin\Release\net6.0-windows'.
The specified executable is not a valid application for this OS
platform.'
I have tried placing a simple text file in the same folder and named it 'test.txt' and checked that it opens in Notepad when I double-click it, but if I try to open it with:
System.Diagnostics.Process.Start(#"C:\temp\test.txt");
I get the same error. Where am I going wrong?

There was a breaking change in .NET Core compared to .NET Framework:
Change in default value of UseShellExecute
ProcessStartInfo.UseShellExecute has a default value of false on .NET Core. On .NET Framework, its default value is true.
Change description
Process.Start lets you launch an application directly, for example, with code such as Process.Start("mspaint.exe") that launches Paint. It also lets you indirectly launch an associated application if ProcessStartInfo.UseShellExecute is set to true. On .NET Framework, the default value for ProcessStartInfo.UseShellExecute is true, meaning that code such as Process.Start("mytextfile.txt") would launch Notepad, if you've associated .txt files with that editor. To prevent indirectly launching an app on .NET Framework, you must explicitly set ProcessStartInfo.UseShellExecute to false. On .NET Core, the default value for ProcessStartInfo.UseShellExecute is false. This means that, by default, associated applications are not launched when you call Process.Start.
Use Process.Start overload accepting ProcessStartInfo and set UseShellExecute to true:
var processStartInfo = new ProcessStartInfo
{
FileName = #"C:\temp\test.eml",
UseShellExecute = true
};
Process.Start(processStartInfo);
Otherwise provide path to executable and pass path to file as a parameter:
var pathToOutlook = #"C:\Program Files\Microsoft Office\root\Office16\OUTLOOK.EXE";
Process.Start(pathToOutlook, #"D:\Downloads\sample.eml");

Related

Process.Start can not open a file based on the extension

If I write into the command prompt
c:\Data\a.xls
c:\Data\b.pdf
c:\Data\c.txt
then the corresponding files are opened with the default application. I could do the same from program.
Process.Start(#"c:\Data\a.xls");
Process.Start(#"c:\Data\b.pdf");
Process.Start(#"c:\Data\c.txt");
Unfortunately, this does not work anymore. I use windows 10 and .net7.
Process.Start("notepad.exe", #"c:\Data\c.txt"); // works
Process.Start("excel.exe", #"c:\Data\a.xls"); // does not work
If I provide the full path of excel.exe then it works. I would like to achieve the old functionality just to provide the filename and open it with the default application.
Set the UseShellExecute property to true.
The default is true on .NET Framework apps and false on .NET Core apps.
Also see StartInfo.
Download/install NuGet package: System.Diagnostics.Process
ProcessStartInfo startInfo = new ProcessStartInfo() { FileName= #"c:\Data\a.xls", UseShellExecute = true };
Process.Start(startInfo);
Additional References:
ProcessStartInfo (source code)
ProcessStartInfo.Verbs
ProcessStartInfo.Verb
Get List of available Verbs (file association) to use with ProcessStartInfo in c#

Running a .net core app with EFCore from System.Diagnostics.Process fails when not using shell execute

I have a .net core executable build in .net 7. this app uses entity framework core 7 underneath.
this executable runs fine from a cmd line prompt.
I have a second windows forms administration GUI project that I'd like to use to run the first executable, and capture the output of the stdout/stderr.
to do this, I create a ProcessStartInfo structure, and set UseShellExecute to false, and override the appropriate OutputDataRecieved, ErrorDataReeceived eventhandlers.
when I start the first process without shell execute, I get a System.Configuration.Management dll 5.0.0.0 can not be found exception coming out of EFCore. The problem goes away if I set UseShellExecute to true, but in this way I can't capture the output.
Would anyone know what the difference in GAC/Assembly lookup between using shell execute and without? And how I can get same behavior across the two?
I've down a workaround by launching cmd.exe instead.
in the arguments I use the /C .
this allows me to have exact environment as starting the executable from cmdline, while still being able to turn off shell execute on the ProcessStartInfo parameters, thus allowing the capture of stdout/stderr.

Why does C# Process.Start not find the executable on my path?

I have this folder on my windows Path environment variable: C:\bin
I have a tool named 7z inside C:\bin\7z\7z.exe.
If I open any shell, like Powershell I can run the command "7z" and it works fine, the executable is found and it runs (And where.exe 7z prints out C:\bin\7z\7z.exe). The fact that the executable is inside a folder named after itself doesn't get in the way of the executable being found. The folder and the executable inside the folder seem to have to be named exactly as the program I am trying to run.
However, when running code in C# to run the executable, it is not found.
ProcessStartInfo startInfo = new ProcessStartInfo() {
UseShellExecute = false,
CreateNoWindow = true,
FileName = "7z",
Arguments = $"-h",
};
var p = Process.Start(startInfo); // Throws
I know that Process.Start supports Path environment variables here as I can successfully run this code for other executables that are not in inner folders.
My questions are:
Why isn't Process.Start able to find the executable?
Is having a directory named after the executable a supported and documented way to find executables with a Path directory? Where can I read this documentation?
If you set ProcessStartInfo.UseShellExecute to false, you must supply the full path to your executable. In this case Process.Start will call the CreateProcess function. From the documentation:
The string can specify the full path and file name of the module to execute or it can specify a partial name. In the case of a partial name, the function uses the current drive and current directory to complete the specification. The function will not use the search path. This parameter must include the file name extension; no default extension is assumed.
If you use ShellExecute true, the shell's best guest for 7z will be the directory, as you dont supply the .exe extension.

.Net Core 2.0 Process.Start throws "The specified executable is not a valid application for this OS platform"

I need to let a .reg file and a .msi file execute automatically using whatever executables these two file types associated with on user's Windows.
.NET Core 2.0 Process.Start(string fileName) docs says:
"the file name does not need to represent an executable file. It can be of any file type for which the extension has been associated with an application installed on the system."
However
using(var proc = Process.Start(#"C:\Users\user2\Desktop\XXXX.reg")) { } //.msi also
gives me
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)
with ErrorCode and HResult -2147467259, and NativeErrorCode 193.
The same code did work in .Net Framework 3.5 or 4 console app.
I can't specify exact exe file paths as the method's parameter since users' environments are variant (including Windows versions) and out of my control. That's also why I need to port the program to .Net Core, trying to make it work as SCD console app so that installation of specific .Net Framework or .NET Core version is not required.
The exception is thrown both in Visual Studio debugging run and when published as win-x86 SCD. My PC is Win7 64bit and I'm sure .reg and .msi are associated with regular programs as usual Windows PC does.
Is there solution for this? Any help is appreciated.
You can also set the UseShellExecute property of ProcessStartInfo to true
var p = new Process();
p.StartInfo = new ProcessStartInfo(#"C:\Users\user2\Desktop\XXXX.reg")
{
UseShellExecute = true
};
p.Start();
Seems to be a change in .net Core, as documented here.
See also breaking changes.
You can set UseShellExecute to true and include this and your path in a ProcessStartInfo object:
Process.Start(new ProcessStartInfo(#"C:\Users\user2\Desktop\XXXX.reg") { UseShellExecute = true });
In case this bothers you as well:
For those of us that are used to simply calling Process.Start(fileName); the above syntax may give us anxiety... So may I add that you can write it in a single line of code?
new Process { StartInfo = new ProcessStartInfo(fileName) { UseShellExecute = true } }.Start();
You have to execute cmd.exe
var proc = Process.Start(#"cmd.exe ",#"/c C:\Users\user2\Desktop\XXXX.reg")
don't forget the /c
use this to open a file
new ProcessStartInfo(#"C:\Temp\1.txt").StartProcess();
need this extension method
public static class UT
{
public static Process StartProcess(this ProcessStartInfo psi, bool useShellExecute = true)
{
psi.UseShellExecute = useShellExecute;
return Process.Start(psi);
}
}
string itemseleccionado = lbdatos.SelectedItem.ToString();
var p = new Process();
p.StartInfo = new ProcessStartInfo(itemseleccionado)
{
UseShellExecute = true
};
p.Start();

Trying to run slui.exe from within a method using ProcessStartInfo and Process

I'm having an issue with running slui.exe from a method in c#. I'm using the code:
ProcessStartInfo startInfo = new ProcessStartInfo(#"C:\Windows\System32\slui.exe");
Process p = new Process();
p.StartInfo = startInfo;
p.Start();
p.WaitForExit();
but I keep getting a Win32Exception: 'The system cannot find the file specified'.
If I change the ProcessStartInfo to: (#"C:\Windows\System32\cmd.exe") it will launch just fine.
Is there something with running slui.exe in this context that is breaking?
I'm certain that the file is in the directory specified, so I'm stumped as to what may be going wrong here.
Any ideas how to call slui.exe from a c# method?
Slui.exe is only available as a 64-bit program on Windows x64. Your hard-coded path c:\windows\system32 will get re-directed to c:\windows\syswow64 when you run as a 32-bit process. And thus won't find the file.
Project + Properties, Compile tab, change the Platform target setting to "AnyCPU". Repeat for the Release configuration. And use Environment.GetFolderPath() to ensure it still works when Windows isn't installed to c:\windows.

Categories