在上篇的《使用C#给Linux写Shell脚本》结尾中,我们留下了一个关于C#如何调用BashShell的问题。在文章发布之后,我留意到有读者留言推荐使用“Pash”(一款类PowerShell的东西),在我下载并安装了该项目之后,尝试之下发现这仍然不是我们想要的。似乎C#还真的没有提供这种(输出重定向)功能,这也迫使我们采取了其他方式来实现。在本篇中,我们将提升“恫吓”等级并顺带把这个难题一并解决,各位看官请系好安全带。

本篇中,我们将介绍:

(1)、C#直接调用BashShell所遭遇的问题

(2)、使用C的popen方式调用BashShell

(3)、通过调用C来间接的调用BashShell


一、C#直接调用BashShell所产生的问题

使用C#调其他应用,毫无疑问最直接的方法就是“System.Diagnostics”中的Process.Start了。但当我们使用Process.Start时,却发现连最简单的命令都无法调用,更无从谈起调用并接受返回了。

上图为其中一种错误(当然还会有更多的问题出现,这里就不列举了)。

二、使用C的popen方式调用

正由于Process.Start无法直接调用BashShell的命令,我们需要绕道而行。

我们先看下C语言,C语言调用Shell的方式有多种,我们选择了popen函数的方式进行调用,先看一下以下的这个demo:

#include<stdio.h>
int main(){
FILE *fp;
char buffer[];
fp=popen("ls /home/le","r");
fread(buffer,,,fp);
pclose(fp);
printf("%s",buffer);
}

通过poepn管道并完成输出重定向。

三、通过调用C来间接调用Shell

既然C已经可以实现对BashShell的调用已经管道重定向,那我们则可以再通过C#调用C的方式,进而间接的完成对BashShell的调用。

我们先对自己的C函数进行改造,改造后的代码如下(对具体操作有疑问的读者可参见《如何让C为C#提供函数》):

#include<stdio.h>
#include<string.h> void* ConvertToCStr(char* input,char* res,int *length){
int i;
for(i=;i<*length;i++){
res[i]=*(input+*i);
}
res[i]='\0';
} void* BashHelper(char* cmdStr,int* cmdLength,char* output,int* length){
FILE* fp;
char buffer[*length];
char cmd[*cmdLength+];
ConvertToCStr(cmdStr,cmd,cmdLength);
fp=popen(cmd,"r");
fread(buffer,*length,*length,fp);
pclose(fp);
strcat(output,buffer);
}

同样的我们也把C# Shell进行改造(没有Intellisense果然难写,我先在控制台写好再拷贝过来)

#!/bin/env csharp

using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
class Clib
{
public static string InvokeBash(string cmdStr)
{
char[] output = new char[];
unsafe
{
fixed (char* c = cmdStr)
fixed (char* op = output)
{
int cmdLenth = cmdStr.Length;
int outputLength = output.Length;
Clib.BashHelper(c, &cmdLenth, op, &outputLength);
return Marshal.PtrToStringAnsi((IntPtr)op);
}
}
} [DllImport("/你存放so的地址/shell.so", CallingConvention = CallingConvention.StdCall)]
static unsafe extern void BashHelper(char* cmdStr, int* cmdLength, char* output, int* length);
}
var cmdStr = "/bin/ls /";
var output = Clib.InvokeBash(cmdStr);
Console.Write(output);

完成之后,我们再次在Shell中调用。

成功执行BashShell命令并把返回输出重定向到C#中。

可能有读者会有这么一个疑问:“这跟直接写BashShell没啥差别啊?!”此言差矣,C#有C#的优势,Bash有Bash的优势,将两者结合起来后,可以形成互补,利用Bash可以快速的操作Linux,而一些Bash无法提供的功能,譬如写入数据库、调用某些服务的API、做其他BashShell无法做的事情等。


好的,本篇就写这么多了,非C内行,文中可能有不科学之处,仅提供思路,勿拍砖哈。谢谢。

原文地址:http://jhonge.net/Home/Single2/1938

