zoukankan      html  css  js  c++  java
  • 使用C#给Linux写Shell脚本(下篇)

        在上篇的《使用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[255];
        fp=popen("ls /home/le","r");
        fread(buffer,255,255,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=0;i<*length;i++){
            res[i]=*(input+2*i);
        }
        res[i]='';
    }
    
    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果然难写,我先在控制台写好再拷贝过来)

    #!/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中调用。

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

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


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

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

  • 相关阅读:
    阶段性总结---初始阶段
    微信授权以及微信支付所遇到的坑(完善)
    CSS3学习
    Playing with String(codeforces 305E)
    Treblecross(uva 10561)
    序列操作(bzoj 1858)
    传送带(bzoj 1857)
    字符串(bzoj 1856)
    刷题比赛(洛谷 1707)
    大楼(bzoj 2165)
  • 原文地址:https://www.cnblogs.com/xiaodiejinghong/p/4475066.html
Copyright © 2011-2022 走看看