Process Start 相关
在自己的【CSharp语法之 Process.Start 相关】 文章中有详解
前言
偶然发现,如果想用如下代码在 .NET 6 中打开指定 URL:
| 1
 | Process.Start("https://baidu.com");
 | 
会引发异常:
 
而同样的代码在 .NET Framework 中是可以正常执行的。
难道,.NET 6 下的实现逻辑不一样?
深入探究
通过调用堆栈,我们发现最后调用的是StartWithCreateProcess方法:
 
对应的 .NET 6 源代码如下:
| 12
 3
 4
 5
 6
 7
 8
 
 | private bool StartCore(ProcessStartInfo startInfo){
 if (!startInfo.UseShellExecute)
 {
 return this.StartWithCreateProcess(startInfo);
 }
 return this.StartWithShellExecuteEx(startInfo);
 }
 
 | 
这和 .NET Framework 中的实现逻辑基本一致:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | public bool Start(){
 this.Close();
 ProcessStartInfo processStartInfo = this.StartInfo;
 if (processStartInfo.FileName.Length == 0)
 {
 throw new InvalidOperationException(SR.GetString("FileNameMissing"));
 }
 if (processStartInfo.UseShellExecute)
 {
 return this.StartWithShellExecuteEx(processStartInfo);
 }
 return this.StartWithCreateProcess(processStartInfo);
 }
 
 | 
那么问题出在哪呢?
通过 dnspy 调试 .NET Framework 版本的测试程序,我们发现,最后执行的是StartWithShellExecuteEx而不是StartWithCreateProcess方法:
 
而之所以走不同的逻辑分支,是由processStartInfo.UseShellExecute控制的。
所以,解决方案也很简单,设置UseShellExecute = true:
| 1
 | Process.Start(new ProcessStartInfo("https://baidu.com") { UseShellExecute = true });
 | 
结论
造成这样的原因,是因为UseShellExecute在 .NET 6 上默认为 false:
| 1
 | public bool UseShellExecute { get; set; }
 | 
而在 .NET Framework 上默认为 true:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | [DefaultValue(true)][MonitoringDescription("ProcessUseShellExecute")]
 [NotifyParentProperty(true)]
 public bool UseShellExecute
 {
 get
 {
 return this.useShellExecute;
 }
 set
 {
 this.useShellExecute = value;
 }
 }
 
 private bool useShellExecute = true;
 
 | 
当UseShellExecute = false时,代码会将传入参数作为文件名使用,从而引发“系统找不到指定的文件”异常。
打开邮件
打开outlook邮件窗口–打开软件,后边没使用
在C#中,要打开Outlook并执行操作,你可以使用Microsoft Outlook PIA (Primary Interop Assembly) 或者通过COM对象模型。以下是使用COM对象模型打开Outlook并创建一个新电子邮件的示例代码:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 
 | using System;using Outlook = Microsoft.Office.Interop.Outlook;
 
 class Program
 {
 static void Main(string[] args)
 {
 
 Outlook.Application outlookApp = new Outlook.Application();
 
 
 Outlook.MailItem mailItem = (Outlook.MailItem)outlookApp.CreateItem(Outlook.OlItemType.olMailItem);
 
 
 mailItem.To = "recipient@example.com";
 mailItem.Subject = "Hello";
 mailItem.Body = "This is a test email.";
 
 
 mailItem.Display(true);
 
 
 System.Runtime.InteropServices.Marshal.ReleaseComObject(mailItem);
 System.Runtime.InteropServices.Marshal.ReleaseComObject(outlookApp);
 
 Console.WriteLine("Email opened in Outlook.");
 }
 }
 
 | 
