I'm trying to compile some unsafe code from an application using Codedom, but everytime I get an error saying I must use "/unsafe." I've googled the issue and added:
Parameters.CompilerOptions = "/unsafe";
To my codedom code. Are there any simple solutions for this?
Edit: if it wasn't already clear, my solution didn't work.
Edit: Here is the class.
public static bool Compile(string EXE_Name, string Source)
{
var Compiler = new CSharpCodeProvider();
var Parameters = new CompilerParameters
{
CompilerOptions = "/unsafe"
};
CompilerResults cResults = default(CompilerResults);
Parameters.GenerateExecutable = true;
Parameters.OutputAssembly = EXE_Name;
Parameters.ReferencedAssemblies.Add(typeof(System.Xml.Linq.Extensions).Assembly.Location);
Parameters.ReferencedAssemblies.Add("System.dll");
Parameters.ReferencedAssemblies.Add("System.Core.dll");
Parameters.ReferencedAssemblies.Add("System.Data.dll");
Parameters.ReferencedAssemblies.Add("System.Data.DataSetExtensions.dll");
Parameters.ReferencedAssemblies.Add("System.Deployment.dll");
Parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
Parameters.ReferencedAssemblies.Add("System.Drawing.dll");
Parameters.ReferencedAssemblies.Add("System.Xml.dll");
Parameters.CompilerOptions = " /target:winexe";
Parameters.TreatWarningsAsErrors = false;
cResults = Compiler.CompileAssemblyFromSource(Parameters, Source);
if (cResults.Errors.Count > 0)
{
foreach (CompilerError CompilerError_loopVariable in cResults.Errors)
{
CompilerError error = CompilerError_loopVariable;
MessageBox.Show("Error: " + error.ErrorText, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return false;
}
else if (cResults.Errors.Count == 0)
{
return true;
}
return true;
}
It works for me - perhaps you weren't setting the parameters correctly?
using System.CodeDom.Compiler;
using Microsoft.CSharp;
class Test
{
public static void Main(string[] args)
{
var compiler = new CSharpCodeProvider();
var parameters = new CompilerParameters {
CompilerOptions = "/unsafe"
};
var source = "unsafe struct Foo {}";
var result = compiler.CompileAssemblyFromSource(parameters, source);
// No errors are shown with the above options set
foreach (var error in result.Errors)
{
Console.WriteLine(error);
}
}
}
var Parameters = new CompilerParameters
{
CompilerOptions = "/unsafe"
};
and later:
Parameters.CompilerOptions = " /target:winexe";
You just replace "/unsafe" with " /target:winexe". Use:
Parameters.CompilerOptions += " /target:winexe";
Related
I'm trying to use CodeDomProvider to make a C# compiler.
I managed to get the errors but i can't get the output.
This is what i have so far:
public List<string> Errors(CompilerResults compilerResults)
{
List<string> messages = new List<string>();
foreach (CompilerError error in compilerResults.Errors)
{
messages.Add(String.Format("Line {0} Error No:{1} - {2}", error.Line, error.ErrorNumber, error.ErrorText));
}
return messages;
}
public CompilerResults ProcessCompilation(string programText)
{
CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = false;
StringCollection assemblies = new StringCollection();
return codeDomProvider.CompileAssemblyFromSource(parameters, programText);
}
CSharpCompiler is the class that contains the functions from above
public JsonResult Compiler(string code)
{
CSharpCompiler compiler = new CSharpCompiler();
CompilerResults compilerResults = compiler.ProcessCompilation(code);
Debug.WriteLine("OUTPUT----------------------------------------------");
foreach (var o in compilerResults.Output)
{
Debug.WriteLine(o);
}
List<string> compilerErrors = compiler.Errors(compilerResults);
if (compilerErrors.Count != 0)
return Json(new { success = false, errors = compilerErrors});
return Json(true);
}
compilerResults.Output is always empty.
If i run this piece of code:
using System;
public class HelloWorld
{
public static void Main()
{
Console.WriteLine("Hello world!");
}
}
What can i do to display the message "Hello world!"?
CompileAssemblyFromSource creates, as its name implies, an assembly. To get access to the compiled code, you can use the CompilerResults.CompiledAssembly property and then use reflection to find and invoke the Main method:
compilerResults.CompiledAssembly.GetType("HelloWorld").GetMethod("Main").Invoke(null, null);
Though if you set parameters.GenerateExecutable to true, you can simplify this to:
compilerResults.CompiledAssembly.EntryPoint.Invoke(null, null);
I m using the following code to invoke SOAP method dynamically. It works when the input for the service is ONE(1). When I increase the input to Two it returns error.
Out of idea why this happens.
I referred to this link to built this..
http://www.codeproject.com/Articles/18950/Dynamic-Discovery-and-Invocation-of-Web-Services
My SOAP Service:
[WebMethod]
public string UpdateMapString(string status, string astationid)
{
return string.Format("Update Completed");
}
This is my C# Code Calling the SOAP service.
The main Function:
private MethodInfo[] methodInfo;
private ParameterInfo[] param;
private Type service;
private Type[] paramTypes;
public List<Type> myproperty = new List<Type>();
private string MethodName = "";
public List<string> treews = new List<string>();
public List<string> treeParameters = new List<string>();
public static void Main(string[] args)
{
Program a = new Program();
a.DynamicInvocation();
a.selectMethod();
a.invoke();
Console.ReadLine();
}
To Call Service:
public void DynamicInvocation()
{
try
{
Uri uri = new Uri("http://localhost:50167/Service.asmx?WSDL");
WebRequest webRequest = WebRequest.Create(uri);
System.IO.Stream requestStream = webRequest.GetResponse().GetResponseStream();
// Get a WSDL file describing a service
ServiceDescription sd = ServiceDescription.Read(requestStream);
string sdName = sd.Services[0].Name;
// Add in tree view
// treeWsdl.Nodes.Add(sdName);
treews.Add(sdName);
Console.WriteLine("Service Name: " + sdName);
// messageTextBox.Text += "Generating Proxy \r\n";
// progressBar1.PerformStep();
// Initialize a service description servImport
ServiceDescriptionImporter servImport = new ServiceDescriptionImporter();
servImport.AddServiceDescription(sd, String.Empty, String.Empty);
servImport.ProtocolName = "Soap";
servImport.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties;
// messageTextBox.Text += "Generating assembly \r\n";
// progressBar1.PerformStep();
CodeNamespace nameSpace = new CodeNamespace();
CodeCompileUnit codeCompileUnit = new CodeCompileUnit();
codeCompileUnit.Namespaces.Add(nameSpace);
// Set Warnings
ServiceDescriptionImportWarnings warnings = servImport.Import(nameSpace, codeCompileUnit);
if (warnings == 0)
{
StringWriter stringWriter = new StringWriter(System.Globalization.CultureInfo.CurrentCulture);
Microsoft.CSharp.CSharpCodeProvider prov = new Microsoft.CSharp.CSharpCodeProvider();
prov.GenerateCodeFromNamespace(nameSpace, stringWriter, new CodeGeneratorOptions());
// messageTextBox.Text += "Compiling assembly \r\n";
// progressBar1.PerformStep();
// Compile the assembly with the appropriate references
string[] assemblyReferences = new string[2] { "System.Web.Services.dll", "System.Xml.dll" };
CompilerParameters param = new CompilerParameters(assemblyReferences);
param.GenerateExecutable = false;
param.GenerateInMemory = true;
param.TreatWarningsAsErrors = false;
param.WarningLevel = 4;
CompilerResults results = new CompilerResults(new TempFileCollection());
results = prov.CompileAssemblyFromDom(param, codeCompileUnit);
Assembly assembly = results.CompiledAssembly;
service = assembly.GetType(sdName);
methodInfo = service.GetMethods();
foreach (MethodInfo t in methodInfo)
{
if (t.Name == "Discover")
break;
Console.WriteLine(t.Name);
}
}
// messageTextBox.Text += warnings;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
// messageTextBox.Text += "\r\n" + ex.Message + "\r\n\r\n" + ex.ToString(); ;
// progressBar1.Value = 70;
}
}
To get the Method:
public void selectMethod()
{
treeParameters.Add(treews[0]);
MethodName = methodInfo[0].Name;
param = methodInfo[0].GetParameters();
/// myProperty.add = param[e.Node.Index].ParameterType;
myproperty.Add(param[0].ParameterType);
// Console.WriteLine("This is param: " + param[0].ToString());
// myProperty = new properties(param.Length);
// Get the Parameters Type
paramTypes = new Type[param.Length];
for (int i = 0; i < paramTypes.Length; i++)
{
paramTypes[i] = param[i].ParameterType;
}
foreach (ParameterInfo temp in param)
{
treeParameters.Add(temp.ParameterType.Name + " " + temp.Name);
}
}
To Invoke Service (error in this function)
public void invoke()
{
Console.WriteLine("Invoke:");
object[] param1 = new object[param.Length];
try
{
for (int i = 0; i < param.Length; i++)
{
//param1[i] = Convert.ChangeType(myProperty.MyValue[i], myProperty.TypeParameter[i]);
// Console.WriteLine(myproperty[i].ToString());
param1[i] = Convert.ChangeType("10", typeof(string));
}
foreach (MethodInfo t in methodInfo)
{
//Console.WriteLine("Tname: " + t.Name.ToString());
if (t.Name == MethodName)
{
//Invoke Method
Object obj = Activator.CreateInstance(service);
//*****************error at this line
Object response = t.Invoke(obj, param1);
//*****************error at this line
// Console.WriteLine(t.Name);
Console.WriteLine(response.ToString());
break;
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
//MessageBox.Show(ex.Message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
I have an interface and a class that implements it. I am trying to create a unit test that will compile both the interface and the class and see that if there are any errors(if theres none then that would mean the class does implement the interface). I am able to build the interface with no errors but when I try to build the class that implements it it says that the class does not implement the interface. I made sure already that the class does implement the interface so i know that there is something wrong with the way I am trying to compile it on my unit test. I generate the inMemoryAssembly.dll and then try to add it to the parameters when trying to compile the implementation, but that is not working.Any suggestion?
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Text;
using System.IO;
namespace UnitTestProject2
{
[TestClass]
public class UnitTest1
{
[TestMethod]
[TestCategory("NumberOfFiles")]
public void TestMethod1()
{
var serviceReferancepath = System.IO.Path.GetFullPath(#"..\..\Service References\");
compileIterface(serviceReferancepath);
compileImplementation(serviceReferancepath);
}
static void compileIterface(string path)
{
CSharpCodeProvider codeProvider = new Microsoft.CSharp.CSharpCodeProvider();
ICodeCompiler compiler = codeProvider.CreateCompiler();
CompilerParameters parametersForInterface = new CompilerParameters();
parametersForInterface.GenerateInMemory = true;
parametersForInterface.ReferencedAssemblies.Add("System.dll");
parametersForInterface.ReferencedAssemblies.Add("System.Data.Services.Client.dll");
parametersForInterface.ReferencedAssemblies.Add("System.ComponentModel.dll");
parametersForInterface.OutputAssembly = "inMemoryAssembly.dll";
StringBuilder interfaceSC = new StringBuilder();
using (StreamReader sr = new StreamReader(path + #"alarm\IActiveEventSource.cs"))
{
string line;
// Read and display lines from the file until the end of
// the file is reached.
while ((line = sr.ReadLine()) != null)
{
interfaceSC.AppendLine(line);
}
}
CompilerResults results = compiler.CompileAssemblyFromSource(parametersForInterface, interfaceSC.ToString());
StringWriter sw = new StringWriter();
foreach (CompilerError ce in results.Errors)
{
if (ce.IsWarning) continue;
sw.WriteLine("{0}({1},{2}: error {3}: {4}", ce.FileName, ce.Line, ce.Column, ce.ErrorNumber, ce.ErrorText);
}
// If there were errors, raise an exception...
string errorText = sw.ToString();
}
static void compileImplementation(string path)
{
Microsoft.CSharp.CSharpCodeProvider codeProvider = new Microsoft.CSharp.CSharpCodeProvider();
ICodeCompiler compiler = codeProvider.CreateCompiler();
CompilerParameters Parameters = new CompilerParameters();
Parameters.ReferencedAssemblies.Add("inMemoryAssembly.dll");
Parameters.GenerateExecutable = false;
Parameters.GenerateInMemory = true;
StringBuilder implementationSC = new StringBuilder();
using (StreamReader sr = new StreamReader(path + #"alarm\implementation\TheActiveEventSource.cs"))
{
string line;
// Read and display lines from the file until the end of
// the file is reached.
while ((line = sr.ReadLine()) != null)
{
implementationSC.AppendLine(line);
}
}
CompilerResults results = compiler.CompileAssemblyFromSource(Parameters, implementationSC.ToString());
StringWriter sw = new StringWriter();
foreach (CompilerError ce in results.Errors)
{
if (ce.IsWarning) continue;
sw.WriteLine("{0}({1},{2}: error {3}: {4}", ce.FileName, ce.Line, ce.Column, ce.ErrorNumber, ce.ErrorText);
}
// If there were errors, raise an exception...
string errorText = sw.ToString();
}
}
}
The compileImplementation method, when I run it with a breakpoint I get the following error for the results
UnitTestProject2.alarm.ActiveEventSource' does not implement interface member 'UnitTestProject2.alarm.IActiveEventSource.EventSource
This the implementation code
namespace UnitTestProject2.alarm
{
partial class ActiveEventSource: IActiveEventSource
{
}
}
edit:
I was looking at the warnings but not the actual error that the compiling of the implementation was saying. the string errortext for the compileImplementatation method says that the inMemoryAssembly.dll could not be found
The following code does not throw any exception but it also doesn't create a new EPT:
public void CreateEnterpriseProjectType(Guid eptGuid, string eptName, string eptDescription)
{
ProjectContext pwaContext = new ProjectContext("http://serverName/pwaName");
pwaContext.Credentials = new NetworkCredential("adminUsername", "adminPassword", "domainName");
EnterpriseProjectTypeCreationInformation eptData = new EnterpriseProjectTypeCreationInformation();
eptData.Id = eptGuid;
eptData.Name = eptName;
eptData.Description = eptDescription;
eptData.IsDefault = false;
eptData.IsManaged = true;
eptData.WorkspaceTemplateName = "PROJECTSITE#0";
eptData.ProjectPlanTemplateId = Guid.Empty;
eptData.WorkflowAssociationId = Guid.Empty;
// Get the maximum order of the existing EPTs and increment by 1 in order to use an order that does not already exist
eptData.Order = Convert.ToInt32(Database.GetValue("SELECT MAX(ENTERPRISE_PROJECT_TYPE_ORDER) FROM [ProjectWebApp].[pub].[MSP_ENTERPRISE_PROJECT_TYPES]")) + 1;
pwaContext.Load(pwaContext.ProjectDetailPages);
pwaContext.ExecuteQuery();
List<ProjectDetailPageCreationInformation> projectDetailPages = new List<ProjectDetailPageCreationInformation>() {new ProjectDetailPageCreationInformation() { Id = pwaContext.ProjectDetailPages[1].Id, IsCreate = false }};
eptData.ProjectDetailPages = projectDetailPages;
EnterpriseProjectType newEpt = pwaContext.EnterpriseProjectTypes.Add(eptData);
pwaContext.EnterpriseProjectTypes.Update();
}
Any ideas on what I'm doing wrong or what I'm missing? Is it possible to create an EPT programmatically?
Yes, it is possible to create an EPT programmatically. Turns out three things were missing:
A second PDP having IsCreate = true (at least one with IsCreate = true and one with IsCreate = false are required for successfully creating an EPT)
A query for iterating through the existing EPTs before adding a new one:
pwaContext.Load(pwaContext.EnterpriseProjectTypes);
pwaContext.ExecuteQuery();
A pwaContext.ExecuteQuery(); after the pwaContext.EnterpriseProjectTypes.Update(); command.
The following code works fine for me:
public class PSI
{
private ProjectContext _context;
private string basicEpt = "Enterprise Project"; // Basic enterprise project type.
private static readonly PSI psi = new PSI();
private int timeoutSeconds = 60;
SvcProject.ProjectClient _prClient;
private PSI ()
{
_context = new ProjectContext(System.Configuration.ConfigurationManager.AppSettings["PwaUrl"]);
//credentials of currently running acount or enable line below
//_context.Credentials = new System.Net.NetworkCredential("user", "pass", "domain");
timeoutSeconds = int.Parse(System.Configuration.ConfigurationManager.AppSettings["DefaultTimeoutPwa"]);
_prClient = new SvcProject.ProjectClient("basicHttp_Project");
}
public static PSI Instance
{
get{ return psi; }
}
public Guid GetEptUid(string eptName)
{
Guid eptUid = Guid.Empty;
try
{
var eptList = _context.LoadQuery( _context.EnterpriseProjectTypes.Where(ept => ept.Name == eptName));
_context.ExecuteQuery();
eptUid = eptList.First().Id;
}
catch (Exception ex)
{
string msg = string.Format("GetEptUid: eptName = \"{0}\"\n\n{1}", eptName, ex.GetBaseException().ToString());
throw new ArgumentException(msg);
}
return eptUid;
}
public PublishedProject CreateProject(string prName, string description, DateTime startDate)
{
try
{
System.Console.Write("\nCreating project: {0} ...", prName);
ProjectCreationInformation newProj = new ProjectCreationInformation();
newProj.Id = Guid.NewGuid();
newProj.Name = prName;
newProj.Description = description;
newProj.Start = startDate;
newProj.EnterpriseProjectTypeId = GetEptUid(basicEpt);
PublishedProject newPublishedProj = _context.Projects.Add(newProj);
QueueJob qJob = _context.Projects.Update();
JobState jobState = _context.WaitForQueue(qJob, timeoutSeconds);
if (jobState == JobState.Success)
return newPublishedProj;
else
return null;
}
catch (Exception ex)
{
System.Console.ForegroundColor = ConsoleColor.Red;
System.Console.WriteLine("\nError: {0}", ex.Message);
System.Console.ResetColor();
return null;
}
}
}
I have a WCF Service and i want to invoke this at run time ...
if i do the same code and instead of WCF(.svc) if i call (.asmx) i can able to get through and getting results... but here WCF gets failed
private void button1_Click(object sender, EventArgs e)
{
string WebserviceUrl = "http://localhost:90/service1/service1.svc";
string serviceName = Service1;
string methodName = GetData;
string[] arArguments = new string[2];
arArguments[0] = 2 ;
string sData =CallWebService(WebserviceUrl, serviceName, methodName, arArguments);
if (!string.IsNullOrEmpty(sData))
MessageBox.Show(sData + "\tData Available");
else
MessageBox.Show(sData + "\tData not Available");
}
[SecurityPermissionAttribute(SecurityAction.Demand, Unrestricted = true)]
private string CallWebService(string WebserviceUrl, string serviceName, string methodName, string[] arArguments)
{
System.Net.WebClient client = new System.Net.WebClient();
System.IO.Stream stream = client.OpenRead(WebserviceUrl + "?wsdl");
ServiceDescription description = ServiceDescription.Read(stream);
ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
importer.ProtocolName = "Soap12";
importer.AddServiceDescription(description, null, null);
importer.Style = ServiceDescriptionImportStyle.Client;
importer.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;
CodeNamespace nmspace = new CodeNamespace();
CodeCompileUnit unit1 = new CodeCompileUnit();
unit1.Namespaces.Add(nmspace);
ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit1);
if (warning == 0) // If Successfull
{
CodeDomProvider provider1 = CodeDomProvider.CreateProvider("CSharp");
string[] assemblyReferences = new string[5] { "System.dll", "System.Web.Services.dll", "System.Web.dll", "System.Xml.dll", "System.Data.dll" };
CompilerParameters parms = new CompilerParameters(assemblyReferences);
CompilerResults results = provider1.CompileAssemblyFromDom(parms, unit1);
if (results.Errors.Count > 0) // Error Part
{
foreach (CompilerError oops in results.Errors)
{
System.Diagnostics.Debug.WriteLine("========Compiler error============");
System.Diagnostics.Debug.WriteLine(oops.ErrorText);
}
throw new System.Exception("Compile Error Occured calling webservice. Check Debug ouput window.");
}
object wsvcClass = results.CompiledAssembly.CreateInstance(serviceName);
MethodInfo mi = wsvcClass.GetType().GetMethod(methodName);
return mi.Name;
}
else
{
return null;
}
}
how to achieve this .....