How to execute a function of R from c#? - c#

I am trying to execute a simple function written in R using C# (Installed R.NET) as under
using Microsoft.Win32;
using RDotNet;
using System;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
using (RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\R-core\R"))
{
var envPath = Environment.GetEnvironmentVariable("PATH");
string rBinPath = (string)registryKey.GetValue("InstallPath");
string rVersion = (string)registryKey.GetValue("Current Version");
rBinPath = System.Environment.Is64BitProcess ? rBinPath + "\\bin\\x64" :
rBinPath + "\\bin\\i386";
Environment.SetEnvironmentVariable("PATH",
envPath + Path.PathSeparator + rBinPath);
}
using (REngine engine = REngine.CreateInstance("RDotNet"))
{
// Initializes settings.
engine.Initialize();
var myAddFunc = engine.Evaluate(#"addFunc <- function(a,b) {
a+b
}").AsFunction();
var sum = engine.Evaluate("#d <- myAddFunc(10,20))").AsNumeric();
engine.Evaluate("print(sum)");
Console.ReadKey();
}
}
}
}
But getting error at
var sum = engine.Evaluate("#d <- myAddFunc(10,20))").AsNumeric();
An unhandled exception of type 'System.ArgumentNullException' occurred in RDotNet.dll
Additional information: Value cannot be null.
What is the mistake that I am doing ?
Running the program in R-Console works fine
> addFunc <- function(a,b) {
+ a+b
+ }
> d<- addFunc(30,40)
> print(d)
[1] 70

typo here? # should be outside of the string. Also it should not be closed by 2 parenthesises.
"#d <- myAddFunc(10,20))"
should be
#"d <- myAddFunc(10,20)"