使用C#给Linux写Shell脚本(下篇)的更多相关文章

  1. 使用C#给Linux写Shell脚本

    在这个逼格决定人格,鄙视链盛行的年头,尤其是咱们IT界,请问您今天鄙视与被鄙视的次数分别是多少?如果手中没有一点压箱的本事,那就只有看的份了.今天我们也要提升下自己的格调,学习些脑洞大开的东西,学完之 ...

  2. 详解Linux交互式shell脚本中创建对话框实例教程_linux服务器

    本教程我们通过实现来讲讲Linux交互式shell脚本中创建各种各样对话框,对话框在Linux中可以友好的提示操作者,感兴趣的朋友可以参考学习一下. 当你在终端环境下安装新的软件时,你可以经常看到信息 ...

  3. 写shell脚本速查笔记

    linux shell脚本的语法蛋疼,而且对于java开发人员来说又不常用,常常是学了一次等到下次用的时候又忘记了.因此制作这个速查笔记,用于要写shell脚本时快速回忆&速查. 获取当前脚本 ...

  4. 十分钟学会写shell脚本

    大家好!我是handsomecui,下面我为大家讲解一下shell脚本的写法,讲的不好的地方,欢迎大家留言拍砖. 1.在linux下会写shell脚本是非常重要的,下面我参照例子给大家展示几个脚本,顺 ...

  5. Linux常用Shell脚本珍藏【转载】

    我们在运维中,尤其是linux运维,都知道脚本的重要性,脚本会让我们的 运维事半功倍,所以学会写脚本是我们每个linux运维必须学会的一门功课,这里收藏linux运维常用的脚本.如何学好脚本,最关键的 ...

  6. 从windows到linux的shell脚本编码和格式问题

    从windows到linux的shell脚本编码和格式问题   从windows到Linux的shell脚本编码和格式问题 1.异常问题 :set ff=unix 启动脚本在启动时报错比如执行sh s ...

  7. Linux简单Shell脚本监控MySQL、Apache Web和磁盘空间

    Linux简单Shell脚本监控MySQL.Apache Web和磁盘空间 1. 目的或任务 当MySQL数据库.Apache Web服务器停止运行时,重新启动运行,并发送邮件通知: 当服务器磁盘的空 ...

  8. Linux:从windows到linux的shell脚本编码和格式

    从windows到linux的shell脚本编码和格式问题 异常问题 :set ff=unix 启动脚本在启动时报错比如执行sh start.sh,时会报Command not found等等的错误, ...

  9. Linux/Unix shell 脚本中调用SQL,RMAN脚本

    Linux/Unix shell脚本中调用或执行SQL,RMAN 等为自动化作业以及多次反复执行提供了极大的便利,因此通过Linux/Unix shell来完成Oracle的相关工作,也是DBA必不可 ...

随机推荐

  1. MachineKey 操作 之 获取 MachineKey

    MachineKey获取介绍 对MachineKey进行配置,以便将其用于对 Forms 身份验证 Cookie 数据和视图状态数据进行加密和解密,并将其用于对进程外会话状态标识进行验证.本次讲的是如 ...

  2. sqlserver 查找某个字段在哪张表里

    select [name] from [库名].[dbo].sysobjects where id in(select id from [库名].[dbo].syscolumns Where name ...

  3. string,stringbuilder,stringbuffer用法

    总结:1.如果要操作少量的数据用 = String   ==================================>字符串常量2.单线程操作字符串缓冲区 下操作大量数据 = Strin ...

  4. RadioButton(单选按钮)文字在按钮的左边

    <RadioButton style="@style/CustomCheckboxTheme" android:layout_width="fill_parent& ...

  5. Maven的配置和使用(二)

    Maven仓库 使用Maven带给我们一个比较直接的好处是管理jar包,这些jar包默认地址是在C:\Users\用户名.m2 目录下,我们来修改下这个地址: 现在自己想建立的仓库地址的路径下新建文件 ...

  6. Hackerrank11 LCS Returns 枚举+LCS

    Given two strings,  a and , b find and print the total number of ways to insert a character at any p ...

  7. XmlRpc.net 入参结构体嵌套的转义操作

    项目使用C#开发,需要使用XmlRpc和Linux服务器端交互,用的是XmlRpc.net. 普通的程序调用入参和出差都没有问题,今天遇到入参结构体嵌套,结果 args 入参在服务器端不能解析.抓包数 ...

  8. Font Squirrel

    Font Squirrel FontSquirrel:国外免费字体下载网是一个提供高质量商业字体下载网站,提供海量的英文字体库,用户可以随意下载并应用于各种商业用字,无需考虑其版权问题. 官网地址:h ...

  9. 【Telerik】查询控件<telerik:RadMaskedTextBox>的使用

    在SilverLight项目中,实现模糊查询,并将值绑定到列表中,使用了Telerik中的<telerik:RadMaskedTextBox>控件. 要先添加命名空间的引用: xmlns: ...

  10. 使用nodeJs安装Vue-cli

    TIP:win10下安装,使用管理员身份进行,否则会有权限限制. 1,安装完成node,node有自带的npm,可以直接在cmd中,找到nodeJs安装的路径下,进行命令行全局安装vue-cli.(n ...