一.前言

我们可能会遇到需要在程序中执行一些系统命令,来获取一些信息;或者调用shell脚本。.NET Core 目前已经可以跨平台执行,那么它如何跨平台执行命令呢,请看下面的讲解。

二.ProcessStartInfo、Process 类介绍

我们主要用到的两个类就是 ProcessStartInfo 和 Process ,他们的用法和.NET Framework下是一样的。

1. ProcessStartInfo 类

ProcessStartInfo主要设置一些我们需要创建的进程的参数。比如需要启动的应用程序的文件名,参数等等。

(1)构造方法

它有三个构造方法:

public ProcessStartInfo();public ProcessStartInfo(string fileName);public ProcessStartInfo(string fileName, string arguments);

fileName:用于启动进程的应用程序。

arguments:在进程启动时传递给应用程序的命令行参数。

(2)主要属性

CreateNoWindow:指示是否在新窗口中启动进程。

RedirectStandardError:指示应用程序的错误输出是否写入到流中。

RedirectStandardInput:指示是否从应用程序读取应用程序的输入流。

RedirectStandardOutput:指示应用程序的文本输出是否写入流。

StandardErrorEncoding:错误输出内容编码。

StandardOutputEncoding:文本输出内容编码。

UseShellExecute:指示是否使用操作系统shell启动进程。如果启动进程时使用shell,则为true; 如果应该直接从可执行文件创建进程,则为false。 默认值是true。

该类并没有定义自己的方法,因为它主要设置一些创建进程需要的参数信息。

2. Process 类

该类的主要作用是提供对本地和远程进程的访问,并使你能够启动和停止本地系统进程。

(1).主要属性

ExitCode:获取退出代码。0表示正常, 非0表示非正常退出。

ExitTime:获取关联进程退出的时间。

StartTime:获取关联进程启动的时间。

HasExited:获取一个值,指示相关进程是否已终止。

MachineName:获取运行关联进程的计算机的名称。

SessionId:获取关联进程的终端服务会话标识符。

StandardError:获取读取应用程序错误输出的流。

StandardInput:获取应用程序输入内容的流。

StandardOutput:获取用于读取应用程序文本输出的流。

Threads:获取关联进程中正在运行的线程集合。

(2).主要方法

Start :启动进程

BeginErrorReadLine:异步开始读取应用错误输出。

BeginOutputReadLine:异步开始读取应用标准输出。

CancelErrorRead:取消读取错误输出。

CancelOutputRead:取消读取标准输出。

Close:释放与此组件关联的所有资源。

CloseMainWindow:通过向其主窗口发送关闭消息来关闭具有用户界面的进程。

Kill:立即停止关联的进程。

Refresh:放弃已经在进程中缓存的关联进程的任何信息。

WaitForExit:等待关联进程退出,可以设置超时时间,如不设置则一直等待。

(3)事件

一共有三个事件:

ErrorDataReceived:接收到关联进程输出错误数据。

OutputDataReceived:接收到关联进程输出标准数据。

Exited:关联进程退出

三.在Windows OSX Linux 下执行命令

这里我选择.NET Core带的 dotnet --info输出.NET Core SDK&Runtime相关的信息。

我们通过cmd执行会收到下面的信息:

1.编写代码执行命令

编写的代码如下:

static void Main(){    //创建一个ProcessStartInfo对象 使用系统shell 指定命令和参数 设置标准输出var psi = new ProcessStartInfo("dotnet", "--info") {    RedirectStandardOutput = true};    //启动var proc=Process.Start(psi);        if (proc == null){Console.WriteLine("Can not exec.");}        else{Console.WriteLine("-------------Start read standard output--------------");        //开始读取using (var sr = proc.StandardOutput){                     while (!sr.EndOfStream){Console.WriteLine(sr.ReadLine());}                     if (!proc.HasExited){proc.Kill();}}Console.WriteLine("---------------Read end------------------");Console.WriteLine($"Total execute time :{(proc.ExitTime-proc.StartTime).TotalMilliseconds} ms");Console.WriteLine($"Exited Code : {proc.ExitCode}");}
}

执行结果如下:

从执行结果可以看出,我们通过编写的程序来执行dotnet --info命令获取的结果几乎一样,只有第一行的提示,我们通过cmd执行命令输出的是中文,我们通过程序调用执行输出的是英文,这个问题,有兴趣的朋友可以研究一下。

2.在Linux上执行

使用的系统环境为CentOS 7.2,.NET Core sdk版本为2.0.3。

直接执行命令结果如下:

我将代码上传到git server,然后在linux上clone然后执行结果如下:

可以看到我们获取执行输出是没有问题的,但是获取进程开始执行出错了,无法从进程检索该信息,现在我们移除统计执行时间的代码:

这下我们执行就没有问题了。从这里我们可以得出结论:由于平台的差异,获取一些信息可能会出现异常,所以我们实际一定要在多个平台上测试。

3.在OSX上运行

我在OSX上的.NET Core SDK版本为2.0.0 很久没更新了。

直接执行命令:

从git Clone代码,执行结果如下:

可以看出我们在OSX上执行是没有问题的。

四.在Windows OSX Linux 下执行脚本

1.编写测试脚本

编写脚本的主要逻辑为输出程序当前目录结构,然后输出一句话 “dotnet in 操作系统类型”

Windows: win.bat

@echo offdirecho "dotnet in Windows"

Linux: linux.sh

#!/bin/bashlsecho "dotnet in Linux"

OSX: OSX.sh

#!/bin/bashlsecho "dotnet in OSX"

2.编写测试代码

我将所有的脚本都放在 项目根目录/shell 文件夹下。

因为我们需要根据不同的操作类型,选择不同的脚本来进行执行,所以我们需要在代码里面判断一下操作系统类型。我们可以通过 RuntimeInformation.IsOSPlatform来判断。

static void Main(){    string fileName="shell/";    //根据系统使用不同的shell文件if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)){fileName += "win.bat";}        else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))    {fileName += "linux.sh";}      else{fileName += "OSX.sh";}        //创建一个ProcessStartInfo对象 使用系统shell 指定命令和参数 设置标准输出var psi = new ProcessStartInfo(fileName) { RedirectStandardOutput = true };    //启动var proc = Process.Start(psi);    if (proc == null){Console.WriteLine("Can not exec.");}    else{Console.WriteLine("-------------Start read standard output--------------");        //开始读取using (var sr = proc.StandardOutput){            while (!sr.EndOfStream){Console.WriteLine(sr.ReadLine());}            if (!proc.HasExited){proc.Kill();}}Console.WriteLine("---------------Read end------------------");Console.WriteLine($"Exited Code : {proc.ExitCode}");}
}

3.在Windows下运行

在windows下运行是完全正常的。

4.在OSX运行

直接运行会报一个权限异常,如下:

使用命令加入执行权限:

chmod +x OSX.sh

然后再次执行:

可以看到成功执行了脚本。

5.在Linux上运行

直接运行也是会有权限问题的:

同样使用命令加入执行权限:

chmod +x linux.sh

然后再次执行:

可以看到成功执行了我们的脚本。

4.容易犯的错误

看见上面的例子,我都成功执行了,其实我踩了几个坑,花了我不少时间来解决。

1.sh脚本一定要指定命令解析器

也就是这句话,放在sh脚本开头

#!/bin/bash

2.不管是windows linux osx 脚本编码必须为 ANSI

不然程序执行的时候,读取字符会出错,造成执行异常。

五.写在最后

希望本文能给大家带来帮助,如有问题欢迎和我讨论。

本文所用代码地址:https://github.com/stulzq/BlogDemos/tree/master/DotnetCmd

原文地址: http://www.cnblogs.com/stulzq/p/9074965.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

