how to publish a mvc website that has python script in it - c#

I'm working on a MVC.net website in which I use python script in it. I have a python file which I call it in order to get some results from it. The algorithm has been wrtiten in python and I have to call to get the result. If I want to execute python file, I have to call python.exe file which I call it like below and the result of calling file is string. When I run website locally it works fine but now I want to publish website to server and don't know how to upload python file in it.
Second question is that how should I change the path of a python.exe and python file to run on cpanel.
string python = #"C:\Users\Cebit\AppData\Local\Programs\Python\Python37\python.exe";
string myPythonApp = #"C:\Users\Cebit\Desktop\phase2-final.py";
ProcessStartInfo myProcessStartInfo = new ProcessStartInfo(python);
myProcessStartInfo.UseShellExecute = false;
myProcessStartInfo.CreateNoWindow = true;
myProcessStartInfo.RedirectStandardOutput = true;
myProcessStartInfo.RedirectStandardError = true;
List<String> argv = new List<String>();
argv.Add(d1);
argv.Add(m1);
argv.Add(y1);
argv.Add(h1);
argv.Add(min1);
argv.Add(d2);
argv.Add(m2);
argv.Add(y2);
argv.Add(h2);
argv.Add(min2);
argv.Add(favor);
argv.Add(budget.ToString());
myProcessStartInfo.Arguments = string.Format("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11} {12}", myPythonApp, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11]);
Process myProcess = new Process();
myProcess.StartInfo = myProcessStartInfo;
myProcess.Start();
StreamReader myStreamReader = myProcess.StandardOutput;
myProcess.WaitForExit();
string myString = myStreamReader.ReadToEnd();
myProcess.Close();
My question is how should I publish a website which I have to run python.exe and python file in a server. Should I have to do something extra in order to run python.exe file in server ? I'm new to use py script in mvc and don't know how to publish it on cpanel

I would suggest using ENVIRONMENT variables to set the path. This would allow you to have different paths for local development vs deployed. Hopefully, then CPANEL allows you to set these variables. Otherwise, you will need to deploy to a VM that you have more control of.
As an example your path string would now be:
string python = Environment.GetEnvironmentVariable("python_exe");
string myPythonApp = Environment.GetEnvironmentVariable("app_python_script");
In terms of actually deploying it, add it as an item and set it to Copy and the py script should be in the bin directory.

Related

MVC executing a LibreOffice conversion

Hi I'm trying to convert either a doc or docx to a pdf in a c# MVC application. I know I can do this using libreOffice. So I created a simple batch file to take 2 variables and then run them into the libreoffice 'soffice' headless to convert to pdf.
So that gave me this code.
echo on
SET var1=%2
IF "%var1:~-1%"=="\" SET var1=%var1:~0,-1%
cd "C:\Program Files\LibreOffice 5\program\"
soffice --headless --convert-to pdf %1 --outdir %var1%
Originally I thought the problem was within my MVC application and the way I called this batch script. But I commented (REM) the soffice and outputted out the command in the bash using the standard output.
var psi = new ProcessStartInfo("cmd.exe", "/k " + command);
//psi.CreateNoWindow = true;
psi.FileName = command;
psi.UseShellExecute = false;
psi.RedirectStandardError = true;
psi.RedirectStandardOutput = true;
psi.Arguments = string.Format("{0} {1}", fullPath2, tempPath);
var process = Process.Start(psi);
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
Trace.WriteLine(output);
Trace.WriteLine(error);
process.WaitForExit();
When I commented the soffice line - it hit the WaitForExit and worked no problems (ok with no pdf conversions, but the script exited).
If I don't do that it seems to execute the cmd and even the soffice commands because I can see them in the task manager - but obvisouly nothing happens.
Additionally the code above works when I did a c# command line program (I've hard coded the file/command lines in both instances). The executable also works when I run as the user that is running the app pool in my MVC application.
The bash file also works file 'standalone' no matter if me or my appPool user run it.
So what gives - why won't this run.
This is the code that comes out of that trace - so what the bash script does.
c:\windows\system32\inetsrv>echo on
c:\windows\system32\inetsrv>SET var1=C:\inetpub\xxxxxxxxx\Temp\
c:\windows\system32\inetsrv>IF "\" == "\" SET var1=C:\inetpub\xxxxxxxxx\Temp
c:\windows\system32\inetsrv>cd "C:\Program Files\LibreOffice 5\program\"
C:\Program Files\LibreOffice 5\program>soffice --headless --convert-to pdf C:\inetpub\xxxxxxxxx\Temp\636295920370843147.doc --outdir C:\inetpub\xxxxxxxxx\Temp
I've got a feeling that this has something to do with the amount of characters or something because the soffice does fireup (can see it in the task manager).
FYI there are no spaces or special characters anywhere.
Any ideas?
Update
This looks to be an issue with the wait command. So any help with that helpful, I'm starting to think perhaps this is an issue with c# and libreoffice 5 - I've seen examples that supposedly work with libreoffice 4.
I guess my challenge continues....

