I am trying to query the names all of the WMI classes within the root\CIMV2 namespace. Is there a way to use a powershell command to retrieve this information in C# ?
Along the lines of Keith's approach
using System;
using System.Management.Automation;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var script = #"
Get-WmiObject -list -namespace root\cimv2 | Foreach {$_.Name}
";
var powerShell = PowerShell.Create();
powerShell.AddScript(script);
foreach (var className in powerShell.Invoke())
{
Console.WriteLine(className);
}
}
}
}
I'm not sure why you mentioned PowerShell; you can do this in pure C# and WMI (the System.Management namespace, that is).
To get a list of all WMI classes, use the SELECT * FROM Meta_Class query:
using System.Management;
...
try
{
EnumerationOptions options = new EnumerationOptions();
options.ReturnImmediately = true;
options.Rewindable = false;
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\cimv2", "SELECT * FROM Meta_Class", options);
ManagementObjectCollection classes = searcher.Get();
foreach (ManagementClass cls in classes)
{
Console.WriteLine(cls.ClassPath.ClassName);
}
}
catch (ManagementException exception)
{
Console.WriteLine(exception.Message);
}
Personally I would go with Helen's approach and eliminate taking a dependency on PowerShell. That said, here's how you would code this in C# to use PowerShell to retrieve the desired info:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Management.Automation;
namespace RunspaceInvokeExp
{
class Program
{
static void Main()
{
using (var invoker = new RunspaceInvoke())
{
string command = #"Get-WmiObject -list -namespace root\cimv2" +
" | Foreach {$_.Name}";
Collection<PSObject> results = invoker.Invoke(command);
var classNames = results.Select(ps => (string)ps.BaseObject);
foreach (var name in classNames)
{
Console.WriteLine(name);
}
}
}
}
}
Just to note that there is a tool available that allows you to create, run, and save WMI scripts written in PowerShell, the PowerShell Scriptomatic tool, available for download from the Microsoft TechNet site.
Using this tool, you could explore all of the WMI classes within the root\CIMV2 or any other WMI namespace.
You'd probably want to just use the System.Management namespace like Helen answered, but you can also host powershell within your application. See http://www.codeproject.com/KB/cs/HowToRunPowerShell.aspx
Related
I am studying this and I have a question, how to extract the path of the process executable?
using System;
using System.Management.Automation;
namespace GetProcess
{
internal class FileName
{
private static void Main()
{
PowerShell ps = PowerShell.Create().AddCommand("Get-Process");
foreach (PSObject result in ps.Invoke())
{
Console.WriteLine("{0,-30}{1,-30}{2,-30}", result.Members["ProcessName"].Value, result.Members["Id"].Value, "How to get the file path?");
// How to get the process path (Mainmodule.FileName) using PowerShell.Create()?
}
ps.Commands.Clear();
Console.ReadKey();
}
}
}
I can get the paths like this:
using (var PSPath = PowerShell.Create().AddScript("Get-Process | Where-Object {$_.Path} | Dir"))
{
foreach (PSObject p in PSPath.Invoke()) Console.WriteLine(p);
}
However, I want to find a method to get the path from PowerShell ps = PowerShell.Create().AddCommand("Get-Process"); where ps is used several times.
Thanks
I am trying to find a way to retrieve Computer name from an IP address in C#, but all of the answers marked online as retrieving machine name or computer name actually get the hostname, not the Computer Name. If you go to Control panel > system, there is a property in that menu "Computer name" ... I'm looking for this value on a remote machine. AFAIK, the HOSTNAME will = the full computer name IF there is no DNS mapping. The problem is that these servers I'm working on do have DNS mapping so the hostname returns their DNS address.
Feel free to correct me on the technical details of that if I said anything wrong, but the question will remain.
I've tried this:
IPHostEntry hostEntry = Dns.GetHostEntry(_ip);
_hostname = hostEntry.HostName;
but obviously returns the HostName, not the Computer name. I could also settle for the "Full computer name" property being returned, and then simply strip the unneeded parts of the string off to reveal the "Computer name."
Also, if you know how to do this with PowerShell, I could use your help as-well. I am hosting the PowerShell engine in my app anyway... so could simply pass your command into PowerShellInstance.AddScript(_yourCommandHere); and pipe its return back into my app.
Please advise if this is possible to do.
#DanielAWhite
EDIT: How is this a duplicate of the listed answer? The answer in that post says exactly what I posted as being the problem to this question. No, that's not a duplicate, because I'm NOT looking for the hostname. I specifically told you in my OP that I wasn't looking for that, and they're not asking what I'm asking. If there is no way to get the computer name from the IP in .NET then just answer the question with that.
From the "duplicate":
Well, not every IP address has a name. However, given the IPAddress you can use >Dns.GetHostEntry to try to resolve it. Also note that if it's being a NAT >router, you'll be getting the router's IP address rather than their actual >machine.
look at my OP... .GetHostEntry DOESN'T work. that's the whole reason I took the time to type this up.
thanks
DOUBLE EDIT: BACON has an answer for how to do this; this post was locked because someone didn't take the time to actually read what I wrote. Since it's locked, you also can't give a better answer. But here's how I did it, saving this here for future reference:
//declare a string to be our machinename
string machineName;
//declare a string which we will pass into powershell later as script
//assigns the hostname or IP
string getComputer = "$ip = " + "\"" + ip + "\"" + "\r\n";
//add to the string this, which gets the Win32_ComputerSystem.. #BACON knew what I was after
//we pipe that back using |select -expand Name
getComputer += "get-wmiobject -class Win32_ComputerSystem -property Name -ComputerName " + "$ip " +
"|select -expand Name";
//create a powershell instance using
using (PowerShell PowerShellInstance = PowerShell.Create())
{
//add the script into our instance of ps
PowerShellInstance.AddScript(getComputer);
//instantiate a collection to house our output from PS
//you could also probably just instantiate a PSObject instead of a collection.. but this might be useful if modified to get an array of computer names... and this is how I did it so can't verify
Collection<PSObject> psOutput;
//assign psOutput from .Invoke() method
psOutput = PowerShellInstance.Invoke();
//you could trim this loop and get rid of it for only one IP
foreach (var item in psOutput)
{
//machineName = MachineName||ComputerName string NOT hostname
machineName = item.BaseObject.ToString();
}
}
Oh, and per bacon in the comments, you have to have WMI allowed through windows firewall for this to work. It worked perfectly for me.
Reconstituting my comments as an answer...
Imagine we had an interface like this...
namespace SO56585341
{
public interface IComputerInfoSource
{
string GetComputerName();
}
}
There are a handful of ways to implement this to get the machine name of the local computer. The simplest is to return the value of the Environment.MachineName property...
namespace SO56585341
{
public class EnvironmentClassComputerInfoSource : IComputerInfoSource
{
public string GetComputerName()
{
return System.Environment.MachineName;
}
}
}
You can also use the Environment.GetEnvironmentVariable() method to retrieve the value of the %ComputerName% environment variable...
namespace SO56585341
{
public class EnvironmentVariableComputerInfoSource : IComputerInfoSource
{
public string GetComputerName()
{
return System.Environment.GetEnvironmentVariable("ComputerName");
}
}
}
You can p/invoke the GetComputerName() Windows API function, which is what Environment.MachineName does behind the scenes...
using System.Runtime.InteropServices;
using System.Text;
namespace SO56585341
{
public class WinApiComputerInfoSource : IComputerInfoSource
{
private const int MAX_COMPUTERNAME_LENGTH = 15;
[DllImport("Kernel32.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool GetComputerName(
StringBuilder lpBuffer,
ref int nSize
);
public string GetComputerName()
{
int maxCapacity = MAX_COMPUTERNAME_LENGTH + 1;
StringBuilder nameBuilder = new StringBuilder(maxCapacity, maxCapacity);
if (!GetComputerName(nameBuilder, ref maxCapacity))
{
// TODO: Error handling...
throw new System.ComponentModel.Win32Exception();
}
return nameBuilder.ToString();
}
}
}
You can use WMI to retrieve the Name property of the singleton Win32_ComputerSystem class. You can do this by instantiating a ManagementClass instance for the Win32_ComputerSystem class and calling GetInstances() on it to retrieve an array containing the sole instance...
using System.Linq;
using System.Management;
namespace SO56585341
{
public class WmiClassComputerInfoSource : IComputerInfoSource
{
public string GetComputerName()
{
using (ManagementClass computerSystemClass = new ManagementClass("Win32_ComputerSystem"))
using (ManagementObjectCollection computerSystemCollection = computerSystemClass.GetInstances())
using (ManagementObject computerSystem = computerSystemCollection.Cast<ManagementObject>().Single())
return (string) computerSystem["Name"];
}
}
}
...or by creating a ManagementObjectSearcher and using that to Get() the lone Win32_ComputerSystem instance...
using System.Linq;
using System.Management;
namespace SO56585341
{
public class WmiSearcherComputerInfoSource : IComputerInfoSource
{
public string GetComputerName()
{
ObjectQuery computerSystemQuery = new SelectQuery("Win32_ComputerSystem");
using (ManagementObjectSearcher computerSystemSearcher = new ManagementObjectSearcher(computerSystemQuery))
using (ManagementObjectCollection computerSystemCollection = computerSystemSearcher.Get())
using (ManagementObject computerSystem = computerSystemCollection.Cast<ManagementObject>().Single())
return (string) computerSystem["Name"];
}
}
}
Finally, the value returned by all of the methods above seems to ultimately be stored in the registry, so if you don't mind relying on that implementation detail you can retrieve it from there directly...
using Microsoft.Win32;
namespace SO56585341
{
public class RegistryComputerInfoSource : IComputerInfoSource
{
public string GetComputerName()
{
// See also #"SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName\"
// https://www.oreilly.com/library/view/windows-nt-workstation/9781565926134/10_chapter-07.html
const string valueParentKeyPath = #"SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName\";
using (RegistryKey parentKey = Registry.LocalMachine.OpenSubKey(valueParentKeyPath, false))
return (string) parentKey.GetValue("ComputerName");
}
}
}
As for getting the same value from a remote computer only the last three implementations above will work, though with minimal tweaking required. First, just to complete this IComputerInfoSource example, let's create an abstract class to hold the remote machine name/address "parameter"...
namespace SO56585341
{
public abstract class RemoteComputerInfoSource : IComputerInfoSource
{
public string RemoteNameOrIp
{
get;
}
protected RemoteComputerInfoSource(string nameOrIp)
{
RemoteNameOrIp = nameOrIp ?? throw new System.ArgumentNullException(nameof(nameOrIp));
}
public abstract string GetComputerName();
}
}
Retrieving the Win32_ComputerSystem instance via a ManagementClass just becomes a matter of explicitly passing it a ManagementPath that also specifies the NamespacePath and Server...
using System.Linq;
using System.Management;
namespace SO56585341
{
public class RemoteWmiClassComputerInfoSource : RemoteComputerInfoSource
{
public RemoteWmiClassComputerInfoSource(string nameOrIp)
: base(nameOrIp)
{
}
public override string GetComputerName()
{
ManagementPath computerSystemPath = new ManagementPath() {
ClassName = "Win32_ComputerSystem",
NamespacePath = #"root\cimv2",
Server = RemoteNameOrIp
};
using (ManagementClass computerSystemClass = new ManagementClass(computerSystemPath))
using (ManagementObjectCollection computerSystemCollection = computerSystemClass.GetInstances())
using (ManagementObject computerSystem = computerSystemCollection.Cast<ManagementObject>().Single())
return (string) computerSystem["Name"];
}
}
}
A ManagementObjectSearcher can be used by passing a similar ManagementPath wrapped in a ManagementScope...
using System.Linq;
using System.Management;
namespace SO56585341
{
public class RemoteWmiSearcherComputerInfoSource : RemoteComputerInfoSource
{
public RemoteWmiSearcherComputerInfoSource(string nameOrIp)
: base(nameOrIp)
{
}
public override string GetComputerName()
{
ManagementScope computerSystemScope = new ManagementScope(
new ManagementPath() {
NamespacePath = #"root\cimv2",
Server = RemoteNameOrIp
}
);
ObjectQuery computerSystemQuery = new SelectQuery("Win32_ComputerSystem");
using (ManagementObjectSearcher computerSystemSearcher = new ManagementObjectSearcher(computerSystemScope, computerSystemQuery))
using (ManagementObjectCollection computerSystemCollection = computerSystemSearcher.Get())
using (ManagementObject computerSystem = computerSystemCollection.Cast<ManagementObject>().Single())
return (string) computerSystem["Name"];
}
}
}
Querying a remote registry just requires an additional call to OpenRemoteBaseKey() to get a handle to the root of the remote hive...
using Microsoft.Win32;
namespace SO56585341
{
public class RemoteRegistryComputerInfoSource : RemoteComputerInfoSource
{
public RemoteRegistryComputerInfoSource(string nameOrIp)
: base(nameOrIp)
{
}
public override string GetComputerName()
{
// See also #"SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName\"
// https://www.oreilly.com/library/view/windows-nt-workstation/9781565926134/10_chapter-07.html
const string valueParentKeyPath = #"SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName\";
using (RegistryKey baseKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, RemoteNameOrIp))
using (RegistryKey parentKey = baseKey.OpenSubKey(valueParentKeyPath, false))
return (string) parentKey.GetValue("ComputerName");
}
}
}
If you compile all of the above code into a project you can use the following Program class to test it...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace SO56585341
{
public static class Program
{
private const string TestHost = "127.0.0.1";
public static void Main()
{
// Get all non-abstract classes in the executing assembly that implement IComputerInfoSource
IEnumerable<Type> computerInfoSourceTypes = Assembly.GetExecutingAssembly().GetTypes()
.Where(type => type.IsClass && !type.IsAbstract && typeof(IComputerInfoSource).IsAssignableFrom(type));
// For each constructor in each candidate class...
foreach (Type computerInfoSourceType in computerInfoSourceTypes)
foreach (ConstructorInfo constructor in computerInfoSourceType.GetConstructors())
{
ParameterInfo[] constructorParameters = constructor.GetParameters();
object[] instanceParameters;
// If the constructor takes no parameters...
if (!constructorParameters.Any())
instanceParameters = Array.Empty<object>();
// ...or a single string parameter...
else if (constructorParameters.Length == 1 && constructorParameters[0].ParameterType == typeof(string))
instanceParameters = new object[1] { TestHost };
// ...otherwise skip this constructor
else
continue;
// Instantiate the class using the constructor parameters specified above
IComputerInfoSource computerInfoSource = (IComputerInfoSource) constructor.Invoke(instanceParameters);
string result;
try
{
result = computerInfoSource.GetComputerName();
}
catch (Exception ex)
{
result = ex.ToString();
}
Console.WriteLine(
"new {0}({1}).{2}(): \"{3}\"",
computerInfoSourceType.Name,
string.Join(
", ",
instanceParameters.Select(value => $"\"{value}\"")
),
nameof(IComputerInfoSource.GetComputerName),
result
);
}
}
}
}
I found this code to work whether TestHost was set to a machine name, CNAME, or IP address. Note that the Remote*ComputerInfoSource classes will fail if...
The appropriate service (RemoteRegistry or Winmgmt) is not running on the remote machine, or...
The appropriate firewall rule (e.g. WMI-WINMGMT-In-TCP) is not enabled on the remote machine, or...
The code is not run as a user with privileges to access the remote service.
As for PowerShell, one should be able to port the code of any of the above methods from C# (either a direct translation or using PowerShell's conveniences) and wrap them in a call to Invoke-Command since that code will be executed local to the remote machine. For example...
Invoke-Command -ComputerName $nameOrIp -ScriptBlock { $Env:COMPUTERNAME }
...or...
Invoke-Command -ComputerName $nameOrIp -ScriptBlock {
# See also 'HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName\'
# https://www.oreilly.com/library/view/windows-nt-workstation/9781565926134/10_chapter-07.html
Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName\' -Name 'ComputerName'
}
PowerShell also has the Get-WmiObject...
Get-WmiObject -Class 'Win32_ComputerSystem' -ComputerName $nameOrIp -Property 'Name'
...and Get-CimInstance cmdlets...
Get-CimInstance -Class 'Win32_ComputerSystem' -ComputerName $nameOrIp -Property 'Name'
...that make working with WMI much easier. In general, I would recommend using WMI since it is pretty easy to use from C# and PowerShell for both local and remote queries, and it exists for exactly this purpose of retrieving system details without having to know about the underlying API calls or data representation.
Note that when using the Invoke-Command or Get-CimInstance cmdlets that the WinRM service must be running on the remote machine and the appropriate firewall rule (e.g. WINRM-HTTP-In-TCP-NoScope) must be enabled. Also, when passing an IP address to the -ComputerName parameter of either of those cmdlets that address must be matched by the value of WSMan:\localhost\Client\TrustedHosts. If you need to scan an entire network by IP address I tested and found that TrustedHosts accepts the * wildcard but not subnet masks, CIDR notation, or the ? wildcard.
I have a WPF C# application that contains a button.
The code of the button click is written in separate text file which will be placed in the applications runtime directory.
I want to execute that code placed in the text file on the click of the button.
Any idea how to do this?
Code sample for executing compiled on fly class method:
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Net;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string source =
#"
namespace Foo
{
public class Bar
{
public void SayHello()
{
System.Console.WriteLine(""Hello World"");
}
}
}
";
Dictionary<string, string> providerOptions = new Dictionary<string, string>
{
{"CompilerVersion", "v3.5"}
};
CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions);
CompilerParameters compilerParams = new CompilerParameters
{GenerateInMemory = true,
GenerateExecutable = false};
CompilerResults results = provider.CompileAssemblyFromSource(compilerParams, source);
if (results.Errors.Count != 0)
throw new Exception("Mission failed!");
object o = results.CompiledAssembly.CreateInstance("Foo.Bar");
MethodInfo mi = o.GetType().GetMethod("SayHello");
mi.Invoke(o, null);
}
}
}
You can use Microsoft.CSharp.CSharpCodeProvider to compile code on-the-fly. In particular, see CompileAssemblyFromFile.
I recommend having a look at Microsoft Roslyn, and specifically its ScriptEngine class.
Here are a few good examples to start with:
Introduction to the Roslyn Scripting API
Using Roslyn ScriptEngine for a ValueConverter to process user input.
Usage example:
var session = Session.Create();
var engine = new ScriptEngine();
engine.Execute("using System;", session);
engine.Execute("double Sin(double d) { return Math.Sin(d); }", session);
engine.Execute("MessageBox.Show(Sin(1.0));", session);
Looks like someone created a library for this called C# Eval.
EDIT: Updated link to point to Archive.org as it seems like the original site is dead.
What you need is a CSharpCodeProvider Class
There are several samples to understand how does it work.
1 http://www.codeproject.com/Articles/12499/Run-Time-Code-Generation-I-Compile-C-Code-using-Mi
The important point of this example that you can do all things on flay in fact.
myCompilerParameters.GenerateExecutable = false;
myCompilerParameters.GenerateInMemory = false;
2 http://www.codeproject.com/Articles/10324/Compiling-code-during-runtime
This example is good coz you can create dll file and so it can be shared between other applications.
Basically you can search for http://www.codeproject.com/search.aspx?q=csharpcodeprovider&x=0&y=0&sbo=kw&pgnum=6 and get more useful links.
I can use PowerShell to do this fairly easily, but I am looking for a C# way to do this. With PS, I can use Get-Service to iterate over the collection and check collections in there called DependentServices and RequiredServices to get the list of the dependent and required services for a given service.
I've looked into the WMI model using the query "Select * from Win32_Service", but this returns a collection of Win32_Service objects that does not seem to have the collections I am interested in. I feel like I am missing something here. I have looked around and tried various searches, but I've not turned up a C#-centric way of doing this.
I want to query a given service and get back the collections mentioned above (DependentServices and RequiredServices). Sorry if I missed the obvious, but I really have not been able to find relevant topics.
You can use the ServiceController class:
StringBuilder sb = new System.Text.StringBuilder();
foreach (var svc in System.ServiceProcess.ServiceController.GetServices())
{
sb.AppendLine("============================");
sb.AppendLine(svc.DisplayName);
foreach (var dep in svc.DependentServices)
{
sb.AppendFormat("\t{0}", dep.DisplayName);
sb.AppendLine();
}
}
MessageBox.Show(sb.ToString());
You can use the Win32_DependentService WMI class and the Associators of sentence to retrieve the dependent services.
Try this sample
using System;
using System.Collections.Generic;
using System.Management;
using System.Text;
namespace GetWMI_Info
{
class Program
{
static void Main(string[] args)
{
try
{
string ComputerName = "localhost";
ManagementScope Scope;
Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), null);
Scope.Connect();
ObjectQuery Query = new ObjectQuery("Associators of {Win32_Service.Name='NetMan'} Where AssocClass=Win32_DependentService ResultClass=Win32_Service");
ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query);
foreach (ManagementObject WmiObject in Searcher.Get())
{
Console.WriteLine("{0,-35} {1,-40}","Name",WmiObject["Name"]);// String
}
}
catch (Exception e)
{
Console.WriteLine(String.Format("Exception {0} Trace {1}",e.Message,e.StackTrace));
}
Console.WriteLine("Press Enter to exit");
Console.Read();
}
}
}
You can use this property -
http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicecontroller.dependentservices.aspx
ServiceController sc = new ServiceController("Event Log");
ServiceController[] scServices = sc.DependentServices;
// Display the list of services dependent on the Event Log service.
if (scServices.Length == 0)
{
Console.WriteLine("There are no services dependent on {0}",
sc.ServiceName);
}
else
{
Console.WriteLine("Services dependent on {0}:",
sc.ServiceName);
foreach (ServiceController scTemp in scServices)
{
Console.WriteLine(" {0}", scTemp.DisplayName);
}
}
I have a WPF C# application that contains a button.
The code of the button click is written in separate text file which will be placed in the applications runtime directory.
I want to execute that code placed in the text file on the click of the button.
Any idea how to do this?
Code sample for executing compiled on fly class method:
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Net;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string source =
#"
namespace Foo
{
public class Bar
{
public void SayHello()
{
System.Console.WriteLine(""Hello World"");
}
}
}
";
Dictionary<string, string> providerOptions = new Dictionary<string, string>
{
{"CompilerVersion", "v3.5"}
};
CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions);
CompilerParameters compilerParams = new CompilerParameters
{GenerateInMemory = true,
GenerateExecutable = false};
CompilerResults results = provider.CompileAssemblyFromSource(compilerParams, source);
if (results.Errors.Count != 0)
throw new Exception("Mission failed!");
object o = results.CompiledAssembly.CreateInstance("Foo.Bar");
MethodInfo mi = o.GetType().GetMethod("SayHello");
mi.Invoke(o, null);
}
}
}
You can use Microsoft.CSharp.CSharpCodeProvider to compile code on-the-fly. In particular, see CompileAssemblyFromFile.
I recommend having a look at Microsoft Roslyn, and specifically its ScriptEngine class.
Here are a few good examples to start with:
Introduction to the Roslyn Scripting API
Using Roslyn ScriptEngine for a ValueConverter to process user input.
Usage example:
var session = Session.Create();
var engine = new ScriptEngine();
engine.Execute("using System;", session);
engine.Execute("double Sin(double d) { return Math.Sin(d); }", session);
engine.Execute("MessageBox.Show(Sin(1.0));", session);
Looks like someone created a library for this called C# Eval.
EDIT: Updated link to point to Archive.org as it seems like the original site is dead.
What you need is a CSharpCodeProvider Class
There are several samples to understand how does it work.
1 http://www.codeproject.com/Articles/12499/Run-Time-Code-Generation-I-Compile-C-Code-using-Mi
The important point of this example that you can do all things on flay in fact.
myCompilerParameters.GenerateExecutable = false;
myCompilerParameters.GenerateInMemory = false;
2 http://www.codeproject.com/Articles/10324/Compiling-code-during-runtime
This example is good coz you can create dll file and so it can be shared between other applications.
Basically you can search for http://www.codeproject.com/search.aspx?q=csharpcodeprovider&x=0&y=0&sbo=kw&pgnum=6 and get more useful links.