Compile in C using a Windows Forms Application - c#

I'm creating a compiler App in C#, using Visual Studio 2010.
The goal of this program is to compile a code written in either C# or C at runtime and return the results of the compilation.
I have done the C# part, but the C part is the one I have problems. For this one, I've tried to use the Visual Studio Command Prompt. The way I'm coding this part is like this:
Create a .c file in C:\ using File.Create.
Using a Process, open the Visual Studio Command Prompt and execute the compilation.
Capture the output to return it as the compilation results.
However, it doesn't work. It throws and Win32 exception, but I don't really know why.
I've heard something about using gcc. But I thought about using the Visual Studio Command Prompt as a possible solution.
EDIT: I figured out the steps to do it (I think). But the Win32 exception appears when the program tries to do the process.Start() line. I guess this might be a permissions problem, but I don't really know.

A friend of mine worked on something similar, and helped me to solve this problem.
On steps 2 and 3, I was trying to write the input and read the output using simply the process standard input and output, and also, I was trying to use an .lnk to run the Command Prompt. All those things caused the error.
The solution was:
Create two batch files, one to start up the Command Prompt and the other to compile the .c file (those were created outside the program's code).
(On runtime) Create the .c file, using the code written. If file exists, delete it and create a new one.
Start the process with cmd.exe.
Run the batch files, using a Stream Writer to write them in the cmd.exe.
Retrieve the output using a Stream Reader.
Fortunately, this worked! Code ended like this:
string CompileC (string code)
{
string path = #"C:\sample.c";
string results = "";
try
{
if (File.Exists(path))
File.Delete(path);
using (FileStream fs = File.Create(path))
{
byte[] codeText = new UTF8Encoding(true).GetBytes(code);
fs.Write(codeText, 0, codeText.Length);
}
Process process = new Process();
process.StartInfo.FileName = #"C:\Windows\system32\cmd.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
using (StreamWriter sw = process.StandardInput)
{
if (sw.BaseStream.CanWrite)
{
//This batch starts up the Visual Studio Command Prompt.
sw.WriteLine(#"C:\Startup.bat");
//This batch does the compilation, once the Command Prompt
//is running, using the 'cl' command.
sw.WriteLine(#"C:\Compile.bat");
}
}
using (StreamReader sr = process.StandardOutput)
{
if (sr.BaseStream.CanRead)
results = sr.ReadToEnd();
}
}
catch (Exception ex) { MessageBox.Show(ex.ToString()); }
return results;
}

Related

Executing python script from C# code mysteriously halts

I currently have a set up in which I am using C# to execute a Python script. It also gets whatever the script would normally output in a command line returned back to be used in my application. (Except for error messages for some reason) The problem is that the script execution mysteriously comes to a halt when it reaches a line to open a .json file. I won't paste the script as it is fairly large, but I pinpointed the line it stops at by adding logs. This is the line:
featuresBody = open("features.json")
I have verified that the Python script makes it passed this point when I execute it in a regular command line, but halts here when executed from C#. Here is my C# code that runs the script:
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = #"C:\Python27\python.exe";
start.Arguments = ltrDirectory + "/train_and_upload_demo_model.py -c " + ltrDirectory + "/config.json";
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
System.Diagnostics.Debug.WriteLine(result);
}
}
This logic is picking up the script and running it in the beginning just fine, but just fails at that one line I noted above. I cannot get details as to what is wrong as error messages don't get returned to C# for whatever reason and I cannot replicate the issue in a command line because the same command works there.
Any ideas why opening a .json file works fine normally, but not when executed from C#...?

Shell Script File(.sh) does not run from c# core on linux

I am trying to run ".sh" file from c# core application.But it doesn't seem to be running properly.Here is my scenario.
I am working on .Net core project which is hosted on Linux environment.We are trying to create "PDF" in our project for which we have used "Apache FOP".
Here i have created one "shell script" file "transform.sh" which internally calls "fop" with required parameters.Since developement is being done on windows machine we tested the same usinf "batch" file i.e. "transform.bat",but since we cannot use the "batch" file on linux enviornment we have created shell script file "transform.sh"
Following is the code from"transform.sh"
./fop -xml $1 -xsl $2 -pdf $3
Following is C# code from which i am calling the "shell script file
var process = new Process
{
StartInfo = new ProcessStartInfo
{
UseShellExecute = false,
RedirectStandardOutput = true,
Arguments = string.Format("{0} {1} {2}", XML_filename, XSL_filename, output)
}
};
process.StartInfo.FileName = "Path to shell script file";
process.Start();
process.WaitForExit();
Above code doesnot give any error but it also does not create the pdf file.If i directly run the shell script file from "Terminal" it works fine and create pdf file.
./transform.sh "/home/ubuntu/psa//PdfGeneration/ApacheFolder/XMLFolder/test.xml" "/home/ubuntu/psa/PdfGeneration/ApacheFolder/XSLTFolder/Certificate.xsl" "/home/ubuntu/psa/PdfGeneration/ApacheFolder/PDFFolder/t444t.pdf"
Please let me know if there is something wrong i am doing?How can i make the sheel script run on linux through C# core application.
Thanks.
I was able to solve the issue,just thought that i should put my solution here so that it may help others in future...
As mentioned in Question i was not able to generate the PDF file through shell script on linux machine.After debugging as suggested by "#JNevill" I came to understand that the shell script file was not getting called from .net process itself.
So my first task was to make the shell script file called through .Net Process.
After lots of searching through Net and trying out different solutions i got solution at How to perform command in terminal using C#(Mono).
So changed my code of calling the process as follow,
var command = "sh";
var myBatchFile = //Path to shell script file
var argss = $"{myBatchFile} {xmlPath} {xsltPath} {pdfPath}"; //this would become "/home/ubuntu/psa/PdfGeneration/ApacheFolder/ApacheFOP/transform.sh /home/ubuntu/psa/PdfGeneration/ApacheFolder/XMLFolder/test.xml /home/ubuntu/psa/PdfGeneration/ApacheFolder/XSLTFolder/Certificate.xsl /home/ubuntu/psa/PdfGeneration/ApacheFolder/PDFFolder/test.pdf"
var processInfo = new ProcessStartInfo();
processInfo.UseShellExecute = false;
processInfo.FileName = command; // 'sh' for bash
processInfo.Arguments = argss; // The Script name
process = Process.Start(processInfo); // Start that process.
var outPut = process.StandardOutput.ReadToEnd();
process.WaitForExit();
After changing the code ,the ".sh" file got executed and i was able to generate the PDF file.
Also script of the ".sh" file i.e. (transform.sh) which was calling Apache FOP file i.e. "FOP.sh" also needed to be changed.
Initially code was
./fop -xml $1 -xsl $2 -pdf $3
Which i changed as follow,(Change was to give full path of the FOP file)
/home/ubuntu/psa/PdfGeneration/ApacheFolder/ApacheFOP/fop -xml $1 -xsl $2 -pdf $3
Late answer, but for me, it worked just by setting the RedirectStandardOutput to true and changing the FileName property like this:
processInfo.FileName = #"C:\Program Files\Git\git-bash.exe";
processInfo.RedirectStandardOutput = true;

How to zip a Folder using SSIS 2008 without using any third party s/w?

I have a scenario where i would like to compress my folder due to presence of large number of files present in them using SSIS 2008. Consider it like i have one Source Folder and one Target Folder and while moving files from "SRC" to "TGT" the folder must be compressed in destination.Now feasible option for doing this i think is SSIS Script task ,since I cannot use Execute Process task due to restriction of using any third party software like 7z/Winrar etc.But i am not able to implement this even after using SSIS Script Component.Tried many online solutions but it did not work.How can i implement such thing using SSIS 2008?
You can use the ZipPackage class if you are targeting .Net 3 and above. Complete example here:
https://msdn.microsoft.com/en-us/library/system.io.packaging.zippackage.aspx
There is also a ZipArchive class, example here:
https://msdn.microsoft.com/en-us/library/system.io.compression.ziparchive(v=vs.110).aspx
I did this exercise , I created a Script Task to perform compression of a folder by using the compression provided by Windows;
the folder name can dynamically change.
In this way it is not necessary to use third party software like 7z/Winrar etc..
You need to provide to the Script Task the folder to be zipped and the name of the compressed folder as ReadOnlyVariables (to be added in the tab ReadOnlyVariables)
These two variables must be defined in the Variables tab (String type) of the package and can be changed dynamically through a cycle (eg. for each)
I use these two variables:
sFolderCompressed - the folder '.zip' that you want to obtain eg. \\XX.XX.XX.XX\C$\.....\folderCompressed
sFolderSource - the source folder containing the files affected eg. \\XX.XX.XX.XX\C$\.....\folderSource
(*)
The script is made using c#, choose Script Language: Microsoft Visual C# 2008
This is the code to be added in the Main method:
public void Main()
{
// TODO: Add your code here
try
{
// variables used in process
string l_sFolderCompressed = (string)Dts.Variables["User::sFolderCompressed"].Value;
string l_sFolderSource = (string)Dts.Variables["User::sFolderSource"].Value;
string l_sCommand = "zip -j " + l_sFolderCompressed + " " + l_sFolderSource + "/*";
// create the ProcessStartInfo using "cmd" as the program to be run,
// and "/C " as the parameters.
// Incidentally, /C tells cmd that we want it to execute the command that follows,
// and then exit.
System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd", "/C " + l_sCommand);
// The following commands are needed to redirect the standard output.
// This means that it will be redirected to the Process.StandardOutput StreamReader.
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
// Do not create the black window.
procStartInfo.CreateNoWindow = true;
// Now we create a process, assign its ProcessStartInfo and start it
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
// Get the output into a string
string result = proc.StandardOutput.ReadToEnd();
// Possibly display the command output.
}
catch (Exception objException)
{
Dts.TaskResult = (int)ScriptResults.Failure;
// Log the exception
}
Dts.TaskResult = (int)ScriptResults.Success;
}
You can also manage a single file
"cmd", "/C zip -j c:\\...\file.zip c:\\..\file.txt");
I hope can help

