I want to pass Arabic string to python script from c#.
And then I will write output to txt file. But my arabic string parameter couldn't pass correctly. It transforms to "????" question marks.
I tried some code, like unicode, but it doesn't work
if __name__ == '__main__':
my_input = sys.argv[1]
out = open("C:\\output.txt", "wb")
p = unicode(my_input, encoding='utf-8')
out.write(p)
out.close()
Also my c# code is like that
public static string run_cmd(string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "C:/Python27/python.exe";
start.Arguments = "C:/test.py" + " " + args;
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
result = reader.ReadToEnd();
}
}
}
Do you have any idea how can I fix this problem?
Or is there something that I missing?
Any idea will be great!
Related
I don't know how can I code the string format to keep the full path with space, because, it is split at each space.
4 arguments:
C:/MyDoc/Example/MyCSV File 1.csv
-1
20-05-2019
7
python.run_cmd("C:/MyCode.py", "C:/MyDoc/Example/MyCSV File 1.csv -1 20-05-2019 7");
Function:
public static void run_cmd(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "C:/PRGM/python.exe";
start.Arguments = string.Format("{0} {1}",cmd, args);
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
}
How about wrapping the file name in quotes, you'll need to escape them using a backslash \:
python.run_cmd("C:/MyCode.py", "\"C:/MyDoc/Example/MyCSV File 1.csv\" -1 20-05-2019 7");
or using a verbatim string:
python.run_cmd("C:/MyCode.py", #"""C:/MyDoc/Example/MyCSV File 1.csv"" -1 20-05-2019 7");
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.
I am making a program that seeks out secured PDFs in a folder and converting them to PNG files using ImageMagick. Below is my code.
string WorkDir = #"C:\Users\rwong\Desktop\TestFiles";
Directory.SetCurrentDirectory(WorkDir);
String[] SubWorkDir = Directory.GetDirectories(WorkDir);
foreach (string subdir in SubWorkDir)
{
string[] filelist = Directory.GetFiles(subdir);
for(int f = 0; f < filelist.Length; f++)
{
if (filelist[f].ToLower().EndsWith(".pdf") || filelist[f].EndsWith(".PDF"))
{
PDFReader reader = new Pdfreader(filelist[f]);
bool PDFCheck = reader.IsOpenedWithFullPermissions;
reader.CLose();
if(PDFCheck)
{
//do nothing
}
else
{
string PNGPath = Path.ChangeExtension(filelistf], ".png");
string PDFfile = '"' + filelist[f] + '"';
string PNGfile = '"' + PNGPath + '"';
string arguments = string.Format("{0} {1}", PDFfile, PNGfile);
ProcessStartInfo startInfo = new ProcessStartInfo(#"C:\Program Files\ImageMagick-6.9.2-Q16\convert.exe");
startInfo.Arguments = arguments;
Process.Start(startInfo);
}
}
}
I have ran the raw command in command prompt and it worked so the command isn't the issue. Sample command below
"C:\Program Files\ImageMagick-6.9.2-Q16\convert.exe" "C:\Users\rwong\Desktop\TestFiles\Test_File File_10.PDF" "C:\Users\rwong\Desktop\TestFiles\Test_File File_10.png"
I looked around SO and there has been hints that spaces in my variable can cause an issue, but most of those threads talk about hardcoding the argument names and they only talk about 1 argument. I thought adding double quotes to each variable would solve the issue but it didn't. I also read that using ProcessStartInfo would have helped but again, no dice. I'm going to guess it is the way I formatted the 2 arguments and how I call the command, or I am using ProcessStartInto wrong. Any thoughts?
EDIT: Based on the comments below I did the extra testing testing by waiting for the command window to exit and I found the following error.
Side note: I wouldn't want to use GhostScript just yet because I feel like I am really close to an answer using ImageMagick.
Solution:
string PNGPath = Path.ChangeExtension(Loan_list[f], ".png");
string PDFfile = PNGPath.Replace("png", "pdf");
string PNGfile = PNGPath;
Process process = new Process();
process.StartInfo.FileName = #"C:\Program Files\ImageMagick-6.9.2 Q16\convert.exe";
process.StartInfo.Arguments = "\"" + PDFfile + "\"" +" \"" + PNGPath +"\""; // Note the /c command (*)
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.Start();
//* Read the output (or the error)
string output = process.StandardOutput.ReadToEnd();
Console.WriteLine(output);
string err = process.StandardError.ReadToEnd();
Console.WriteLine(err);
process.WaitForExit();
It didn't like the way I was formatting the argument string.
This would help you to run you command in c# and also you can get the result of the Console in your C#.
string WorkDir = #"C:\Users\rwong\Desktop\TestFiles";
Directory.SetCurrentDirectory(WorkDir);
String[] SubWorkDir = Directory.GetDirectories(WorkDir);
foreach (string subdir in SubWorkDir)
{
string[] filelist = Directory.GetFiles(subdir);
for(int f = 0; f < filelist.Length; f++)
{
if (filelist[f].ToLower().EndsWith(".pdf") || filelist[f].EndsWith(".PDF"))
{
PDFReader reader = new Pdfreader(filelist[f]);
bool PDFCheck = reader.IsOpenedWithFullPermissions;
reader.CLose()l
if(!PDFCheck)
{
string PNGPath = Path.ChangeExtension(filelistf], ".png");
string PDFfile = '"' + filelist[f] + '"';
string PNGfile = '"' + PNGPath + '"';
string arguments = string.Format("{0} {1}", PDFfile, PNGfile);
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.EnableRaisingEvents = true;
p.StartInfo.CreateNoWindow = true;
p.startInfo.FileName = "C:\Program Files\ImageMagick-6.9.2-Q16\convert.exe";
p.startInfo.Arguments = arguments;
p.OutputDataReceived += new DataReceivedEventHandler(Process_OutputDataReceived);
//You can receive the output provided by the Command prompt in Process_OutputDataReceived
p.Start();
}
}
}
private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
{
string s = e.Data.ToString();
s = s.Replace("\0", string.Empty);
//Show s
Console.WriteLine(s);
}
}
I'm trying to run a Python script from C# as a stream, and to repeatedly pass inputs and outputs between Python and the stream, using StreamWriter and StreamReader.
I can read and write, but apparently only once, and not multiple times. (Which is what I need.)
Hopefully, somebody can tell me what I'm doing wrong.
(I'm aware that I can probably do what I need to do by reading and writing to a file. However, I'd like to avoid this if I can, since using the Stream seems cleaner.)
Here's my C# code:
using System;
using System.Diagnostics;
using System.IO;
public class Stream_Read_Write
{
public static void Main()
{
string path = "C:\\Users\\thomas\\Documents\\Python_Scripts\\io_test.py";
string iter = "3";
string input = "Hello!";
stream_read_write(path, iter, input);
//Keep Console Open for Debug
Console.Write("end");
Console.ReadKey();
}
private static void stream_read_write(string path, string iter, string input)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "C:\\Python27\\python.exe";
start.Arguments = string.Format("{0} {1}", path, iter);
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
start.RedirectStandardInput = true;
start.CreateNoWindow = true;
using (Process process = Process.Start(start))
using (StreamWriter writer = process.StandardInput)
using (StreamReader reader = process.StandardOutput)
{
for (int i = 0; i < Convert.ToInt32(iter); i++)
{
Console.WriteLine("writing...");
writer.WriteLine(input);
writer.Flush();
Console.WriteLine("written: " + input + "\n");
Console.WriteLine("reading...");
string result = reader.ReadLine();
Console.WriteLine("read: " + result + "\n");
}
}
}
}
The Python code looks like this:
import sys
iter = int(sys.argv[1])
for i in range(iter):
input = raw_input()
print (input)
And this is the output that I get:
writing...
written: Hello!
reading...
Strangely, when I remove the loops from both Python and C#, it works.
(For one iteration)
writing...
written: Hello!
reading...
read: Hello!
end
It's not clear to me why this happens, or what the solution could be, so any help is much appreciated.
I found a solution to my problem. I'm not really sure why this works, though.
For C#:
using System;
using System.Diagnostics;
using System.IO;
public class Stream_Read_Write
{
public static void Main()
{
string path = "C:\\Users\\thomas_wortmann\\Documents\\Python_Scripts\\io_test.py";
string iter = "3";
string input = "Hello";
stream_read_write(path, iter, input);
//Keep Console Open for Debug
Console.Write("end");
Console.ReadKey();
}
private static void stream_read_write(string path, string iter, string input)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "C:\\Python27\\python.exe";
start.Arguments = string.Format("{0} {1}", path, iter);
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
start.RedirectStandardInput = true;
start.CreateNoWindow = true;
using (Process process = Process.Start(start))
using (StreamWriter writer = process.StandardInput)
using (StreamReader reader = process.StandardOutput)
{
for (int i = 0; i < Convert.ToInt32(iter); i++)
{
writer.WriteLine(input + i);
Console.WriteLine("written: " + input + i);
string result = null;
while (result == null || result.Length == 0)
{ result = reader.ReadLine(); }
Console.WriteLine("read: " + result + "\n");
}
}
}
}
And the python code looks like this:
import sys
def reverse(input):
return input [::-1]
iter = int(sys.argv[1])
for i in range(iter):
input = sys.stdin.readline()
print reverse(input)
sys.stdout.flush()
This is a conventional stream problem.
You have to “flush” the stream
(e.g. stdout.flush() , where stdout is a stream object)
in order to send the data
no matter in C# or in Python.
In C#, as I know, you have to execute stream.Close()
to complete the flush itself,
or you can wrap the stream with “using”
and it send the data when the brackets is closed.
Edit:
Btw, the stream is only available to one side at a time.
i edited my code to the following:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Search
{
class Program
{
static void Main(string[] args)
{
string abc = string.Format("{0}", args[0]);
string latestversion = string.Format("{1}", args[1]);
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "sslist.exe";
p.StartInfo.Arguments = "-R -H -h sinsscm01.ds.net" + type;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.Start();
string procOutput = p.StandardOutput.ReadToEnd();
string procError = p.StandardError.ReadToEnd();
TextWriter outputlog = new StreamWriter("C:\\Work\\listofsnapshot.txt");
outputlog.Write(procOutput);
outputlog.Close();
string greatestVersionNumber = "";
using (StreamReader sr = new StreamReader("C:\\Work\\listofsnapshot.txt"))
{
while (sr.Peek() >= 0)
{
var line = sr.ReadLine();
var versionNumber = line.Replace(latestversion, "");
if(versionNumber.Length != line.Length)
greatestVersionNumber = versionNumber;
}
}
Console.WriteLine(greatestVersionNumber);
TextWriter latest = new StreamWriter("C:\\Work\\latestbuild.properties");
latest.Write("Version_Number=" + greatestVersionNumber);
latest.Close();
}
}
}
where string type and string latest version are the arguments parsed.
So, my commandline looks like this:
c:/searchversion.exe "/SASE Lab Tools" "6.70_Extensions/6.70.102/ANT_RELEASE_"
where "/SASE Lab Tools" should be stored as a string abc and "6.70_Extensions/6.70.102/ANT_RELEASE_" should be stored as a string as latestversion.
However i get an error: System.Format.Exception: Index(zero based) must be greater than or equal to zero and less than the size of the argument list at line 14:
string latestversion = string.Format("{1}", args[1]);
Anybody knows whats wrong?
string latestversion = string.Format("{0}", args[0]);
updated
if you go debugging do you have your args[] filled with data?
for
string latestversion = string.Format("{1}", args[1]);
You specified the 2nd item in the array of the string format, for which there isnt one. So the array is out of bounds. you meant
string latestversion = string.Format("{0}", args[1]);
See abc and latestversion are two different strings. And since you are formatting those one-by-one, you need to start your format specifiers by 0 each time. So, your code should be:
string latestversion = string.Format("{0}", args[1]);