C# 以编程方式执行R脚本

C# 以编程方式执行R脚本,c#,r,com,C#,R,Com,我有一个C#程序,可以生成一些R代码。现在我将脚本保存到文件中,然后将其复制/粘贴到R控制台中。我知道R有一个COM接口,但它似乎不适用于最新版本的R(或2.7.8之后的任何版本)。有什么方法可以在保存到文件后从C#以编程方式执行R脚本吗?我假设C#有一个类似于system()的函数,它允许您调用通过Rscript.exe运行的脚本来在C#中执行此操作 shell (R CMD BATCH myRprogram.R) 一定要这样包装你的情节 pdf(file="myoutput.pdf") p

我有一个C#程序,可以生成一些R代码。现在我将脚本保存到文件中,然后将其复制/粘贴到R控制台中。我知道R有一个COM接口,但它似乎不适用于最新版本的R(或2.7.8之后的任何版本)。有什么方法可以在保存到文件后从C#以编程方式执行R脚本吗?

我假设C#有一个类似于
system()
的函数,它允许您调用通过
Rscript.exe运行的脚本来在
C#
中执行此操作

shell (R CMD BATCH myRprogram.R)
一定要这样包装你的情节

pdf(file="myoutput.pdf")
plot (x,y)
dev.off()

或者图像包装器

我们的解决方案基于stackoverflow的这个答案

使用monor更改,我们从字符串发送R代码并将其保存到临时文件,因为用户在需要时运行自定义R代码