I know I am late by more than 2 years for this, have you fixed it?
Anyways, try this
using (REngine engine = REngine.CreateInstance("RDotNet"))
{
// Initializes settings.
engine.Initialize();
var myAddFunc = engine.Evaluate(#"addFunc <- function(a,b) {
a+b
}").AsFunction();
var sum = engine.Evaluate(#"addFunc(12,30)").AsNumeric();
engine.Evaluate("print(sum)");
Console.Write(sum[0].ToString());
Console.ReadKey();
}
you need to use addFunc instead of myAddFunc at second Evaluate statement (i.e.
var sum = engine.Evaluate(#"addFunc(12,30)").AsNumeric();
)

Related

Running an R-script from C#

I have the following R script and C# program that is used as an example of calling R from C#. If I run the script from within R-GUI, I see the expected output. However, if I run it from within C# as below, I get no output. I tried moving the R script inside the C# executable directory, and this doesn't work either. I tried running Visual Studio as Administrator, again no output.
Not sure what I am doing wrong:
R code:
# Gradient Boosting model with gbm
# Turn off library warning messages
suppressWarnings(library(gbm))
# gbm result for simulated data
get_gbm <- function()
{
set.seed(123)
a <- sample(1:10, 250, replace = T)
b <- sample(10:20, 250, replace = T)
flag <- ifelse(a > 5 & b > 10, "red", ifelse(a < 3, "yellow", "green"))
df <- data.frame(a = a, b = b, flag = as.factor(flag))
train <- df[1:200,]
test <- df[200:250,]
mod_gb <- gbm(flag ~ a + b,
data = train,
distribution = "multinomial",
shrinkage = .01,
n.minobsinnode = 10,
n.trees = 100)
pred <- predict.gbm(object = mod_gb,
newdata = test,
n.trees = 100,
type = "response")
res <- cbind(test, pred)
return(res)
}
# need to call function to get the output
get_gbm()
C# code:
using System;
using System.Diagnostics;
using System.IO;
class Program
{
static void Main(string[] args)
{
var rmainpath = #"C:\Program Files\R\R-4.0.3";
var rpath = rmainpath + #"\bin\Rscript.exe";
var mainGoogleDrivePath = #"C:\Users\Administrator\Google Drive";
//var scriptpath = mainGoogleDrivePath + #"\repos\rsource\Script.R";
var scriptpath = mainGoogleDrivePath + #"\Projects\RFromCSharp\RFromCSharp\bin\Debug\Script.R";
var output = RunRScript(rpath, scriptpath);
Console.WriteLine(output); // output is empty
Console.ReadLine();
}
private static string RunRScript(string rpath, string scriptpath)
{
try
{
var info = new ProcessStartInfo
{
FileName = rpath,
WorkingDirectory = Path.GetDirectoryName(scriptpath),
Arguments = scriptpath,
RedirectStandardOutput = true,
CreateNoWindow = true,
UseShellExecute = false
};
using (var proc = new Process { StartInfo = info })
{
if (false == proc.Start())
throw new Exception("Didn't start R");
return proc.StandardOutput.ReadToEnd();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
return string.Empty;
}
}

Raspberry Pi, Windows IoT, C#

I am currently experimenting with my Raspberry Pi with Grove sensors and Windows IoT. I am trying to transfer information from the Raspberry Pi to Azure and I receive an error (In line 85).
The code looks this way:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Http;
using Windows.ApplicationModel.Background;
using GrovePi;
using GrovePi.I2CDevices;
using GrovePi.Sensors;
using GrovePi.Common;
using System.Threading.Tasks;
using Microsoft.Azure.Devices.Client;
using Newtonsoft.Json;
// The Background Application template is documented at http://go.microsoft.com/fwlink/?LinkID=533884&clcid=0x409
namespace GrooveTHS
{
public sealed class StartupTask : IBackgroundTask
{
IRgbLcdDisplay LCDDisplay;
public void Run(IBackgroundTaskInstance taskInstance)
{
IDHTTemperatureAndHumiditySensor sensor = DeviceFactory.Build.DHTTemperatureAndHumiditySensor(Pin.DigitalPin7, DHTModel.Dht11); // pinD7
LCDDisplay = DeviceFactory.Build.RgbLcdDisplay(); // pinI2C-1
IRotaryAngleSensor potentiometer = DeviceFactory.Build.RotaryAngleSensor(Pin.AnalogPin2); // pinA2
ILed red = DeviceFactory.Build.Led(Pin.DigitalPin5); // pinD5
ILed green = DeviceFactory.Build.Led(Pin.DigitalPin6); // pinD6
IUltrasonicRangerSensor dsensor = DeviceFactory.Build.UltraSonicSensor(Pin.DigitalPin4); // pin D4
double angle = 0;
double tmax = 0;
while (true)
{
Task.Delay(500).Wait();
angle = potentiometer.SensorValue();
sensor.Measure();
string sensortemp = sensor.TemperatureInCelsius.ToString();
tmax = Math.Floor(angle / 10);
string sensorvalue = dsensor.MeasureInCentimeters().ToString();
if (sensor.TemperatureInCelsius > tmax)
{
System.Diagnostics.Debug.WriteLine("Raumtemperatur: " + sensortemp + "C " + "Tmax: " + tmax.ToString() + "C");
red.AnalogWrite(Convert.ToByte(240));
green.AnalogWrite(Convert.ToByte(0));
}
else
{
System.Diagnostics.Debug.WriteLine("Raumtemperatur: " + sensortemp + "C" + "Tmax: " + tmax.ToString() + "C");
red.AnalogWrite(Convert.ToByte(0));
green.AnalogWrite(Convert.ToByte(240));
}
if (dsensor.MeasureInCentimeters() < 150)
{
LCDDisplay.SetBacklightRgb(BitConverter.GetBytes(990)[0], BitConverter.GetBytes(990)[0], BitConverter.GetBytes(990)[0]);
LCDDisplay.SetText("Raumtemperatur: " + sensortemp + "C " + "Tmax: " + tmax.ToString() + "C");
}
else
{
LCDDisplay.SetText("");
LCDDisplay.SetBacklightRgb(BitConverter.GetBytes(0)[0], BitConverter.GetBytes(0)[0], BitConverter.GetBytes(0)[0]);
}
}
}
static async void SendDeviceToCloudMessagesAsync(long inputDistance)
{
string iotHubUri = "IotHubAuburn.azure-devices.net"; // ! put in value !
string deviceId = "jb"; // ! put in value !
string deviceKey = "sHGJlQbLLMeMExNaqtvh8/7N7MHWlBZ0ESj2ePahSwQ="; // ! put in value !
DateTime time = DateTime.UtcNow;
var deviceClient = DeviceClient.Create(iotHubUri, AuthenticationMethodFactory.CreateAuthenticationWithRegistrySymmetricKey(deviceId, deviceKey), TransportType.Http1);
JSON jsonStr = new JSON();
jsonStr.distance = inputDistance;
jsonStr.time = time;
jsonStr.deviceId = deviceId;
var list = JsonConvert.SerializeObject(jsonStr);
System.Diagnostics.Debug.WriteLine(list);
var message = new Message(Encoding.UTF8.GetBytes(list));
await deviceClient.SendEventAsync(message);
}
}
}
And errors I am getting are following (Translated from german language):
1) CS0246 The type or a namespacename "JSON" was not found (maybe a
using-derective or a reprimand assembly is missing).
2) CS0246 The type or a namespacename "JSON" was not found (maybe a
using-derective or a reprimand assembly is missing).
Kind regards,
Alex
The error means that the "JSON" class definition can't be found.
As #Eric Magers pointed out, you can find from the code source you referenced where is the JSON class defined.
Or you can also define your own "JSON" class, for example, like this:
internal class JSON
{
public JSON()
{
}
public string deviceId { get; internal set; }
public long distance { get; internal set; }
public DateTime time { get; internal set; }
}
Another method without defining "JSON" class like this:
string dataBuffer;
DateTime time = DateTime.UtcNow;
long inputDistance = 0;
String deviceId = "MyCSharpDevice";
dataBuffer = string.Format("{{\"deviceId\":\"{0}\",\"distance\":{1},\"time\":{2}}}", deviceId, inputDistance, time);
Message message = new Message(Encoding.UTF8.GetBytes(dataBuffer));
await deviceClient.SendEventAsync(message);
For sending messages to Azure IoT Hub using HTTP protocol in C# you can reference this official sample. Note: the official sample is in Console Application and you are using a background application on Windows IoT Core. Application types are different but how to use Azure IoT Hub SDK is the same.

C# Exporting SharePoint List Attachments from Access

I have a task to export all attachments inside of a SharePoint 2007 List. The list has about 5,000 items. I would like to export these items in one large batch. With the research I have done so far, I have only found one solution that meets my requirements. Below is the link to the web page that I'm referring to. I'm getting an error on line 21 with MSACCESS.Doa.DBEngine(). I'm new to C#, so I'm not exactly sure why I'm getting this error. I have the Access referenced in the VS project. I'm using VS Enterprise. What do I need to do to fix this issue? Thank you for your help.
Source
http://viziblr.com/news/2011/11/5/batch-exporting-sharepoint-2010-list-item-attachments-using.html
C# Code
---
using System;
using System.Linq;
using MSACCESS = Microsoft.Office.Interop.Access;
namespace ExportAccessAttachments3
{
class Program
{
static void Main(string[] args)
{
const string fieldname_filename = "FileName";
const string fieldname_filedata = "FileData";
string outputfolder = #"D:\attachments";
string dbfilename = #"D:\\AX6Reports.accdb";
string tablename = "AX6Reports";
var prefix_fieldnames = new[] { "Name", "Design" };
string attachment_fieldname = "Attachments";
var dbe = new MSACCESS.Dao.DBEngine();
var db = dbe.OpenDatabase(dbfilename, false, false, "");
var rstype = MSACCESS.Dao.RecordsetTypeEnum.dbOpenDynaset;
var locktype = MSACCESS.Dao.LockTypeEnum.dbOptimistic;
string selectclause = string.Format("SELECT * FROM {0}", tablename);
var rs = db.OpenRecordset(selectclause, rstype, 0, locktype);
rs.MoveFirst();
int row_count = 0;
while (!rs.EOF)
{
var prefix_values = prefix_fieldnames.Select(s => rs.Fields[s].Value).ToArray();
var attachment_rs = (MSACCESS.Dao.Recordset2)rs.Fields[attachment_fieldname].Value;
int attachment_count = 0;
while (!attachment_rs.EOF)
{
var field_filename = attachment_rs.Fields[fieldname_filename].Value;
var field_attachment = (MSACCESS.Dao.Field2)attachment_rs.Fields[fieldname_filedata];
if (field_attachment != null)
{
if (field_attachment.Value != null)
{
string prefix = "";
if (prefix_fieldnames.Length > 0)
{
prefix = string.Format("{0}__", string.Join("__", prefix_values));
prefix = prefix.Replace(" ", "_");
prefix = prefix.Replace(":", "_");
prefix = prefix.Replace("/", "_");
}
var dest_fname = System.IO.Path.Combine(outputfolder, prefix + field_filename);
if (System.IO.File.Exists(dest_fname))
{
System.IO.File.Delete(dest_fname);
}
field_attachment.SaveToFile(dest_fname);
}
}
attachment_rs.MoveNext();
attachment_count++;
}
attachment_rs.Close();
Console.WriteLine(row_count);
row_count++;
rs.MoveNext();
}
rs.Close();
}
}
}
Error
An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in mscorlib.dll
Additional information: Retrieving the COM class factory for component with CLSID {CD7791B9-43FD-42C5-AE42-8DD2811F0419} failed due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).

String calculator [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Hi fellow programmers,
I am creating a calculator in C#
and I have a string variable math which contains 100 * 5 - 2
How can I display its output which is 498 in my console?
My code is this:
String math = "100 * 5 - 2";
Console.WriteLine(math);
Console.ReadLine(); // For Pause
So basically, what my code will give me is the string itself which 100 * 5 - 2
but I want it to give me 498 as a result.
Idea about this is pretty much appreciated.
Thanks
Regular Expression evaluation can be done using DataTable.Compute method (from MSDN) :
Computes the given expression on the current rows that pass the filter
criteria.
Try this:
using System.Data;//import this namespace
string math = "100 * 5 - 2";
string value = new DataTable().Compute(math, null).ToString();
Simply try this
String math = (100 * 5 - 2).ToString();
I don't know, Why you want more complex? It's very easy ..
And if you want surely that,You can do that by using EvaluateExpression
public int EvaluateExpression(string math )
{
return Convert.ToInt32(math);
}
........................
String math = "100 * 5 - 2";
int result = EvaluateExpression(math );
Console.WriteLine(result );
See this discussions
Evaluating string "3*(4+2)" yield int 18
Update:
If those values came from input textbox, then write this way
String math = txtCalculator.Text.Trim();
int result = EvaluateExpression(math );
Console.WriteLine(result );
And also you can find out some pretty answer from this discussion
Is it possible to compile and execute new code at runtime in .NET?
Update 2:
Finally I have tried this sample for you :
My full code for class library
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.XPath;
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
String math = "100 * 5 - 2";
Console.WriteLine(Evaluate(math));
}
public static double Evaluate(string expression)
{
var xsltExpression =
string.Format("number({0})",
new Regex(#"([\+\-\*])").Replace(expression, " ${1} ")
.Replace("/", " div ")
.Replace("%", " mod "));
// ReSharper disable PossibleNullReferenceException
return (double)new XPathDocument
(new StringReader("<r/>"))
.CreateNavigator()
.Evaluate(xsltExpression);
// ReSharper restore PossibleNullReferenceException
}
}
You can compile code from string at runtime and execute it:
using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace DynamicCalcTest
{
class Program
{
static void Main(string[] args)
{
var result = new DynamicCalculator<double>("2 + 2 * 2").Execute();
}
}
public class DynamicCalculator<T>
{
private MethodInfo _Method = null;
public DynamicCalculator(string code)
{
_Method = GetMethodInfo(code);
}
public T Execute()
{
return (T)_Method.Invoke(null, null);
}
private MethodInfo GetMethodInfo(string code)
{
var tpl = #"
public static class Calculator
{{
public static double Calc()
{{
return {0};
}}
}}";
var finalCode = string.Format(tpl, code);
var parameters = new CompilerParameters();
parameters.ReferencedAssemblies.Add("mscorlib.dll");
parameters.GenerateInMemory = true;
parameters.CompilerOptions = "/platform:anycpu";
var options = new Dictionary<string, string> { { "CompilerVersion", "v4.0" } };
var c = new CSharpCodeProvider(options);
var results = c.CompileAssemblyFromSource(parameters, finalCode);
var type = results.CompiledAssembly.GetExportedTypes()[0];
var mi = type.GetMethod("Calc");
return mi;
}
}
}

How to use PrintCapabilities Class in C#

I am trying to intercept a printer job and change the attributes of the print job. I can intercept the print job and get information regarding it. I followed this article for that
http://www.codeproject.com/Questions/423178/printing-order-intercept-with-csharp
Now I want to change the paper size of the print job and for that I found this article
http://social.msdn.microsoft.com/Forums/en/windowsxps/thread/8af6ba92-5d2c-444b-91f4-a8747739c1b7
But the problem is I cannot create class PrintCapabilities. Am I missing something ?? Please help.
My current code looks like the following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Printing;
namespace PrintJob
{
class EvenWatch
{
private ManagementEventWatcher manEWatch;
public EvenWatch(string host)
{
System.Management.ManagementScope oMs = new System.Management
.ManagementScope(#"\\" + host + #"\root\cimv2");
oMs.Connect();
manEWatch = new ManagementEventWatcher(oMs, new EventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 0.1 WHERE TargetInstance ISA 'Win32_PrintJob'"));
manEWatch.EventArrived += new EventArrivedEventHandler(
mewPrintJobs_EventArrived);
manEWatch.Start();
}
static void mewPrintJobs_EventArrived(object sender, EventArrivedEventArgs e)
{
foreach (PropertyData prop in e.NewEvent.Properties)
{
string val = prop.Value == null ? "null" : prop.Value.ToString();
}
ManagementBaseObject printJob = (ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value;
string v = "";
foreach (PropertyData propp in printJob.Properties)
{
string name = propp.Name;
string val = propp.Value == null ? "null" : propp.Value.ToString();
val += "\n";
v += name + ":" + val;
}
PrintQueue printerSpooler = null;
printerSpooler = new PrintQueue(new PrintServer(), "EPSON LQ-300+ /II ESC/P 2");
PrintJobSettings printJobSetting = printerSpooler.CurrentJobSettings;
string desc = printJobSetting.Description;
//printerSpooler.CurrentJobSettings.CurrentPrintTicket
Console.WriteLine("-------");
Console.WriteLine(v);
}
}
}
I actually found out the answer. If you are using 4.0 you should also reference ReachFramework.dll once you do that the magic does happen :)

Categories

Resources