OAuth 2.0 inconsistent errors when using BigQuery commandline tool

I'm using BigQuery's command-line tool to load data into BigQuery.
I'm running the bq tool through a C# program using the following method:
private void RunShellCmd(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo
{
FileName = cmd,
Arguments = args,
UseShellExecute = false,
RedirectStandardOutput = true
};
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
if (OnMessage != null)
{
OnMessage(result);
}
}
}
}
Where cmd is the path for the bq script tool and args are:
load --nosync --credential_file=_CRED_PATH_ --source_format=NEWLINE_DELIMITED_JSON --project_id=_PROJECT_ID_ _TABLE_URI_ _DATA_FILE_
When performing the exact command from shell, it works perfectly.
However, through the C# program, I'm getting the following output:
Welcome to BigQuery! This script will walk you through the process of initializing your .bigqueryrc configuration file.
First, we need to set up your credentials if they do not already exist.
******************************************************************
** No OAuth2 credentials found, beginning authorization process **
******************************************************************
Go to the following link in your browser:
https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fbigquery&redirect_uri=...
Enter verification code: You have encountered a bug in the BigQuery CLI. Google engineers monitor and answer questions on Stack Overflow, with the tag google-bigquery: http://stackoverflow.com/questions/ask?tags=google-bigquery Please include a brief description of the steps that led to this issue, as well as the following information:
========================================
== Platform == CPython:2.7.5:Windows-2008ServerR2-6.1.7601-SP1
== bq version == v2.0.16
== Command line == ['C:\\Python27\\Scripts\\bq-script.py', 'load', '--nosync', '--credential_file=C:\\Users\\Administrator\\.bigquery.v2.token', '--source_format=NEWLINE_DELIMITED_JSON', '--project_id=_PROJECT_ID_',
>'_TABLE_URI_', '_DATA_FILE_PATH_']
== UTC timestamp == 2013-10-20 05:52:59
== Error trace == File "build\bdist.win32\egg\bq.py", line 783, in RunSafely
return_value = self.RunWithArgs(*args, **kwds) File "build\bdist.win32\egg\bq.py", line 2082, in RunWithArgs
client = Client.Get() File "build\bdist.win32\egg\bq.py", line 604, in Get
cls.client = Client.Create() File "build\bdist.win32\egg\bq.py", line 584, in Create
credentials = _GetCredentialsFromFlags() File "build\bdist.win32\egg\bq.py", line 390, in _GetCredentialsFromFlags
credentials = credentials_getter(storage) File "build\bdist.win32\egg\bq.py", line 330, in
_GetCredentialsFromOAuthFlow
credentials = oauth2client.tools.run(flow, storage) File "build\bdist.win32\egg\oauth2client\util.py", line 132, in positional_wrapper
return wrapped(*args, **kwargs) File "build\bdist.win32\egg\oauth2client\old_run.py", line 149, in run
code = raw_input('Enter verification code: ').strip()
========================================
Unexpected exception in init operation: EOF when reading a line
Successfully started load _TABLE_URI_
The odd thing is that the command actually works and loads the data correctly (As also proven by the final output line).
But for some reason, it is preceded by an OAUTH 2.0 error.
Has anyone encountered something like this before?
Any idea what might cause it?
Thanks!
Why are you calling the bq.py tool from c# rather than using the C# client?
The c# client is available here:
https://developers.google.com/api-client-library/dotnet/apis/#BigQuery_API
and the ndocs are here:
https://developers.google.com/resources/api-libraries/documentation/bigquery/v2/csharp/latest/annotated.html
If you don't want to / can't use the C# client, my guess as to what is happening is that bq is having trouble writing out a credential file (or reading a credential file). Possibly this is due to a windows path issue ('/' vs '\') or possibly the path it tries to write to or read-from is inaccessible. (or possibly the path it writes to doesn't match the path it tries to read from the next time).

