使用 .R 文件作为资源并直接在 C# 中创建批处理

Posted

技术标签:

【中文标题】使用 .R 文件作为资源并直接在 C# 中创建批处理【英文标题】:Using a .R file as a resource and create a batch directly in C# 【发布时间】:2020-05-30 10:12:42 【问题描述】:

我有许多闪亮的应用程序,文件结构为 global.R、ui.R、server.R 和我称之为 batchTrigger.R 的东西。后者的内容简直就是以下——

.libPath(*Path to my R Package Repository*)
require('shiny')
runApp(*Path to the folder with the aforementioned files*)

我使用以下代码创建了一个名为 application.cmd 的批处理文件-

cls
@pushd ""
:::::::::::::::::::
@echo off
ECHO Loading...Please, wait. The Application will open automatically. 
ECHO --- 
ECHO Do not close this console window for the whole duration of your session 
ECHO in the application.
ECHO ---
@echo off

"C:\Program Files\R\bin\Rscript.exe" ".../**batchTrigger.R**"

:::::::::::::::::::
@popd
cmd /k

这个批处理文件运行良好。然后我更进一步,决定创建一个包含多个 R 应用程序的 windows 窗体。我在表单中有两个按钮,每个按钮都像这样-

 private void application1_click(object sender, EventArgs e)
    
        System.Diagnostics.Process cmd = new Process();
        cmd.StartInfo.UseShellExecute = false;
        cmd.StartInfo.FileName = "...\\**application1.cmd**";
        cmd.StartInfo.Arguments = "/K";
        cmd.StartInfo.CreateNoWindow = false;
        cmd.StartInfo.RedirectStandardInput = true;
        cmd.Start();
    

到目前为止,一切都很好。两个按钮都按预期工作。我想更进一步,但由于我是 C# 的新手,我需要帮助。我希望得到的是解决方案中如此部署的应用程序中 R 文件和 cmd 文件的动态位置。换句话说,我应该能够在 C# 代码in 中编写批处理文件的内容,并且 batchTrigger.R 的路径应该随着 Windows 窗体应用程序的位置而变化(这将是一个自包含部署的可执行文件)。这个想法是 R 包存储库和 R 安装可能保持静态,并且可以分别由 batchTrigger.R 和 application.cmd 指向,但是 batchTrigger.R 本身的位置以及其他 R 文件随应用程序移动。我认为 resource.resx 可以对此做点什么,但我究竟该怎么做,我似乎不明白。任何建议将不胜感激。

【问题讨论】:

您是否考虑过将 bat 文件中您想要动态化的部分作为参数传递给 bat 脚本?这可能更简单。 我刚刚意识到我的想法中犯了一个错误。 global.R、ui.R 和 server.R 文件的位置由 batchTrigger.R 文件指向,它本身不是原生格式。话虽如此,@Dweeberly,我喜欢你的建议。我可以在 R 脚本中创建可以从外部获取的参数,如果 C# 可以以某种方式将应用程序的当前位置作为 csv 抛出我,我也许可以将其作为我的 R 脚本的主目录读入 batchTrigger .R 文件。你认为这是一个好方法吗? 我不能说有一条“正确”的路径,但是让你的 C# 调用带有参数的脚本会提供额外的灵活性,因为你可能会在未来找到更容易修改你的脚本文件,而不是重新编译你的 C#。 GetCurrentDirectory 应该会为您提供您正在工作的目录。 真的很好奇为什么不直接从 c# 启动 Rscript。编写启动rscript的批处理文件并从c#启动批处理文件是添加不必要的中间人 【参考方案1】:

制作一个通用方法:

private void StartSilentR(string rScriptFilePath)

    System.Diagnostics.Process cmd = new Process();
    cmd.StartInfo.UseShellExecute = false;
    cmd.StartInfo.FileName = @"C:\Program Files\R\bin\Rscript.exe";
    cmd.StartInfo.Arguments = rScriptFilePath;
    cmd.StartInfo.CreateNoWindow = false;
    //avoid this unless you must control the app via stdin
    //cmd.StartInfo.RedirectStandardInput = true;
    cmd.Start();

然后在确定脚本的位置后编写一些调用它的东西。例如,如果您的目录结构为:

RLauncherCSharpApp.exe 
rscripts\ui.R
rscripts\global.R
rscripts\batchTrigger.R

然后在c#中你可以:

//take exe Path, remove exe name and add rscripts folder and batchtrigger.R file name 
var rbt = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "rscripts", "batchTrigger.R");

StartSilentR(rbt);

或者,假设您要搜索应用文件夹的所有子文件夹,以查找所有名为 batchTrigger.R 的文件:

var exeFolder = Path.GetDirectoryName(Application.ExecutablePath);
string[] paths = Directory.GetFiles(exeFolder, "batchTrigger.R", SearchOption.AllDirectories);

//maybe add them to a list view and the user can click one to launch ..

【讨论】:

以上是关于使用 .R 文件作为资源并直接在 C# 中创建批处理的主要内容,如果未能解决你的问题,请参考以下文章

使用批处理文件对 c# 解决方案进行条件编译 [关闭]

在c#中将字符串作为批处理文件运行

创建可执行 COM 作为 ATL 项目并在 C# 中使用它

在 C# 中创建大型(巨大)数组

如何在 C# 中直接执行 SQL 查询?

Python subprocess.Popen() 不传输 ® 符号,而是将文字字母 'r' 作为参数转换为批处理文件