确保你的项目引用了Microsoft Outlook Object Library。如果你的开发环境是Visual Studio,你可以通过NuGet包管理器安装Microsoft.Office.Interop.Outlook。
请注意,由于COM对象的交互性质,这种方法可能会引发各种异常,比如Outlook没有安装或者COM对象访问被禁用等问题。在实际部署时,你可能需要处理这些异常。
报错找不到文件
我有一个用C#编写的简单应用程序。net 6.0。按下按钮后,我想打开一个Outlook窗口,其中包含文本框中的e-mail内容和文本框中的收件人。
问题是,该应用程序用于公司领域的计算机。我无法使用smtp以编程方式发送电子邮件。
必须从当前登录到计算机(窗口10)的用户的帐户中完全禁止邮件,该用户已配置Outlook帐户,以便将其分配给windows帐户。
我试图使用Microsoft.Office.Interop.Outlook,但我出错了
| 1
 | Could not load file or assembly 'Microsoft.Office.Interop.Outlook, Version = 15.0.0.0, Culture = neutral, PublicKeyToken = 71e9bce111e9429c
 | 
您需要向该项目添加COM引用。右键单击项目的依赖项并选择Add COM references:
 
在对话框窗口中,您可以找到Outlook的条目并将其选中。
 
维奥拉!单击Ok按钮并在代码中使用OOM。
方法一、通过mailto标签发送邮件(常用)
		通过mailto不是正真意义上的发送邮件,它只是会自动调用我们本地默认的邮件服务软件(这取决于我们本地安装了什么邮件软件,outlook,firemail等等),发送还是需要我们自己点击发送才能完成。
  mailto标签有很多实用的方法,比如:加入邮件的默认主题、抄送地址、暗送(密件抄送)地址,邮件内容等待…..
1、为邮件加入发件人
  格式:mailto:发件人地址
  代码示例
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | 
 
 
 
 private void btnSendEmail_ItemClick(object sender, ItemClickEventArgs e)
 {
 string message = string.Format("mailto:{0}", sendFrom);
 System.Diagnostics.Process.Start(message);
 }
 
 | 
2、为邮件加入默认标题
  格式:mailto:发件人地址?subject=邮件主题
  代码示例
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | 
 
 
 
 
 private void btnSendEmail_ItemClick(object sender, ItemClickEventArgs e)
 {
 string message = string.Format("mailto:{0}?subject={1}", sendFrom, subjetc);
 System.Diagnostics.Process.Start(message);
 }
 
 | 
3、为邮件加入默认的抄送地址
   格式:mailto:发件人地址?cc=抄送地址
  代码示例
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | 
 
 
 
 
 private void btnSendEmail_ItemClick(object sender, ItemClickEventArgs e)
 {
 string message = string.Format("mailto:{0}?cc={1}", sendFrom, sendCC);
 System.Diagnostics.Process.Start(message);
 }
 
 | 
4、为邮件加入默认暗送(密件抄送)地址
   格式:mailto:发件人地址?bcc=密送地址
  代码示例
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | 
 
 
 
 
 private void btnSendEmail_ItemClick(object sender, ItemClickEventArgs e)
 {
 string message = string.Format("mailto:{0}?bcc={1}", sendFrom, sendBCC);
 System.Diagnostics.Process.Start(message);
 }
 
 | 
6、多个邮件地址
   格式:mailto:发件人地址1,发件地址2,发件地址3(以逗号分隔)
7、综合型的:加入默认抄送地址,标题,内容
   格式:mailto:发件人地址1,发件人地址2?cc=抄送地址&bcc=密送地址&subject=主题&body=邮件内容
  代码示例
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | 
 
 
 
 
 
 
 
 private void btnSendEmail_ItemClick(object sender, ItemClickEventArgs e)
 {
 string message = string.Format("mailto:{0}?cc={1}&bcc={2}&subject={3}&body={4}", sendFrom, sendCC,
 sendBCC, subjetc, content);
 System.Diagnostics.Process.Start(message);
 }
 
 | 
如图所示:
 