Getting output from one executable in an other one

I'm currently trying to get the output of an executable console-app into an other one. To be exact, a little overview of what I'm trying to do:
I have one executable which I cannot edit and neither see it's code. It writes some (quite a bunch to be honest) lines into the console when executed.
Now I want to write another executable that starts the one above and reads the things it writes.
Seems simple to me, so I started coding but ended up with an error message saying that StandardOut has not been redirected or the process hasn't started yet.
I tried it using this kinda structure (C#):
Process MyApp = Process.Start(#"C:\some\dirs\foo.exe", "someargs");
MyApp.Start();
StreamReader _Out = MyApp.StandardOutput;
string _Line = "";
while ((_Line = _Out.ReadLine()) != null)
Console.WriteLine("Read: " + _Line);
MyApp.Close();
I can open the executable and it also does open the one inside, but as soon as it comes to reading the returned values, the app crashes.
What am I doing wrong?!
Take a look at the documentation for the Process.StandardOutput property. You will need to set a boolean indicating that you want the stream redirected as well as disabling shell execute.
Note from the documentation:
To use StandardOutput, you must set ProcessStartInfo..::.UseShellExecute to false, and you must set ProcessStartInfo..::.RedirectStandardOutput to true. Otherwise, reading from the StandardOutput stream throws an exception
You would need to change your code a little bit to adjust for the changes:
Process myApp = new Process(#"C:\some\dirs\foo.exe", "someargs");
myApp.StartInfo.UseShellExecute = false;
myApp.StartInfo.RedirectStandardOutput = false;
myApp.Start();
string output = myApp.StandardOutput.ReadToEnd();
p.WaitForExit();
you could try setting processStartInfo.RedirectStandardOutput = true;
As noted above, you can use RedirectStandardOutput as here.
Another, dirtier way is something like
using (Process child = Process.Start
("cmd", #"/c C:\some\dirs\foo.exe someargs > somefilename"))
{
exeProcess.WaitForExit();
}
And then read its output from somefilename

Categories