TraceLab Component Library
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties
RController.cs
Go to the documentation of this file.
1 // RPlugin - A framework for running R scripts in .NET
2 // Copyright © 2012-2013 SEMERU
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 using RPlugin.Properties;
18 using System;
19 using System.Diagnostics;
20 using System.IO;
21 using System.Reflection;
22 using System.Text;
23 
24 namespace RPlugin.Core
25 {
26  internal static class RController
27  {
28  internal static bool HasSetupRun;
29  internal static string Temp;
30  internal static string Cache;
31  internal static string Scripts;
32 
37  static RController()
38  {
39  HasSetupRun = false;
40  Temp = Path.Combine(Path.GetTempPath(), Properties.Settings.Default.TempPath);
41  Cache = Path.Combine(Temp, Properties.Settings.Default.TempCache);
42  Scripts = Path.Combine(Temp, Properties.Settings.Default.TempScripts);
43  // create temp paths
44  Directory.CreateDirectory(Temp);
45  Directory.CreateDirectory(Cache);
46  Directory.CreateDirectory(Scripts);
47  // extract scripts
48  foreach (string resourceName in Assembly.GetExecutingAssembly().GetManifestResourceNames())
49  {
50  if (resourceName.EndsWith(".R"))
51  {
52  ExtractResource(Scripts, resourceName);
53  }
54  }
55  // success
56  HasSetupRun = true;
57  }
58 
59  internal static void RequirePackages(string RScriptPath, params string[] args)
60  {
61  RequireSetupRun();
62  // check packages
63  RScriptResult RCheck = RunScript(RScriptPath, Path.Combine(Scripts, Settings.Default.Resources + "PackageInstaller.R"), "0 " + String.Join(" ", args));
64  if (RCheck.ExitCode != 0)
65  {
66  HasSetupRun = false;
67  throw new Exception("There was an error in the application:\n" + RCheck.Error);
68  }
69  // install missing packages
70  if (!String.IsNullOrWhiteSpace(RCheck.Output.Trim()))
71  {
72  RScriptResult RInstall = RunScriptAdmin(RScriptPath, Path.Combine(Scripts, Settings.Default.Resources + "PackageInstaller.R"), "1 " + RCheck.Output.Trim());
73  if (RInstall.ExitCode != 0)
74  {
75  HasSetupRun = false;
76  throw new Exception("There was an error installing packages.");
77  }
78  }
79  }
80 
88  internal static RScriptResult RunScript(string RScriptPath, string script, params object[] args)
89  {
90  RequireSetupRun();
91  ProcessStartInfo info = new ProcessStartInfo
92  {
93  FileName = RScriptPath,
94  Arguments = "--verbose \"" + Path.Combine(Scripts, script) + "\" " + String.Join(" ", args),
95  UseShellExecute = false,
96  WindowStyle = ProcessWindowStyle.Hidden,
97  CreateNoWindow = true,
98  RedirectStandardError = true,
99  RedirectStandardOutput = true,
100  };
101  RScriptResult result = new RScriptResult();
102  Process R = new Process();
103  R.StartInfo = info;
104  R.OutputDataReceived += result.ScriptOutputHandler;
105  R.ErrorDataReceived += result.ScriptErrorHandler;
106  R.Start();
107  R.BeginOutputReadLine();
108  R.BeginErrorReadLine();
109  R.WaitForExit();
110  result.ExitCode = R.ExitCode;
111  return result;
112  }
113 
123  internal static RScriptResult RunScriptAdmin(string RScriptPath, string script, params object[] args)
124  {
125  RequireSetupRun();
126  ProcessStartInfo info = new ProcessStartInfo
127  {
128  FileName = "cmd.exe",
129  Arguments = "/C \"call \"" + RScriptPath + "\" \"" + Path.Combine(Scripts, script) + "\" " + String.Join(" ", args) + "\"",
130  UseShellExecute = true,
131  Verb = "runas",
132  };
133  Process RAdmin = new Process();
134  RAdmin.StartInfo = info;
135  RAdmin.Start();
136  RAdmin.WaitForExit();
137  return new RScriptResult(null, null, RAdmin.ExitCode);
138  }
139 
143  internal static void ClearCache()
144  {
145  ClearCache(Cache);
146  }
147 
152  internal static void ClearCache(string path)
153  {
154  if (Directory.Exists(path))
155  {
156  DirectoryInfo dInfo = new DirectoryInfo(path);
157  foreach (FileInfo file in dInfo.GetFiles())
158  {
159  try
160  {
161  file.Delete();
162  }
163  catch (Exception) { }
164  }
165  foreach (DirectoryInfo dir in dInfo.GetDirectories())
166  {
167  try
168  {
169  ClearCache(dir.FullName);
170  }
171  catch (Exception) { }
172  }
173  if (!path.Equals(Cache))
174  {
175  try
176  {
177  Directory.Delete(path);
178  }
179  catch (Exception) { }
180  }
181  }
182  }
183 
190  internal static FileStream CreateCacheFile(string name, bool overwrite)
191  {
192  RequireSetupRun();
193  string filename = Path.Combine(Cache, name);
194  if (File.Exists(filename) && !overwrite)
195  {
196  throw new Exception("Filename collision in cache: " + filename);
197  }
198  else
199  {
200  return File.Create(filename);
201  }
202  }
203 
208  internal static DirectoryInfo CreateCacheDirectory(string name, bool checkExists)
209  {
210  RequireSetupRun();
211  string dirname = Path.Combine(Cache, name);
212  if (Directory.Exists(dirname) && checkExists)
213  {
214  return null;
215  }
216  else
217  {
218  return Directory.CreateDirectory(dirname);
219  }
220  }
221 
227  internal static void ExtractResource(string dir, string ResourceName)
228  {
229  File.WriteAllText(Path.Combine(dir, ResourceName),
230  new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(ResourceName)).ReadToEnd());
231  }
232 
238  internal static string GetResourceContents(string ResourceName)
239  {
240  return (new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(ResourceName))).ReadToEnd();
241  }
242 
248  internal static void RequireSetupRun()
249  {
250  if (!HasSetupRun)
251  {
252  throw new Exception("Setup has not been run.");
253  }
254  }
255  }
256 }