.NET Core 跨平台执行命令、脚本相关推荐

  1. linux执行命令脚本,Linux - 执行命令与脚本

    01 - Linux执行多条命令 方法1:在命令行下可以一次性粘贴多条语句,shell会依次执行并输出结果 方法2:在一个命令行中,用分号将各个命令隔开或者使用&&连接各个命令 示例: ...

  2. linux批量执行命令脚本,2.3-命令批量执行脚本

    命令批量执行脚本,同样需要两个脚本来实现:1 exe.expect 2 exe.sh 3 ip.list    IP列表 cat exe.expect #!/usr/bin/expect set ho ...

  3. SSH远程登录执行命令脚本

    一.简述 运维工作中远程登录执行命令的脚本很常用,下面分享一下我常用的脚本 二.脚本内容 #!/bin/bashSCRIPT_NAME=`basename $0` CURRENT_DIR=$(cd & ...

  4. .net 服务器自动执行,自动检测服务器使用流量并执行命令脚本

    #coding=utf-8 limit_total=0# limit_total 上传+下载的流量限制,单位GB,如果不限制就是0,如果限制1T就是1024 limit_in=0# limit_in ...

  5. jar包执行命令脚本

    最近需要部署jar包,编写了执行脚本.不完美,停止的时候直接使用kill -9 pid,比较暴力,所以不适合在生产环境使用. 查询相关进程列表 [root@ /]# ps -ef | grep jar ...

  6. Linux Shell脚本专栏_批量主机远程执行命令脚本_08

    文章目录 1. 安装expect 2. 脚本制作 3. 赋予权限 4. 运行脚本 5. 直接运行脚本 6. vmstat测试 1. 安装expect [root@localhost ~]# yum i ...

  7. linux实用的脚本:xcall(同步执行命令)与xsync(同步文件目录)

    一.同步文件/目录脚本(xsync) 将文件或目录同步到集群的其他节点 在使用之前,所有节点均需要安装 rsync 服务(yum install rsync -y) 建议创建脚本目录为:/usr/lo ...

  8. php 设置window计划任务,windows下设置计划任务自动执行PHP脚本

    背景: 环境部署在linux下或者windows中,可以使用windows的自动任务设置自动执行脚本执行一些日常运维任务 图形界面设置相对比较简单 准备工作: wamp(集成的PHP执行环境) 已经写 ...

  9. linux关机前执行脚本,Linux关机时执行指定脚本

    要实现在Linux关机时执行某个脚本的具体思路 1.在文件夹 /etc/init.d/ 下创建关机时需要执行的脚本 file_name; 2.分别在文件夹 /etc/rc0.d/ 和 /etc/rc6 ...

最新文章

  1. 二维码Aztec简介及其解码实现(zxing-cpp)
  2. php js 比较大小写,jQuery-JavaScript比较字符串而不区分大小写
  3. hbase shell命令扩展(转自http://www.netfoucs.com/cuirong1986/article/details/7986900)
  4. 潜在语义分析原理以及python实现代码!!!!
  5. 科兴生物董事长:两针建立免疫记忆 三针后抗体提升十倍
  6. qr分解求线性方程组_矩阵分解
  7. sql高级语法之IF、IFNULL
  8. 安装linux可是c盘文件夹失败,硬盘安装linux失败,进不去以前的windows怎么处理?
  9. VMware下安装ubuntu,桥接上网配置静态IP
  10. fatal error: GL/glut.h: 没有那个文件或目录
  11. mysql安装和基本操作
  12. ubuntu18.04安装roboware-studio
  13. 如何用matlab解决数学建模中的报童问题
  14. java dateformat 格式_使用Java SimpleDateFormat类格式化月份。月份可以采用M、MM、MMM和MMMM格式。...
  15. 教你自己搭建一个ip池(绝对超好用!!!!)
  16. Spring Aop 5种通知写法及参数JoinPoint详解
  17. 延迟队列实现30分钟订单自动过期失效
  18. 企业内部即时通讯系统项目总结
  19. 内蒙古电大计算机考试成绩查询成绩查询,2021年网络教育7月统考成绩查询时间及入口...
  20. 数学向量 java,数学向量和旋转(Topdown java game dev – physics problem)

热门文章

  1. UILabel自适应高度和自动换行
  2. Oracle Solaris 11 Express发布了
  3. MAUI中Maui.Graphics.Controls绘制控件
  4. 使用Redis set 解决数据的唯一性问题
  5. 22468!Windows 11新预览版发布:旧版系统支持十月终止请速升
  6. 使用EF Core操作层次结构数据
  7. 2020年CNCF和开源项目开发速度
  8. 【12图】你管这破玩意叫Pulsar
  9. C# 8.0 默认接口实现
  10. .NET 异步,你也许不知道的5种用法