public static void RunFromCmd(string batch, params string[] args)
{
    // Not required. But our R scripts use allmost all CPU resources if run multiple instances
    lock (typeof(REngineRunner))
    {
        string file = string.Empty;
        string result = string.Empty;
        try
        {
            // Save R code to temp file
            file = TempFileHelper.CreateTmpFile();
            using (var streamWriter = new StreamWriter(new FileStream(file, FileMode.Open, FileAccess.Write)))
            {
                streamWriter.Write(batch);
            }

            // Get path to R
            var rCore = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\R-core") ??
                        Registry.CurrentUser.OpenSubKey(@"SOFTWARE\R-core");
            var is64Bit = Environment.Is64BitProcess;
            if (rCore != null)
            {
                var r = rCore.OpenSubKey(is64Bit ? "R64" : "R");
                var installPath = (string)r.GetValue("InstallPath");
                var binPath = Path.Combine(installPath, "bin");
                binPath = Path.Combine(binPath, is64Bit ? "x64" : "i386");
                binPath = Path.Combine(binPath, "Rscript");
                string strCmdLine = @"/c """ + binPath + @""" " + file;
                if (args.Any())
                {
                    strCmdLine += " " + string.Join(" ", args);
                }
                var info = new ProcessStartInfo("cmd", strCmdLine);
                info.RedirectStandardInput = false;
                info.RedirectStandardOutput = true;
                info.UseShellExecute = false;
                info.CreateNoWindow = true;
                using (var proc = new Process())
                {
                    proc.StartInfo = info;
                    proc.Start();
                    result = proc.StandardOutput.ReadToEnd();
                }
            }
            else
            {
                result += "R-Core not found in registry";
            }
            Console.WriteLine(result);
        }
        catch (Exception ex)
        {
            throw new Exception("R failed to compute. Output: " + result, ex);
        }
        finally
        {
            if (!string.IsNullOrWhiteSpace(file))
            {
                TempFileHelper.DeleteTmpFile(file, false);
            }
        }
    }
}

完整的博客帖子:

这是我最近为此写的课程。您还可以传入并返回来自C#和R的参数:

//
///此类使用控制台从文件运行R代码。
/// 
公共类RScriptRunner
{
/// 
///使用Rscript.exe从文件运行R脚本。
///例如:
///rscript runner.RunFromCmd(curDirectory+@“\ImageClustering.r”、“rscript.exe”、curDirectory.Replace(“\\”、“/”);
///使用R从C#传递参数:
///args=commandArgs(trailingOnly=TRUE)
///打印(args[1]);
/// 
///R代码所在的文件。
///通常只需要“rscript.exe”
///多个R参数可以用空格分隔。
///返回包含R响应的字符串。
公共静态字符串RunFromCmd(字符串rCodeFilePath、字符串rscript可执行路径、字符串args)
{
string file=rCodeFilePath;
字符串结果=string.Empty;
尝试
{
var info=new ProcessStartInfo();
info.FileName=rscript可执行路径;
info.WorkingDirectory=Path.GetDirectoryName(rscript可执行路径);
info.Arguments=rCodeFilePath+“”+args;
info.RedirectStandardInput=false;
info.RedirectStandardOutput=true;
info.UseShellExecute=false;
info.CreateNoWindow=true;
使用(var proc=new Process())
{
proc.StartInfo=info;
proc.Start();
结果=proc.StandardOutput.ReadToEnd();
}
返回结果;
}
捕获(例外情况除外)
{
抛出新异常(“R脚本失败:+结果,ex);
}
}
}
注意:如果您对清理流程感兴趣,可能需要在代码中添加以下内容。

进程CloseMainWindow();
过程关闭()

这里有一个简单的方法来实现这一点

我的Rscript位于:

C:\Program Files\R\R-3.3.1\bin\RScript.exe

R代码位于:

C:\Users\lenovo\Desktop\R\u试用版\withoutALL.R


我想到了这一点,除了当我使用Rscript运行脚本时,它不能正确地保存绘图。该脚本将创建一组热图,并将绘图保存到不同的文件中。当我运行Rscript时,它只是将最后一张图片保存在pdf文件中,而不是通过IDE执行时得到的单独png文件。这就是R以交互方式与非交互方式工作的方式。打开设备,如
pdf()
png()
jpeg()
或。。。我以为我是在这样做:savePlot(“heatmap1.png”,type=“png”);正如我之前说过的,交互模式(其中
savePlot()
有一定的含义)和非交互模式(您打开设备时)是有区别的。好吧,现在我有了:filled.contour(…)savePlot(“heatmap1.png”,type=“png”),您建议我将其更改为:png(“heatmap1.png”)filled.contour(…)dev.off()如果您有lattice或ggplot2绘图,可能需要在绘图语句周围使用print()。这对我不适用,并且不会清理新的cmd*.exe实例-请参阅我一直在使用它。您可能存在以下问题:Rscript ExecutablePath(您的进程可能无法访问完整的exe路径,或者您需要为Rscript.exe创建环境变量)、您尝试运行的R代码(如果R代码失败,您将看不到任何结果或错误),或者您可能缺少Rscript.exe。
/// <summary>
/// This class runs R code from a file using the console.
/// </summary>
public class RScriptRunner
{
    /// <summary>
    /// Runs an R script from a file using Rscript.exe.
    /// Example:  
    ///   RScriptRunner.RunFromCmd(curDirectory + @"\ImageClustering.r", "rscript.exe", curDirectory.Replace('\\','/'));
    /// Getting args passed from C# using R:
    ///   args = commandArgs(trailingOnly = TRUE)
    ///   print(args[1]);
    /// </summary>
    /// <param name="rCodeFilePath">File where your R code is located.</param>
    /// <param name="rScriptExecutablePath">Usually only requires "rscript.exe"</param>
    /// <param name="args">Multiple R args can be seperated by spaces.</param>
    /// <returns>Returns a string with the R responses.</returns>
    public static string RunFromCmd(string rCodeFilePath, string rScriptExecutablePath, string args)
    {
            string file = rCodeFilePath;
            string result = string.Empty;

            try
            {

                var info = new ProcessStartInfo();
                info.FileName = rScriptExecutablePath;
                info.WorkingDirectory = Path.GetDirectoryName(rScriptExecutablePath);
                info.Arguments = rCodeFilePath + " " + args;

                info.RedirectStandardInput = false;
                info.RedirectStandardOutput = true;
                info.UseShellExecute = false;
                info.CreateNoWindow = true;

                using (var proc = new Process())
                {
                    proc.StartInfo = info;
                    proc.Start();
                    result = proc.StandardOutput.ReadToEnd();
                }

                return result;
            }
            catch (Exception ex)
            {
                throw new Exception("R Script failed: " + result, ex);
            }
    }
}
 using System; 
 using System.Diagnostics; 
 public partial class Rscript_runner : System.Web.UI.Page
            { 
            protected void Button1_Click(object sender, EventArgs e)
                {
                 Process.Start(@"C:\Program Files\R\R-3.3.1\bin\RScript.exe","C:\\Users\\lenovo\\Desktop\\R_trial\\withoutALL.R");
        }
            }