Using a .R file as a resource and create a batch directly in C#

2020-02-14 c# r winforms batch-file integration

I have a number of shiny applications with the file structure global.R, ui.R, server.R and something I call batchTrigger.R. The contents of the latter is simply the following-

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

I created a batch file called application.cmd with the following code-

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

This batch file is working just fine. Then I went one step further, and decided to create a windows form with multiple R Applications. I have two buttons in the form, each of which goes something like this-

 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();
    }

So far, so good. Both the buttons work exactly as they were supposed to. I want to go one more step ahead, but since I am very new at C#, I need help. What I am hoping to get is a dynamic location for the R files and the cmd files within the thus deployed application, within the solution. In other words, I should be able to write the contents of the batch file within the C# code, and the path of the batchTrigger.R should be something which changes with the location of the windows form application (which will be a self contained deployed executable file). The idea is that the R package repository and R installation may remain static and can be pointed at by the batchTrigger.R and application.cmd respectively, but the location of batchTrigger.R itself along with other R files move with the application. I think that resource.resx can do something about this, but how exactly can I go about doing it, I don't seem to get. Any suggestion would be highly appreciated.

Answers

Make a general method:

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();
}

Then write something that calls it after working out where the script is. For example if you have your directory structure as:

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

Then in c# you can:

//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);

Or, say you want to search all the subfolders of the app's folder looking for all files called 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 ..

Related