在C#中调用命令执行R脚本,要实现这个功能我们得知道:(1)如何用c#调用系统命令;(2)如何用系统命令执行R脚本;(3)如何写R脚本
一、C#调用系统命令
这里的“startInfo.FileName = "cmd.exe";”是通过C#调用的系统命令,当然你也可以执行cmd.exe,也可以执行其他的应用和程序,比如计算器“calc”,R程序“R.exe”等。这里的“string[] command”参数是要执行的命令语句,我这里是针对的是控制台,因为其他的应用程序我不知道怎么将参数传入程序中。

1 /// <summary> 2 /// 执行DOS命令,返回DOS命令的输出 3 /// </summary> 4 /// <param name="dosCommand">dos命令</param> 5 /// <param name="milliseconds">等待命令执行的时间(单位:毫秒), 6 /// 如果设定为0,则无限等待</param> 7 /// <returns>返回DOS命令的输出</returns> 8 public string Execute(string[] command, int seconds = 10) 9 { 10 string output = ""; //输出字符串 11 if (command[0] != null && !command[0].Equals("")) 12 { 13 Process process = new Process();//创建进程对象 14 ProcessStartInfo startInfo = new ProcessStartInfo(); 15 startInfo.FileName = "cmd.exe";//设定需要执行的命令 16 //startInfo.Arguments = "/C " + command;//“/C”表示执行完命令后马上退出 17 //startInfo.Arguments = command;//“/C”表示执行完命令后马上退出 18 startInfo.UseShellExecute = false;//不使用系统外壳程序启动 19 startInfo.RedirectStandardInput = true; //重定向输入 20 startInfo.RedirectStandardOutput = true; //重定向输出 21 startInfo.CreateNoWindow = true;//不创建窗口 22 process.StartInfo = startInfo; 23 try 24 { 25 if (process.Start())//开始进程 26 { 27 if (seconds == 0) 28 { 29 process.WaitForExit();//这里无限等待进程结束 30 } 31 else 32 { 33 process.WaitForExit(seconds); //等待进程结束,等待时间为指定的毫秒 34 } 35 StreamWriter sw = process.StandardInput; 36 sw.WriteLine(command[0]); 37 sw.WriteLine(command[1]); 38 sw.Close(); 39 //process.StandardInput.Close(); 40 output = process.StandardOutput.ReadToEnd();//读取进程的输出 41 } 42 } 43 catch 44 { 45 } 46 finally 47 { 48 if (process != null) 49 process.Close(); 50 } 51 } 52 return output; 53 }
二、 用系统命令执行R脚本
先说明一下用控制台执行R脚本,而之后的用C#调用系统命令执行R脚本就是将这些控制台的语句当作参数传入上面的string[] command数组中
1、将R.exe所在路径加到环境变量path下,路径一般为C:\Program Files\R\R-3.0.1\bin或者在控制台中敲入要转入的目录。
2、在windows 命令行中敲入 调用命令:r CMD BATCH D:\RWORKSPACE\CMD_TEST.R (注意 CMD BATCH 都要大写)
命令的普遍形式为R CMD command file,command是别的工具。比如前面用到的批处理工具BATCH。
这样它就在执行R脚本了。我的测试脚本很简单,当然你可以写的很复杂,执行你要完成的任务。
结果它会生成一个rasterName.csv的结果文件和执行状态的文件Test.r.Rout文件
三、 写R脚本
当然你可以很简单的在记事本中写R脚本,但是为了应用程序的可交互性,你可以用代码在记事本中写脚本,但是要注意的是文件路径的问题。因为在R程序中的路径是“\\”或者“/”的,你的代码中可以将获取的路径的符号其替换为“\\\\”或者“/”。不然无法读取文件。