方法二、通过SMTP协议发送邮件
核心代码:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 
 | 
 
 
 
 
 
 
 
 
 
 
 
 
 public static bool SendMessage(string userEmailAddress, string userName, string password, string host, int port,
 string[] sendToList, string[] sendCCList, string subject, string body, string[] attachmentsPath, out string errorMessage)
 {
 errorMessage = string.Empty;
 SmtpClient client = new SmtpClient();
 client.Credentials = new System.Net.NetworkCredential(userEmailAddress, password);
 client.DeliveryMethod = SmtpDeliveryMethod.Network;
 client.Host = host;
 client.Port = port;
 client.UseDefaultCredentials = true;
 
 MailMessage msg = new MailMessage();
 
 foreach (string send in sendToList)
 {
 msg.To.Add(send);
 }
 
 foreach (string cc in sendCCList)
 {
 msg.To.Add(cc);
 }
 
 
 if (attachmentsPath != null && attachmentsPath.Length > 0)
 {
 foreach (string path in attachmentsPath)
 {
 var attachFile = new Attachment(path);
 msg.Attachments.Add(attachFile);
 }
 }
 msg.From = new MailAddress(userEmailAddress, userName);
 msg.Subject = subject;
 msg.Body = body;
 msg.BodyEncoding = System.Text.Encoding.UTF8;
 msg.IsBodyHtml = true;
 msg.Priority = MailPriority.High;
 
 try
 {
 client.Send(msg);
 return true;
 }
 catch (System.Net.Mail.SmtpException ex)
 {
 errorMessage = ex.Message;
 return false;
 }
 }
 
 | 
如图所示:
 
计算器
| 1
 | System.Diagnostics.Process.Start(@"calc.exe");
 | 
默认浏览器
示例界面:
 
方法一:从注册表中读取默认浏览器可执行文件路径
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | private void button1_Click(object sender, EventArgs e){
 
 RegistryKey key = Registry.ClassesRoot.OpenSubKey(@"http\shell\open\command\");
 string s = key.GetValue("").ToString();
 
 
 System.Diagnostics.Process.Start(s.Substring(0, s.Length - 8), "http://blog.csdn.net/testcs_dn");
 }
 
 | 
方法二:
| 12
 3
 4
 5
 
 | private void button2_Click(object sender, EventArgs e){
 
 System.Diagnostics.Process.Start("explorer.exe", "http://blog.csdn.net/testcs_dn");
 }
 
 | 
方法三:
| 12
 3
 4
 5
 
 | private void button3_Click(object sender, EventArgs e){
 
 System.Diagnostics.Process.Start("http://blog.csdn.net/testcs_dn");
 }
 
 | 
方法四:调用IE浏览器
| 12
 3
 4
 5
 
 | private void button4_Click(object sender, EventArgs e){
 
 System.Diagnostics.Process.Start("iexplore.exe", "http://blog.csdn.net/testcs_dn");
 }
 
 | 
方法二和方法三一样,只不过方法三写法简便,
下面说一下方法四
1、所需环境
 .NET环境、需要引用System.Diagnostics这个命名空间、 一个准备好的静态网页
2、实现
其实这个程序非常的简单,只是把调用程序的方法用在了这里而已,并且是用特定程序打开特定文件的的一种使用。
| 1
 | System.Diagnostics.Process.Start(@"IExplore.exe", "http://blog.csdn.net/testcs_d");
 | 
这个函数Start里面有两个参数,第一个是指定的程序的地址,第二个参数是指定的文件的地址,一组合就出现了我们想要的效果(由于IE是系统应用且在环境变量中有了设置,可以直接写.exe的文件)。前提是我们要有上述的网页放在指定位置。
我们不能直接把这个函数写到控件事件中,否则会报错的。我写了一个方法然后调用实现的。如果要调用别的浏览器只要把例子中的”iexplore.exe”改为其他的浏览器程序名既可。
我们还可以用它来进行打开别的文件的操作,比如,用notpad++来打开一个文本文件了,在方法的第一参数上写上notpad++的主程序地址,后面写上文本文件名字就可以了。
相关链接(侵删)
- C# 如何通过mailto标签和SMTP协议两种方式发送邮件
- Process.Start 为什么会引发“系统找不到指定的文件”异常
- C# 打开应用程序或打开默认电子邮件应用程序
- C#打开outlook邮件窗口
- 【C#】调用默认浏览器打开网页的几种方法
=================我是分割线=================
欢迎到公众号来唠嗑:
