CodeDom.compiler memory - c#

I am generating assembly on runtime . Problem is that i cant get rid-of it after i am done with it. I need to destroy this assambly what i have created
string _Errors = "";
object[] parms = null;
CodeDomProvider _CodeCompiler = CodeDomProvider.CreateProvider("CSharp"); //new Microsoft.CSharp.CSharpCodeProvider().CreateCompiler();
CompilerParameters _CompilerParameters = new CompilerParameters();
_CompilerParameters.GenerateExecutable = false;
_CompilerParameters.GenerateInMemory = true;
_CompilerParameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
_CompilerParameters.TreatWarningsAsErrors = false;
_CompilerParameters.CompilerOptions = "/optimize";
try
{
System.CodeDom.Compiler.CompilerResults _CompilerResults = null;
_CompilerResults = _CodeCompiler.CompileAssemblyFromSource(_CompilerParameters, _SourceCode);
if (_CompilerResults.Errors.Count > 0)
{
_Errors = "";
foreach (System.CodeDom.Compiler.CompilerError CompErr in _CompilerResults.Errors)
{
_Errors += "Line number " + CompErr.Line +
", Error Number: " + CompErr.ErrorNumber +
", '" + CompErr.ErrorText + ";\r\n\r\n";
}
return false;
}
else
{
_Errors = null;
} _CompilerResults.CompiledAssembly = null;
_CompilerResults = null;
_CompilerParameters = null;
_CodeCompiler.Dispose();
GC.Collect();}catch{}

I suppose by "get rid of it" you mean "unload". Unfortunatelly (or not so) once loaded into an AppDomain, assemblies cannot be unloaded. To circumvent this, you can generate (or load, for that matter) assembly in a separate AppDomain and then destroy it as needed.

Related

c# - How to call/link a workflow on a web application from a c# program?

I have a C# (WinForms) application that can scan documents via a printer. After scanning, I will be able to enter document details on it and have a button to finalize the documents. The documents details and info will be stored in my database ABC in certain tables.
Now, I have another web application written in Java(IntelliJ) that has some button functionality to upload documents and then start a workflow and route it to another user to approve the document. I won't go into detail on the specifics. This application also connects to the same database ABC.
So now comes the tougher part, I need to link these two applications in a way that when I finalize my document
on the C# application, it has to auto trigger the workflow on the web application side. Rather than manually starting the workflow on the web application, it would just call or trigger the workflow, so I do not need to access the web application at all for the process to start.
private void FinButton_Click(object sender, EventArgs e)
{
int count = 0;
var txtBoxFields = new List<TextBox>
{
textBox1,
textBox2,
textBox3,
textBox4,
textBox5,
textBox6,
textBox7,
textBox8,
textBox9,
textBox10,
textBox11,
textBox12,
textBox13,
textBox14,
textBox15
};
var templateFields = new List<String>
{
"T1",
"T2",
"T3",
"T4",
"T5",
"T6",
"T7",
"T8",
"T9",
"T10",
"T11",
"T12",
"T13",
"T14",
"T15"
};
//long tid = 0;
//Start insert query into templatebatch table in db
var dbConnection2 = DBConnection.Instance();
dbConnection2.DatabaseName = ConfigurationManager.AppSettings["dbName"];
if (dbConnection2.IsConnect())
{
bool test = true;
for (int i = 1; i <= 15; i++)
{
var input = txtBoxFields[i - 1].Text;
var insertQuery = "INSERT INTO templateinfo(TID, THEADER, " + templateFields[i - 1] + ") VALUES(#tid, #theader,#t" + i + ")";
var insertCmd = new MySqlCommand(insertQuery, dbConnection2.Connection);
insertCmd.Parameters.AddWithValue("#tid", tid);
insertCmd.Parameters.AddWithValue("#theader", "N");
if (String.IsNullOrEmpty(input))
{
count = 1;
insertCmd.Parameters.AddWithValue("#t" + i, String.Empty);
break;
}
else
{
if (test)
{
insertCmd.Parameters.AddWithValue("#t" + i, txtBoxFields[i - 1].Text);
insertCmd.ExecuteNonQuery();
test = false;
var selectQuery = "select TINFOID from templateinfo where TID=" + tid + " and THEADER = 'N'";
var selectCmd = new MySqlCommand(selectQuery, dbConnection2.Connection);
var selectReader = selectCmd.ExecuteReader();
using (MySqlDataReader dr = selectReader)
{
while (dr.Read())
{
tinfoid = Convert.ToInt32(dr["TINFOID"]);
}
}
}
else
{
var updateQuery = "update templateinfo set " + templateFields[i - 1] + "='" + txtBoxFields[i - 1].Text + "' where TINFOID = '" + tinfoid + "' and TID=" + tid + " and THEADER='N'";
var updateCmd = new MySqlCommand(updateQuery, dbConnection2.Connection);
var updateReader = updateCmd.ExecuteReader();
using (var reader = updateReader)
{
}
}
}
}
}
if (count == 1)
{
//MessageBox.Show("Input field(s) cannot be left empty.");
}
//Finalize here
var client = new LTATImagingServiceClient();
client.Finalize(userID, tid, tinfoid, batchID);
Debug.WriteLine(userID + ", " + tid + ", " + tinfoid + ", " + batchID);
var batchName = templateView.SelectedNode.Text;
var folderPath = #"C:\temp\batches\" + mastertemplatename + #"\" + subtemplatename + #"\" + batchName + #"\";
ThumbnailLists.Items.Clear();
// var img = Image.FromFile(#"C:\temp\batch-done.png");
if (ImageBox.Image != null)
{
ImageBox.Image.Dispose();
}
ImageBox.Image = null;
try
{
using (new Impersonation(_remoteDomain, _remoteUser, _remotePassword))
{
// MessageBox.Show(_remoteUser);
// MessageBox.Show(_remotePassword);
var tPath = #"\\126.32.3.178\PantonSys\SAM\Storage\3\" + mastertemplatename + #"\" + subtemplatename + #"\" + batchName + #"\";
bool exists = System.IO.Directory.Exists(tPath);
if (!exists)
{
System.IO.Directory.CreateDirectory(tPath);
}
string[] fileList = Directory.GetFiles(folderPath, "*");
foreach (var file in fileList)
{
File.Copy(file, tPath + Path.GetFileName(file));
}
CurrentPageBox.Text = "";
NumberPageBox.Text = "";
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
MessageBox.Show(ex.Message);
}
var dbConnection = DBConnection.Instance();
dbConnection.DatabaseName = ConfigurationManager.AppSettings["dbName"];
if (dbConnection.IsConnect())
{
var deleteBatchQuery = "DELETE FROM templatebatch WHERE batchname ='" + templateView.SelectedNode.Text + "'";
var deleteBatchCmd = new MySqlCommand(deleteBatchQuery, dbConnection.Connection);
var deleteBatchReader = deleteBatchCmd.ExecuteReader();
using (var reader = deleteBatchReader)
{
while (reader.Read())
{
}
}
templateView.Nodes.Remove(templateView.SelectedNode);
Directory.Delete(folderPath, true);
MessageBox.Show("Successfully Transferred.");
foreach (var txtFields in txtBoxFields)
{
txtFields.Text = "";
txtFields.Enabled = false;
}
finButton.Visible = false;
finButton.Enabled = false;
}
bindButton.Visible = false;
}
Would this be possible to achieve or just being far-fetched?
I would appreciate any suggestions or pointers on this. Do let me know if there is anything unclear in my explanation.
EDIT:
Request URL: http://126.32.3.178:8111/process/taskmanager/start/start.jsp
Request Method: POST
Status Code: 200 OK
Remote Address: 126.32.3.178:8111
Referrer Policy: no-referrer-when-downgrade
Is there a way I could call this from the C# application?
You can send your file directly from your C# app with use of Http client. Here is code sample:
private async Task<bool> Upload(string filePath)
{
const string actionUrl = #"http://126.32.3.178:8111/process/taskmanager/start/start.jsp";
var fileName = Path.GetFileName(filePath);
var fileBytes = File.ReadAllBytes(filePath);
var fileContent = new ByteArrayContent(fileBytes);
using (var client = new HttpClient())
using (var formData = new MultipartFormDataContent())
{
formData.Add(fileContent, fileName);
var response = await client.PostAsync(actionUrl, formData);
return response.IsSuccessStatusCode;
}
}
Also, note that there maybe some sort of authentication should be performed before you can post a request.

How to save generated exe in Run-Time Compilation

I am trying to save to Desktop generated code by CSharpProvider to Desktop. How can I do that?
CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp");
string Output = "Out.exe";
Button ButtonObject = (Button)sender;
textBox2.Text = "";
System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
//Make sure we generate an EXE, not a DLL
parameters.GenerateExecutable = true;
parameters.OutputAssembly = Output;
CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, textBox1.Text);
if (results.Errors.Count > 0)
{
textBox2.ForeColor = Color.Red;
foreach (CompilerError CompErr in results.Errors)
{
textBox2.Text = textBox2.Text +
"Line number " + CompErr.Line +
", Error Number: " + CompErr.ErrorNumber +
", '" + CompErr.ErrorText + ";" +
Environment.NewLine + Environment.NewLine;
}
}
else
{
//Successful Compile
textBox2.ForeColor = Color.Blue;
textBox2.Text = "Success!";
//If we clicked run then launch our EXE
if (ButtonObject.Text == "Run") Process.Start(Output);
}
I don't want to run it just save it.
I have solved it . Changed the out.exe to c:\out.exe.

c# Retrieve multiple XML child nodes

I've managed to link up a single XElement successfully into my program though I'm not having any luck with the other two I have in place, I've tried using;
IEnumerable query = from booking in doc.Descendants("Booking")
Though I've haven't had much luck placing the values into list box.
Here's the code for function:
private void btnimport_Click(object sender, EventArgs e)
{
OpenFileDialog open = new OpenFileDialog();
open.CheckFileExists = true;
open.InitialDirectory = "#C:\\";
open.Filter = "XML Files (*.xml)|*.xml|All Files(*.*)|*.*";
open.Multiselect = false;
if (open.ShowDialog() == DialogResult.OK)
{
try
{
XDocument doc = XDocument.Load(open.FileName);
//Grabs the customer elements
var query = from booking in doc.Descendants("Booking")
select new
{
//Customer Elements
CustomerId = booking.Element("CustomerId").Value,
Title = booking.Element("Title").Value,
Firstname = booking.Element("FirstName").Value,
Lastname = booking.Element("LastName").Value,
DateofBirth = booking.Element("DateofBirth").Value,
Email = booking.Element("Email").Value,
HouseNo = booking.Element("HouseNo").Value,
Street = booking.Element("Street").Value,
Postcode = booking.Element("Postcode").Value,
Town = booking.Element("Town").Value,
County = booking.Element("County").Value,
ContactNo = booking.Element("ContactNo").Value,
//Holiday Elements
HolidayId = booking.Element("HolidayId").Value,
HotelName = booking.Element("HotelName").Value,
Location = booking.Element("Location").Value,
BookFrom = booking.Element("BookFrom").Value,
BookTo = booking.Element("BookTo").Value,
CheckInTime = booking.Element("CheckInTime").Value,
CheckOutTime = booking.Element("CheckOutTime").Value,
NoOfRoomsBooked = booking.Element("NoOfRoomsBooked").Value,
RoomType = booking.Element("RoomType").Value,
RoomServices = booking.Element("RoomServices").Value,
Parking = booking.Element("Parking").Value,
Pet = booking.Element("Pet").Value,
//TravelInfo Elements
TravelInfoId = booking.Element("TravelInfoId").Value,
TravellingFrom = booking.Element("TravellingFrom").Value,
Destination = booking.Element("Destination").Value,
Fare = booking.Element("Fare").Value,
TravelInsurance = booking.Element("TravelInsurance").Value,
InFlightMeals = booking.Element("In-FlightMeals").Value,
LuggageAllowance = booking.Element("LuggageAllowance").Value,
ExtraLuggage = booking.Element("ExtraLuggage").Value,
CarHire = booking.Element("CarHire").Value,
ReturnTransfer = booking.Element("ReturnTransfer").Value,
};
//Inputs all of the values in bookings
foreach (var booking in query)
{
//Customer values
txtCustomerId.Text = txtCustomerId.Text + booking.CustomerId;
txttitle.Text = txttitle.Text + booking.Title;
txtfname.Text = txtfname.Text + booking.Firstname;
txtlname.Text = txtlname.Text + booking.Lastname;
txtdob.Text = txtdob.Text + booking.DateofBirth;
txtemail.Text = txtemail.Text + booking.Email;
txthouseno.Text = txthouseno.Text + booking.HouseNo;
txtstreet.Text = txtstreet.Text + booking.Street;
txtpostcode.Text = txtpostcode.Text + booking.Postcode;
txttown.Text = txttown.Text + booking.Town;
txtcounty.Text = txtcounty.Text + booking.County;
txtcontactno.Text = txtcontactno.Text + booking.ContactNo;
//Holiday Values
txtHolidayId.Text = txtHolidayId.Text + booking.HolidayId;
txthname.Text = txthname.Text + booking.HotelName;
txtl.Text = txtl.Text + booking.Location;
txtbf.Text = txtbf.Text + booking.BookFrom;
txtbt.Text = txtbt.Text + booking.BookTo;
txtcit.Text = txtcit.Text + booking.CheckInTime;
txtcot.Text = txtcot.Text + booking.CheckOutTime;
txtnorb.Text = txtnorb.Text + booking.NoOfRoomsBooked;
txtrt.Text = txtrt.Text + booking.RoomType;
txtrs.Text = txtrs.Text + booking.RoomServices;
txtpark.Text = txtpark.Text + booking.Parking;
txtpet.Text = txtpet.Text + booking.Pet;
//TravelInfo Values
txtTravelInfoId.Text = txtTravelInfoId.Text + booking.TravelInfoId;
txttf.Text = txttf.Text + booking.TravellingFrom;
txtd.Text = txtd.Text + booking.Destination;
txtf.Text = txtf.Text + booking.Fare;
txtti.Text = txtti.Text + booking.TravelInsurance;
txtifi.Text = txtifi.Text + booking.InFlightMeals;
txtla.Text = txtla.Text + booking.LuggageAllowance;
txtel.Text = txtel.Text + booking.ExtraLuggage;
txtch.Text = txtch.Text + booking.CarHire;
txtrtrans.Text = txtrtrans.Text + booking.ReturnTransfer;
}
MessageBox.Show("XML has been imported");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
If anyone knows where I've gone wrong or what I need to add / change please let me know :)
Many thanks,
10gez10
You have several problems:
Firstly, your data elements are not immediate children of the booking element, there are intermediate elements <Customer>, <Holiday> and <TravelInfo>. Thus you need to do something like
var query = from booking in doc.Descendants("Booking")
let customer = booking.Element("Customer")
let holiday = booking.Element("Holiday")
let travelInfo = booking.Element("TravelInfo")
select new
{
//Customer Elements
CustomerId = customer.Element("CustomerId").Value,
Title = customer.Element("Title").Value,
HolidayId = holiday.Element("HolidayId").Value,
TravelInfoId = travelInfo.Element("TravelInfoId").Value,
}
Secondly, several elements are misspelled:
CheckOutTime should be CheckoutTime
In-FlightMeals should be InFlightMeals.
CarHire should be CareHire (yes "CareHire" is what's in the XML.)
Thus, when you do (e.g.) Element("In-FlightMeals").Value, Element() is returning null so you get a null reference exception and your code is aborted.
Thirdly, the element BookTo is completely missing, so BookTo = holiday.Element("BookTo").Value generates a null reference exception.
More generally, I do not recommend this coding approach. If any of your XML elements are missing, your query will throw an exception because element.Element("name") will be null. What's worse, Visual Studio doesn't seem to report an accurate line number on which the null reference occurs, instead giving the line number of the select new statement. And (on my version at least), it's not possible to step into the constructor for an anonymous type either. This makes debugging well-nigh impossible.
Instead, skip the intermediate anonymous type and do things in a more direct, traditional manner:
foreach (var booking in doc.Descendants("Booking"))
{
var customer = booking.Element("Customer");
var holiday = booking.Element("Holiday");
var travelInfo = booking.Element("TravelInfo");
XElement element;
if (customer != null)
{
if ((element = customer.Element("CustomerId")) != null)
txtCustomerId.Text = txtCustomerId.Text + element.Value;
}
// And so on.
}

Problems Moving Computer in Active Directory with Distinguished Name

I was able to get the account-disabling part of my code to work, but to keep our AD tree even more clean, we have a specifically created !Disabled OU. I'd like my code to be able to both disable the computer account and move it into the !Disabled OU.
Here's what I have so far:
string computerName = Environment.MachineName;
using (PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, null, "username", "password"))
{
ComputerPrincipal computer = ComputerPrincipal.FindByIdentity(domainContext, computerName);
if (computer != null)
{
try
{
computer.Enabled = false;
label3.Visible = true;
computer.Save();
label3.Text = "Computer was disabled in Active Directory." + "\n";
try
{
string LdapDomain = "prefix.domain.suffix";
string distinguishedName = string.Empty;
string connectionPrefix = "LDAP://" + LdapDomain;
DirectoryEntry entry = new DirectoryEntry(connectionPrefix);
DirectorySearcher mySearcher = new DirectorySearcher(entry);
mySearcher.Filter = "(&(objectClass=computer)(|(cn=" + computerName + ")(dn=" + computerName + ")))";
SearchResult result = mySearcher.FindOne();
if (result == null)
{
label3.Text += ("Unable to locate the distinguishedName for the object " + computerName + " in the " + LdapDomain + " domain." + "\n");
}
else if (result != null)
{
DirectoryEntry directoryObject = result.GetDirectoryEntry();
distinguishedName = "LDAP://" + directoryObject.Properties["distinguishedName"].Value;
label3.Text += ("Distinguished name is " + distinguishedName + "\n");
string newLocation = "OU=!Disabled,DC=prefix,DC=domain,DC=suffix";
DirectoryEntry nLocation = new DirectoryEntry("LDAP://" + newLocation);
string newName = directoryObject.Name;
//directoryObject.MoveTo(nLocation, newName);
DirectoryEntry moveParent = new DirectoryEntry(newLocation);
directoryObject.MoveTo(moveParent); //Comes from Microsoft example, as prior may have been possible cause of errors.
label3.Text += ("Successfully moved computer to the !Disabled OU");
nLocation.Close();
directoryObject.Close();
entry.Close();
entry.Dispose();
mySearcher.Dispose();
}
else
{
label3.Text += ("Unexpected error in moving computer.");
}
button1.Visible = true;
}
catch (Exception p)
{
label3.Text += ("Failed to move computer with exception " + p);
button1.Visible = true;
}
/*
public void Move(string objectLocation, string newLocation)
{
//For brevity, removed existence checks
DirectoryEntry eLocation = new DirectoryEntry("LDAP://" + objectLocation);
DirectoryEntry nLocation = new DirectoryEntry("LDAP://" + newLocation);
string newName = eLocation.Name;
eLocation.MoveTo(nLocation, newName);
nLocation.Close();
eLocation.Close();
}
*/
}
catch (Exception x)
{
label3.Visible = true;
label3.Text = "Unable to disable computer with exception " + x;
button1.Visible = true;
}
}
else if (computer == null)
{
label3.Visible = true;
label3.Text = "Computer was not found in Active Directory.";
button1.Visible = true;
}
else
{
label3.Visible = true;
label3.Text = "Unexpected error in computer search.";
button1.Visible = true;
}
}
The display aspects are pretty sloppy, but it's a quick and dirty Windows Form that displays all the things that are going on. The problem I'm having is that even though I have the distinguished name and can get a DirectoryEntry object from the search, when I call the MoveTo() method I get an error about the object not existing or not being found. Could someone point me in the right direction here?
I've considered binding to the two different OU's and using the DirectoryEntry.Children.Add() and DirectoryEntry.Children.Remove() methods as a workaround, but that doesn't fix the problem I'm having traversing AD.

Add additional References when compliling code at runtime

I found this program ( http://support.microsoft.com/kb/304655 ) where i compile the code during runtime, It works for code that uses the reference,
using System;
Following is the the code for the program that compiles code during runtime,
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
ICodeCompiler icc = codeProvider.CreateCompiler();
string Output = "Out.exe";
Button ButtonObject = (Button)sender;
textBox2.Text = "";
System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
//Make sure we generate an EXE, not a DLL
parameters.GenerateExecutable = true;
parameters.OutputAssembly = Output;
CompilerResults results = icc.CompileAssemblyFromSource(parameters, textBox1.Text);
if (results.Errors.Count > 0)
{
textBox2.ForeColor = Color.Red;
foreach (CompilerError CompErr in results.Errors)
{
textBox2.Text = textBox2.Text +
"Line number " + CompErr.Line +
", Error Number: " + CompErr.ErrorNumber +
", '" + CompErr.ErrorText + ";" +
Environment.NewLine + Environment.NewLine;
}
}
else
{
//Successful Compile
textBox2.ForeColor = Color.Blue;
textBox2.Text = "Success!";
//If we clicked run then launch our EXE
if (ButtonObject.Text == "Run") Process.Start(Output);
}
And Following is the code i need to compile at runtime,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Text.RegularExpressions;
using Newtonsoft.Json.Linq;
namespace Tsubame
{
class Program
{
static void Main(string[] args)
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(#"url");
// Create Client
WebClient client = new WebClient();
// Assign Credentials
client.Credentials = new NetworkCredential("user", "pass");
//Grab Data
var data = client.DownloadString(#"url");
JObject o = JObject.Parse(data);
string getFristRow = Convert.ToString(o["Body"][0]["RowId"]);
string encaplulateStart = "\\\"";
string encaplulateEnd = "\\\":";
List<string> _matches = new List<string>();
_matches = Regex.Matches(getFristRow, #"(?<=" + encaplulateStart + ").*(?=" + encaplulateEnd + ")")
.Cast<Match>()
.Select(m => m.Value)
.ToList();
foreach (string head in _matches)
{
Console.WriteLine(head);
}
Console.ReadLine();
}
}
}
But when I input this gives the error code,
Error Number: CS0234
For the references other than System. May I please know how to add additional references during runtime so that it can compile sucessfully :) Thank you very much :)
You need to add the references in CompilerParameters using CompilerParameters.ReferencedAssemblies:
var parameters = CompilerParameters
{
GenerateExecutable = true,
OutputAssembly = Output,
ReferencedAssemblies = {
"System.dll",
"System.Core.dll",
// etc
}
};
(Of course you don't have to use object initializer syntax to set this up, but it makes it neater IMO.)

Categories