1 /// <summary> 2 /// 创建随机森林影像分类R脚本 3 /// </summary> 4 /// <param name="rowCount"></param> 5 /// <param name="columnCount"></param> 6 /// <param name="bandCount"></param> 7 /// <param name="workPath"></param> 8 /// <param name="roiPath"></param> 9 /// <param name="rasterPath"></param> 10 public void CreateRandomForestScript(int rowCount=2850, int columnCount=2850, int bandCount=4, string workPath = @"D:", string roiPath = "", string rasterPath = "") 11 { 12 string scriptPath = System.IO.Path.GetFullPath(workPath) + @"\randomForest.r"; 13 workPath = workPath.Replace("\\", "\\\\"); //workPath = workPath.Replace('\\', '/'); 14 roiPath = roiPath.Replace("\\", "\\\\"); 15 rasterPath = rasterPath.Replace("\\", "\\\\"); 16 string resultName = "rasterResult.txt"; 17 string str = ""; 18 string funStr = ""; 19 using (StreamWriter sr = new StreamWriter(scriptPath,false,Encoding.GetEncoding("GB2312"))) 20 { 21 str = "setwd('"+workPath+"')\n"; 22 str += "library(randomForest)\n"; 23 str += "roi<-read.table('" + roiPath + "')\n"; 24 //str += "roi<-read.table(file.choose())\n"; 25 str += "raster<-read.table('" + rasterPath + "')\n"; 26 //str += "raster<-read.table(file.choose())\n"; 27 funStr = "V" + (bandCount + 1) + "~"; 28 for (int i = 0; i < bandCount;i++) 29 { 30 funStr += "V" + (i + 1)+"+"; 31 } 32 funStr = funStr.Remove(funStr.Length-1); 33 str += "spam<-randomForest("+funStr+",data=roi)\n"; 34 //str += "spam<-randomForest(V5~V1+V2+V3+V4,data=roi)\n"; 35 str += "rm(roi)\n"; 36 str += "gc()\n"; 37 str += "c<-predict(spam,raster,type='response')\n"; 38 str += "rm(spam)\n"; 39 str += "rm(raster)\n"; 40 str += "gc()\n"; 41 str += "e<-unlist(c)\n"; 42 str += "result<-matrix(e,nrow="+rowCount+",ncol="+columnCount+")\n"; 43 str += "rm(c)\n"; 44 str += "rm(e)\n"; 45 str += "gc()\n"; 46 str += "write.table(result, '" + resultName + "')\n"; 47 str += "rm(result)\n"; 48 str += "gc()\n"; 49 sr.WriteLine(str); 50 sr.Close(); 51 } 52 }
这是写的创建随机森林影像分类的脚本的函数,产生的脚本文件如下:
四、 调用系统命令执行R脚本
主要的是command 参数那两行代码

1 private void buttonOK_Click(object sender, EventArgs e) 2 { 3 try 4 { 5 if (workPath == "" || roiPath == "" || rasterPath == "" || textBoxX1.Text == "" || textBoxX2.Text == "") 6 return; 7 rowCount = Convert.ToInt32(textBoxX1.Text); 8 columnCount = Convert.ToInt32(textBoxX2.Text); 9 bandCount = Convert.ToInt32(integerInput1.Value); 10 RandomForestClassfier randomForest = new RandomForestClassfier(); 11 randomForest.CreateRandomForestScript(rowCount, columnCount, bandCount, workPath, roiPath, rasterPath); 12 string[] command = new string[2]; 13 command[0] = "cd /d C:\\Program Files\\R\\R-3.2.1\\bin\\x64"; 14 command[1] = "r CMD BATCH "+workPath+@"\randomForest.r"; 15 randomForest.RunRandomForestScript(command); 16 MessageBox.Show("影像分类完成", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); 17 } 18 catch (Exception ex) 19 { 20 MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 21 } 22 }
五、 参考资料
1.http://www.jb51.net/article/57477.htm
2.http://www.jb51.net/article/26993.htm
3.http://q.cnblogs.com/q/44086/
4.http://blog.csdn.net/diyiziran/article/details/21379181
5.http://book.2cto.com/201305/21969.html