使用C#給Linux寫Shell腳本(下篇)

    在上篇的《使用C#給Linux寫Shell腳本》結尾中,咱們留下了一個關於C#如何調用BashShell的問題。在文章發佈以後,我留意到有讀者留言推薦使用「Pash」(一款類PowerShell的東西),在我下載並安裝了該項目以後,嘗試之下發現這仍然不是咱們想要的。彷佛C#還真的沒有提供這種(輸出重定向)功能,這也迫使咱們採起了其餘方式來實現。在本篇中,咱們將提高「恫嚇」等級並順帶把這個難題一併解決,各位看官請繫好安全帶。shell

    本篇中,咱們將介紹:數據庫

      (1)、C#直接調用BashShell所遭遇的問題安全

      (2)、使用C的popen方式調用BashShell函數

      (3)、經過調用C來間接的調用BashShellspa


    1、C#直接調用BashShell所產生的問題.net

    使用C#調其餘應用,毫無疑問最直接的方法就是「System.Diagnostics」中的Process.Start了。但當咱們使用Process.Start時,卻發現連最簡單的命令都沒法調用,更無從談起調用並接受返回了。3d

    上圖爲其中一種錯誤(固然還會有更多的問題出現,這裏就不列舉了)。code

 

    2、使用C的popen方式調用blog

    正因爲Process.Start沒法直接調用BashShell的命令,咱們須要繞道而行。get

    咱們先看下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管道並完成輸出重定向。

 

    3、經過調用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]='\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果真難寫,我先在控制檯寫好再拷貝過來)

#!/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

相關文章
相關標籤/搜索