shell: 使用C#给Linux写Shell脚本(下篇)

shell scott 179℃ 0评论

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

shell: 使用C#给Linux写Shell脚本(下篇)

shell: 使用C#给Linux写Shell脚本(下篇)

本篇中,我们将介绍:

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

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

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

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

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

shell: 使用C#给Linux写Shell脚本(下篇)

shell: 使用C#给Linux写Shell脚本(下篇)

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

二、使用C的popen方式调用

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

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

1
2
3
4
5
6
7
8
9
#include<stdio.h>
int  main(){
    FILE  *fp;
     char  buffer[255 ];
    fp =popen(" ls /home/le >" ," r >" );
    fread(buffer, 255 ,255 ,fp);
    pclose(fp);
    printf( " %s >" ,buffer);
}
shell: 使用C#给Linux写Shell脚本(下篇)

shell: 使用C#给Linux写Shell脚本(下篇)

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<stdio.h>
#include <string .h>
void * ConvertToCStr(char * input,char * res,int  *length){
     int  i;
     for (i=0 ;i<*length;i++){
        res[i] =*(input+2 *i);
    }
    res[i] =' \0 ' ;
}
 void * BashHelper(char * cmdStr,int * cmdLength,char * output,int * length){
    FILE * fp;
     char  buffer[*length];
     char  cmd[*cmdLength+1 ];
    ConvertToCStr(cmdStr,cmd,cmdLength);
    fp =popen(cmd," r >" );
    fread(buffer, *length,*length,fp);
    pclose(fp);
    strcat(output,buffer); 
}

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

1
2
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
#!/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 [255 ];
         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中调用。

shell: 使用C#给Linux写Shell脚本(下篇)

shell: 使用C#给Linux写Shell脚本(下篇)

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

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

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

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

原文:http://www.cnblogs.com/xiaodiejinghong/p/4475066.html

转载请注明:osetc.com » shell: 使用C#给Linux写Shell脚本(下篇)

喜欢 (0)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址