Run multiple SQL scripts through batch file from C# - 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;
}

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

Run command line with date parameters with C# in SSIS (2015)

I need to run a command line on a Windows server with date parameters using C# in SSIS (2015)
The command line example:
D:\TEST >dotnet TEST.dll --fromDateTime "2018-11-21" --toDateTime "2018-11-22"
Can you assist me in the script?
Thanks
Thank you all for your assistance.
I found the answer to my problem:
Can't use the SSIS Execute Process Task since it is applicable to EXE or BAT
Don't want / Can't change my DotNet DLL to an EXE since it is very limiting and the project includes many other factors that are not under this issue (and the dev is done by other teams)
here is the C# with the answer - it works! :)
public void Main()
{
string FromDate = Dts.Variables["User::FromDate"].Value.ToString();
string ToDate = Dts.Variables["User::ToDate"].Value.ToString();
string TEST_Path = Dts.Variables["$Package::TEST_Path"].Value.ToString();
string TEST_ExePath = Dts.Variables["$Package::TEST_ExePath"].Value.ToString();
var strCmdText = #"c:\program files\dotnet\dotnet.exe";
var parameters = TEST_ExePath.ToString() + " --fromDateTime " + FromDate.ToString() + " --toDateTime " + ToDate.ToString();
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo = new System.Diagnostics.ProcessStartInfo(strCmdText, parameters);
p.StartInfo.WorkingDirectory = TEST_Path;
p.StartInfo.UseShellExecute = false;
bool fireAgain = false;
try
{
p.Start();
}
catch(Exception e)
{
Dts.Events.FireError(0, "Script Task Example", "Exception encountered: " + e.ToString(), String.Empty, 0);
}
p.WaitForExit();
Dts.Events.FireInformation(0, "Script Task Example", "Exit code = " + p.ExitCode.ToString(), String.Empty, 0, ref fireAgain);
Dts.TaskResult = (int)ScriptResults.Success;
}

Converting XSD into .cs class

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);

simple script for generating archives arj

here's code:
string command = string.Empty;
DirectoryInfo dInfoForTesting = new DirectoryInfo(#"E:\TestFiles");
FileInfo[] files = dInfoForTesting.GetFiles();
foreach (FileInfo file in files)
{
string rndPswd = "134";
command = "arj a -m1 -g" + rndPswd + " " + file.Name + ".arj " + file.FullName;
Process.Start(#"C:\ARJ_TEST\programming\test\ARJ.EXE", command);
}
I want to create automatically archives protected by simple password 134 uisng ARJ archiver. But when i run this code for the first file i see the image below. But this file exists!
Please, help to understand me, what i am doing wrong.
EDIT:
i 've decided to rewrite code to run cmd in the folder E:\TestFiles, where there are all files for testing:
ProcessStartInfo startInfo = new ProcessStartInfo
{
WorkingDirectory = #"E:\TestFiles",
FileName = "cmd.exe",
UseShellExecute = false,
RedirectStandardInput = false
};
foreach (FileInfo file in files)
{
string rndPswd = "134";
command = "arj a -m1 -g" + rndPswd + " " + file.Name + ".arj " + file.Name;
startInfo.Arguments = command;
Process.Start(startInfo);
}
For example, if i run command arj a -m1 -g134 10.arj 10 directly from cmd, arj creates an archive 10.arj. But when i run my code for the first file (10) nothing happens...

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.

Categories