Converting XSD into .cs class - c#

I know this may seem to be a duplicated question but I highly doubt it.
I am currently making a Windows Form application where the user can select an XSD file using the OpenFileDialog
Once the XSD is uploaded/selected I want it to create a .cs file from it using the default developer XSD tool.
But for some reason, it just opens the selected XSD file in notepad(?)
I've tried to comment the code to give it some sense.
//Filter only .xsd files
ofd.Filter = "XSD|*.xsd";
if (ofd.ShowDialog() == DialogResult.OK)
{
//Read file name
string File = ofd.FileName;
string z = ofd.InitialDirectory;
//Start making commands for in the CMD
//Change directory to the folder where the Dev Command prompt is located
string changeDirectory = #"cd C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\";
//Open the Dev CMD
string bat = "VsDevCmd";
//Change folder to our test folder
string cd = #"cd C:\Users\Pierre\Desktop\testxsd";
//execute xsd /c *selected file* /c is used to create the .cs file.
string command = #"xsd /c " + File;
//Combine the commands into 1 line.
string x = cd + "&" + command;
string xyz = changeDirectory + "&" + bat + "&" + x;
//print the outcome -> When I copy paste this into CMD the .cs file is generated
Console.WriteLine(xyz);
ProcessStartInfo oInfo = new ProcessStartInfo(Environment.ExpandEnvironmentVariables(#"C:\WINDOWS\system32\cmd.exe"), xyz);
oInfo.UseShellExecute = false;
oInfo.ErrorDialog = false;
oInfo.CreateNoWindow = true;
oInfo.RedirectStandardOutput = true;
try
{
Process p = System.Diagnostics.Process.Start(oInfo);
System.IO.StreamReader oReader2 = p.StandardOutput;
string sRes = oReader2.ReadToEnd();
oReader2.Close();
// sRes now contains the output from xsd.exe
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
So, as you can see in the comments, when I copy paste the console.writeline(xyz) into CMD it got properly executed and the .cs file is generated as it should.
However, when I just launch this code it opens the selected xsd in notepad.
Literally no idea what could be wrong

You are kind of taking the very long panoramic route when there is actually a very quick one... As #PatrickHofman stated in the comments use xsd directly...
To do this, open the Visual Studio command prompt, and write where xsd to find exact path of xsd executable.
Then start a process using xsd from the path you found and the various options ie. /c and filename.
using System.Diagnostics;
...
FileInfo fi = new FileInfo(ofd.FileName);
Process process = new Process();
process.StartInfo.FileName = xsdPath;
process.StartInfo.Arguments = "/c " + fi.FullName;
process.StartInfo.WorkingDirectory = fi.DirectoryName;
process.Start();
//wait for exit if needed...
process.WaitForExit();
If for some reason this is not working, capture the output from the command by doing this before process.Start():
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.OutputDataReceived +=
(sender, args) => Console.WriteLine("received output: {0}", args.Data);
process.BeginOutputReadLine();

I think you should use the XmlSchemaClassGenerator package for this (Nuget). That way you wont have to do all the process juggling yourself.
Example from GitHub readme:
var generator = new Generator
{
OutputFolder = outputFolder,
Log = s => Console.Out.WriteLine(s),
GenerateNullables = true,
NamespaceProvider = new Dictionary<NamespaceKey, string>
{
{ new NamespaceKey("http://wadl.dev.java.net/2009/02"), "Wadl" }
}
.ToNamespaceProvider(new GeneratorConfiguration { NamespacePrefix = "Wadl" }.NamespaceProvider.GenerateNamespace)
};
generator.Generate(files);

Related

Fail to execute a specific cmd batch file in C#

I'm using Process to execute a batch file which will generate certificate file.
The code works great when I execute other file (which contains openssl command). But when I execute a file which contains keytool command, it executed, but no file was generated.
I've:
Set UseShellExecute true.
Set WaitForExit(-1) and find the return was true, so it did executed.
I clicked that batch file manually, and the file generates right away, so the command was fine :(
BTW I'm using .Net Core MVC.
I can't find any error code anywhere, so I'm at my wits' end now.
Does anyone has a clue? Any help would be very appriciated!
success code(openssl):
I generate a p12 file (a certificate format) in that folder first, and it works fine.
private string Gen_P12(string domain, string pwd)
{
//generate folder
string folder = #"D:\Temp\";
if (!Directory.Exists(folder))
Directory.CreateDirectory(folder);
//generate bat(p12)
string bat = "openssl.exe pkcs12 -export -inkey " + domain + ".key -in " + domain + ".cer -out " + domain + ".p12 -password pass:" + pwd +"\r\n";
//download in folder
var path = Path.Combine(folder, domain + "_P12.bat");
using (FileStream fs = System.IO.File.Create(path))
{
byte[] content = new UTF8Encoding(true).GetBytes(bat);
fs.Write(content, 0, content.Length);
}
Thread.Sleep(500);
//execute
ProcessStartInfo myBat = new ProcessStartInfo();
string name = domain + "_P12.bat";
myBat.FileName = name;
myBat.WorkingDirectory = folder;
myBat.UseShellExecute = true;
//Process.Start(myBat);
Process p = Process.Start(myBat);
p.WaitForExit(-1);
return folder;
}
fail code(keytool):
Trying to use that P12 file and keytool command to generate a keystore (also a certificate format) but fail.
private string Gen_KS(string domain, string folder, string CA_domain, byte[] cer, string pwd)
{
//generate bat
string bat = "keytool -importkeystore -srckeystore " + domain + ".p12 -srcstoretype PKCS12 -srcstorepass " + pwd + " -destkeystore " + domain + ".keystore -storepass " + pwd + "\r\n";
var path = Path.Combine(folder, domain + "_KS.bat");
using (FileStream fs = System.IO.File.Create(path))
{
byte[] content = new UTF8Encoding(true).GetBytes(bat);
fs.Write(content, 0, content.Length);
}
Thread.Sleep(700);
//execute
ProcessStartInfo myBat = new ProcessStartInfo();
myBat.WorkingDirectory = folder;
string name = domain + "_KS.bat";
myBat.FileName = name;
myBat.UseShellExecute = true;
Process p = Process.Start(myBat);
var a = p.WaitForExit(-1);
string route = folder + domain + ".keystore";
return route;
}
Thanks!
Thanks to #user9938, I solved the problem!
1. Brief conclusion:
I need to process the bat as administrator.
(And I still don't get why only do the keytool command needs administrator rights)
2. Find the errors: (How to apply StanderError when UseShellExecute=true)
In fact we don't have to set it true to execute commands.
Try this (replace execute section):
Process process = new Process();
try
{
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.FileName = "cmd.exe";
process.Start();
process.StandardInput.WriteLine(bat); //command string, not the bat file
process.StandardInput.AutoFlush = true;
process.StandardInput.WriteLine("exit");
StreamReader reader = process.StandardError;
string curLine = reader.ReadLine();
reader.Close();
process.WaitForExit();
process.Close();
}catch (Exception e){}
Check the value of curLine through Breakpoints, the error message was: "'keytool' is not recognized as an internal or external command, operable program or batch file".
3. How to solve it:
Just set the Verb attribute as "runas".
//execute
ProcessStartInfo myBat = new ProcessStartInfo();
myBat.WorkingDirectory = folder;
string name = domain + "_KS.bat";
myBat.Verb = "runas";
myBat.FileName = name;
myBat.UseShellExecute = true;
Process p = Process.Start(myBat);
var a = p.WaitForExit(-1);
Done! Thank you user9938<3

Passing parameters to exe from ini file

I'm writing a program to launch a project.
Please tell me how to transfer parameters from such an ini file to exe?
[Data]
User = "Test"
UID = 1234
[Path]
Dir = E:\Test
Exe = test.exe
So I try to assign them
process.StartInfo.FileName = BasePath + "\\Loader.exe";
process.StartInfo.Arguments = Resources.Start;
process.StartInfo.WorkingDirectory = BasePath;
Please tell me how to implement this?
The ini file must be transferred, it does not accept a simple line. Or I am doing something wrong.
If I understand you well, this code should work
(replace "Loader.exe" and "inifile.ini" with proper names of your files):
ProcessStartInfo psi = new ProcessStartInfo(BasePath + "\\Loader.exe");
psi.Arguments = BasePath + "\\inifile.ini";
psi.WorkingDirectory = BasePath;
try
{
Process p = Process.Start(psi);
}
catch (Exception ex)
{
MessageBox.Show("Error:\n" + ex.InnerException, "Run Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}

Run multiple SQL scripts through batch file from C#

I am writing code that executes SQL scripts from different folders through a batch file. There are many folders on the U drive, and in each folder, there are 23 SQL scripts. I have to execute all of these scripts from all folders.
Folders can be more or less, but there are always 23 scripts in each folder. I am getting an error
The syntax of the command is incorrect
The code below has two parts first to create batch files, second to execute the SQL scripts thorough those created batch files. Please help me - where am I wrong in executing scripts i.e 2nd part of code?
Creating the batch files:
string file = #"U:\TDScripts";
string y = File.ReadAllText(#"U:\scriptexe.txt");
foreach (string name in Directory.GetDirectories(file))
{
var letter = string.Join("_", name.Split('_').Take(2));
var x = letter.ToUpper();
Console.WriteLine(Path.GetFileNameWithoutExtension(name));
string s = name;
StreamWriter sw = new StreamWriter(File.Create(name + ".bat"));
sw.WriteLine(y.Replace("Filename", x)
.Replace("File", letter)
.Replace("/path", file)
.Replace("{folder}", s)
.Replace(#"U:\TDScripts\", "")
.Replace(#"U:\TDSCRIPTS\", "_")
.Replace("/", #"\")
.Replace("{", "")
.Replace("}", "")
.Replace(#"\path", file));
sw.Close();
Executing the SQL scripts:
int exitCode;
ProcessStartInfo processInfo;
Process process;
processInfo = new ProcessStartInfo("cmd.exe", "/c" + s);
processInfo.UseShellExecute = false;
processInfo.WorkingDirectory = s;
process = Process.Start(processInfo);
process.WaitForExit();
exitCode = process.ExitCode;
Console.WriteLine("ExitCode: " + exitCode.ToString(), "ExecuteCommand" + "\r\n\r\n\r\n");
process.Close();
if (!exitCode.Equals(0))
{
break;
}

Run Python 2.7 sript from C# with command line params

How do I run this python 2.7 code from C# (file name is myPythonScript.py):
import argparse
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument(
'-sd', '-start_date', help='start date to download data')
parser.add_argument(
'-ed', '-end_date', help='end date to download data')
args = parser.parse_args()
#print(args.accumulate(args.start_date))
print(args.sd, args.ed)
Above code only takes two dates as command line params and shows it to the user. I want to run it as a process from C#.
When I use this C# code it runs script without params well. But when I add params it can`t find python file. Why? How to resolve this?
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = #"C:\Anaconda2\python.exe";
// path to my python script
string appEXE = AppDomain.CurrentDomain.BaseDirectory;
// this scripts runs without params
python_script_name = #"myPythonScript.py -sd 01/01/2015 -ed 05/09/2017";
startInfo.Arguments="\""+appEXE+ "Python\\"+ python_script_name + "\"";
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardError = true;
using (Process process = Process.Start(startInfo))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
//MessageBox.Show("Normal results"+result);
Debug.WriteLine(result);
}
process.WaitForExit();
// This will show error: no such file or directory
MessageBox.Show("Errors"+process.StandardError.ReadToEnd());
GC.Collect();
Try these lines out:
string scriptPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Python", "myPythonScript.py")
startInfo.Arguments = "\"" + scriptPath + "\"" + " -sd 01/01/2015 -ed 05/09/2017"
I think you had an issue with quotation marks.

How to call ffmpeg.exe to convert audio files on Windows Azure?

I run a Web Role on Windows Azure to receive AAC audio files (uploaded by base64 string) and store them into blob. it works fine by now.
Next, I also have to convert them into MP3 and store the MP3s into blob too. I decided to use something like ffmpeg.exe -i path.aac path.mp3.
The problems are that:
How to call external ffmpeg.exe inside a web service of a web role?
what would be the path?
Please help me if you know. Thank you in advance.
I suggest that you use a Local Storage Resource for your webrole where you can download the AAC files from the blob storage, and have them converted to MP3. Then upload back to blob storage.
Side note is that you can also use the Path.GetTempFileName() to get a temporary file name for your AAC / MP3 files, but I don't encourage to do so (even if I've done it before).
As for the actuall ffmpeg running, you might want to browse the code for AzureVideoConv, which I've built some time ago. You will find a lot of useful code there.
Here is a sample of the actual ffmpeg call (note that I download the exe from a blob storage, to avoid bloating my azure package with external exe files, and to easily update the ffmpeg.exe when required):
internal void ConvertFile(string inputFileName, Guid taskID)
{
string tmpName = string.Format(
"{0}\\{1}.flv",
Path.GetTempPath(), inputFileName.Substring(inputFileName.LastIndexOf("\\")+1));
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = this._processorExecutable;
psi.Arguments = string.Format(#"-i ""{0}"" -y ""{1}""", inputFileName, tmpName);
psi.CreateNoWindow = true;
psi.ErrorDialog = false;
psi.UseShellExecute = false;
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.RedirectStandardOutput = true;
psi.RedirectStandardInput = false;
psi.RedirectStandardError = true;
try
{
// Start the process with the info we specified.
// Call WaitForExit and then the using statement will close.
using (Process exeProcess = Process.Start(psi))
{
exeProcess.PriorityClass = ProcessPriorityClass.High;
string outString = string.Empty;
// use ansynchronous reading for at least one of the streams
// to avoid deadlock
exeProcess.OutputDataReceived += (s, e) => {
outString += e.Data;
};
exeProcess.BeginOutputReadLine();
// now read the StandardError stream to the end
// this will cause our main thread to wait for the
// stream to close (which is when ffmpeg quits)
string errString = exeProcess.StandardError.ReadToEnd();
Trace.WriteLine(outString);
Trace.TraceError(errString);
byte[] fileBytes = File.ReadAllBytes(tmpName);
if (fileBytes.Length > 0)
{
this._sSystem.SaveOutputFile(
fileBytes,
tmpName.Substring(tmpName.LastIndexOf("\\")+1),
taskID
);
}
}
}
catch (Exception e)
{
Trace.TraceError(e.Message);
}
}
NOTE the last check in of the project is using Windows Azure SDK 1.3
Thank you a lot #astaykov. You did a good job. Though It's not specific for my case(I need a specific piece of code instead of a whole large project), but it really inspired me. For specifying into my case, I am going to answer this question by my own - note that I did this based on #astaykov's code with somewhere directly copy&paste.
Firstly, configure the role with a Local Storage Resource. Then get its path by these code:
LocalResource converter_path =
RoleEnvironment.GetLocalResource("AudioConvertSpace");
string rootPathName = converter_path.RootPath;
get the path of ffmpeg.exe, xxx.aac and xxx.mp3 in the local storage:
string aac_path = rootPathName + "\\" + "fmwa-" + guidguid + ".aac";
string mp3_path = rootPathName + "\\" + "fmwa-" + guidguid + ".mp3";
string exe_path = rootPathName + "\\" + "ffmpeg.exe";
write the .aac file to local storage:
System.IO.File.WriteAllBytes(aac_path, decoded_audio_byte_array);
keep in mind that the local storage is not guaranteed to be stable or durable, so check the existence of the ffmpeg.exe -- if it doesn't exist, download it from blob.
if (System.IO.File.Exists(exe_path) == false)
{
var exeblob = _BlobContainer.GetBlobReference("ffmpeg.exe");
exeblob.DownloadToFile(exe_path, null);
}
initial and run the ffmpeg.exe process:
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = exe_path;
psi.Arguments = string.Format(#"-i ""{0}"" -y ""{1}""",
aac_path, mp3_path);
psi.CreateNoWindow = true;
psi.ErrorDialog = false;
psi.UseShellExecute = false;
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.RedirectStandardOutput = true;
psi.RedirectStandardInput = false;
psi.RedirectStandardError = true;
Process exeProcess = Process.Start(psi);
exeProcess.PriorityClass = ProcessPriorityClass.High;
string outString = string.Empty;
exeProcess.OutputDataReceived += (s, e) => {
outString += e.Data;
};
exeProcess.BeginOutputReadLine();
string errString = exeProcess.StandardError.ReadToEnd();
Trace.WriteLine(outString);
Trace.TraceError(errString);
exeProcess.WaitForExit();
upload the output of ffmpeg.exe into the blob storage:
byte[] mp3_audio_byte_array = System.IO.File.ReadAllBytes(mp3_path);
var mp3blob = _BlobContainer.GetBlobReference("fmwa-"+guidguid+".mp3");
mp3blob.Properties.ContentType = "audio/mp3";
mp3blob.UploadByteArray(mp3_audio_byte_array);
clean the temp files:
System.IO.File.Delete(aac_path);
System.IO.File.Delete(mp3_path);

Categories