C# - Command runs from command prompt but not from service

I have a C# (ASP Core) service running on Windows Server 2012 R2 that executes Newman test suites via the command line. The command the service executes works perfectly when run directly in the command prompt, but is not working from the service. To add insult to injury, the very same command DOES work from the service running locally on my dev machine (Windows 10 Pro). I am certain I am running the same command in all instances, as the service outputs the CLI's StandardOutput into a file, the contents of which I paste straight into the command prompt.
EDIT: The service is hosted on IIS.
The error I receive:
module.js:471
throw err;
^
Error: Cannot find module 'C:\Users\MyName\AppData\Roaming\npm\node_modules\newman\bin\newman.js'
at Function.Module._resolveFilename (module.js:469:15)
at Function.Module._load (module.js:417:25)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:393:7)
at startup (bootstrap_node.js:150:9)
at bootstrap_node.js:508:3
The command I'm running (all paths are the same in every instance):
"C:\Program Files\NodeJS\node.exe" C:\Users\MyName\AppData\Roaming\npm\node_modules\newman\bin\newman.js run https://api.getpostman.com/collections/MyCollectionURI -r cli,junit --reporter-junit-export D:\TestHarnessServiceLogs\XML\{FilenameFromDatetime}.xml -e https://api.getpostman.com/environments/MyEnvironmentURI --disable-unicode
C# to build and run command:
//Build over multiple lines to make it vaguely readable, then string replace away the newlines so it runs as one command
string runTestCmd = $#"{_nodeExecutablePath}
{_newmanDotJsFile} run
{collectionPath}
-r cli,junit
--reporter-junit-export {_junitReportPathWithFilename}
-e {environmentPath}
--disable-unicode"
.Replace(Environment.NewLine, " ")
.Replace("\t", "");
File.WriteAllText(#"D:\TestHarnessServiceLogs\Command.txt", runTestCmd);
//Launch hidden CLI
using (Process p = new Process())
{
p.StartInfo.FileName = #"C:\Windows\System32\cmd.exe";
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.Arguments = _nodeVarsBatPath;
p.Start();
//Execute commands
using (StreamWriter sw = p.StandardInput)
{
if (sw.BaseStream.CanWrite)
{
sw.WriteLine(runTestCmd);
}
}
//Parse the various outputs
output = p.StandardOutput.ReadToEnd();
error = p.StandardError.ReadToEnd();
exitCode = p.ExitCode.ToString(); //Always returns 0, think this is because it evaluates success of creating the process, not what happens inside it
File.WriteAllText(#"D:\TestHarnessServiceLogs\output.txt", output);
File.WriteAllText(#"D:\TestHarnessServiceLogs\error.txt", error);
File.WriteAllText(#"D:\TestHarnessServiceLogs\exitCode.txt", exitCode);
}
Newman is installed globally in both environments, and some relevant AppSettings below (names modified slightly for brevity):
"_newmanDotJsFile": "C:\\Users\\MyName\\AppData\\Roaming\\npm\\node_modules\\newman\\bin\\newman.js",
"_nodeVarsBatPath": "\"C:\\Program Files\\NodeJS\\nodevars.bat\"",
"_nodeExecutablePath": "\"C:\\Program Files\\NodeJS\\node.exe\"",
How can an identical command find the newman module and run fine from the CLI but not from the service?
EDIT: The user the service is running under couldn't access the file, having done that I now get the following (obviously permissions based) error instead, think I know where this is going...:
fs.js:994
binding.lstat(pathModule._makeLong(path), statValues);
^
Error: EPERM: operation not permitted, lstat 'C:\Users\MyName'
at Error (native)
at Object.fs.lstatSync (fs.js:994:11)
at Object.realpathSync (fs.js:1676:21)
at toRealPath (module.js:133:13)
at Function.Module._findPath (module.js:181:22)
at Function.Module._resolveFilename (module.js:467:25)
at Function.Module._load (module.js:417:25)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:393:7)
at startup (bootstrap_node.js:150:9)
EDIT 2: Created a new user for the service to run under, installed newman for that user and gave it the right permissions (didn't seem clever to give Network Service access to my profile) - all is now working!
It sounds like the service doesn't run as your user? Perhaps that's why it doesn't find the file in that location you specified.

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;

Problem while trying to run .exe on remote with psexec (c#)?

Hey all,
I'm trying to run an exe file ON A REMOTE MACHINE (not from, but ON).
I have very simple code as following:
ProcessStartInfo info = new ProcessStartInfo("C:\\PsTools");
info.FileName = "psexec \\\\" + machine.Name + "\\C\\Program Files\\test.exe";
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
Process p = Process.Start(info);
When trying to run this code i get "The system cannot find the file specified" error.
There is a file named "test.bat" on the specified directory.
The remote machine is on the same domain and the C folder is shared (I'm the admin).
I have PsTools installed and configured as environment variables.
I have tried variety of codes (for example if i don't use "psexec" on the ProcessStartInfo constructor and on the FileName property, the bat file runs on the local machine instead of the remote one...) and nothing works!
any ideas?
My guess is that it's failing to find psexec, because you've set UseShellExecute to false. Try giving the full path to psexec.exe.
You should also set the FileName property to just the file you want to start, and the Arguments property to the command line arguments, like this:
ProcessStartInfo info = new ProcessStartInfo("C:\\PsTools");
info.FileName = #"c:\whatever\psexec.exe";
info.Arguments = #"""\\" + machine.Name + #"\C\Program Files\test.exe""";
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
Process p = Process.Start(info);
Note that I've also added double quotes in the Arguments property so that it doesn't get split into two arguments due to "Program Files" having a space in it.

How to use lame.exe in my application?

I capture audio files in the wave format in my Microsoft Surface application. Now for file size reasons, I'd like to convert the wave file into a mp3 file. I read in the Internet that a good possibility to do that is using lame.
But how can I call this exe file from my application? and how can I include it into my application?
Use Process class to call an external application:
string lameEXE = #"C:\path_of_lame\lame.exe";
string lameArgs = "-V2";
string wavFile = #"C:\my_wavs\input.wav";
string mp3File = #"C:\my_mp3s\output.mp3";
Process process = new Process();
process.StartInfo = new ProcessStartInfo();
process.StartInfo.FileName = lameEXE;
process.StartInfo.Arguments = string.Format(
"{0} {1} {2}",
lameArgs,
wavFile,
mp3File);
process.Start();
process.WaitForExit();
int exitCode = process.ExitCode;
You can call an executable from .NET by using the System.Diagnostics.Process class and related classes - see here for the documentation.
Lame has pretty robust command line arguments, which can be found here. You can pass command line arguments to the Process using the ProcessStartInfo.Arguments property.
public void mciConvertWavMP3(string fileName, bool waitFlag)
{
//maxLen is in ms (1000 = 1 second)
string outfile= "-b 32 --resample 22.05 -m m \"" + pworkingDir+fileName + "\" \"" + pworkingDir + fileName.Replace(".wav",".mp3") + "\"";
System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo();
psi.FileName = "\"" + pworkingDir + "lame.exe" + "\"";
psi.Arguments = outfile;
//psi.WorkingDirectory = pworkingDir;
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Minimized;
System.Diagnostics.Process p = System.Diagnostics.Process.Start(psi);
if (waitFlag)
{
p.WaitForExit();
// wait for exit of called application
}
}
Above code taken from here .
Depending on the usage, you can incorporate a Process.StartInfo object, control properties such as ShellExecute and also redirect any output from the application to (say) a log file or UI component.
To bundle the exe with your project, check this question from stackoverflow out. Personally, I'd go with the first suggestions:
There are several ways you could
accomplish this. First, you should add
program.exe to the project. You would
do this by right-clicking the project
in Visual Studio, and selecting Add >
Existing Item... Select program.exe,
and it will appear in the project.
Viewing its properties, you can set
"Copy to Output Directory" to "Copy
Always", and it will appear in your
output directory beside your
application.
If you stick to the above method, then reference lame.exe relatively ('....\Tools\Lame.exe' for example).
Finally, according to the official lame site : RareWares offers several compiled LAME versions, including modified versions featuring special functionality.
There is a DLL version of LAME, I would be surprised if you can't find a VB or C# example using it. Check this discussion thread: http://www.eggheadcafe.com/software/aspnet/31294459/-lameencdll-and-vbnet.aspx

Categories