Scheduler - C# App - Batch - FTP - Works Manually But Not In Schedulers - c#

I have a C# app which executes a batch script, which writes ftp commands to a text file and then executes the text file. It works when executed manually, but not when executed from schedulers such as Windows Task Scheduler (not the one I'll ultimately be using but am using for debugging purposes).
Specifically, when run from the scheduler, the script executes, but the parameters don't get passed, and the ftp script file is not overwritten before it is called, so it only executes whatever script was left from the previous job. It does, however, overwrite the .txt reports that record the ftp session, as intended. Again, when run manually, it all works.
Security policies prevent much tinkering with permissions, but I gave the job account full permissions on all affected folders, and added "log on as batch file" rights to the job account. No parameters need to be passed to the C# application. Any suggestions would be appreciated.
C# Code:
ProcessStartInfo psi = new ProcessStartInfo(scriptFile, paramList);
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
Process p = Process.Start(psi);
//etc...
Batch Script:
Set DIR=%~1
Set SUBDIR=%~2
Set SWITCH=%~3
cd "%DIR%Scripts\
ECHO USER user>FtpScript.txt
ECHO pass>>FtpScript.txt
ECHO lcd "%DIR%FilesToFtp\%SUBDIR%\%SWITCH%">>FtpScript.txt
ECHO lcd "%DIR%FilesToFtp\%SUBDIR%\%SWITCH%"\>>FtpScript.txt
IF "%SWITCH%"=="ONE" ECHO QUOTE SITE LRECL=100 RECFM=FB>>FtpScript.txt
IF "%SWITCH%"=="TWO" ECHO QUOTE SITE LRECL=200 RECFM=FB>>FtpScript.txt
IF "%SWITCH%"=="THREE" ECHO QUOTE SITE LRECL=300 RECFM=FB>>FtpScript.txt
ECHO MPUT "*.*">>FtpScript.txt
ECHO(>>FtpScript.txt
REM other commands, etc...
FTP -d -n -s:"%DIR%Scripts\FtpScript.txt" server > "%FPATH%Reports\%SUBDIR%_%SWITCH%_log.txt"
EXIT 0
Thanks in advance.

Related

Running Bash Commands from C#

I am trying to figure out how to run a bash command from C# running on IIS 7/.Net 4.5.
I've been searching the web and a lot of answers presume you have certain things installed/in place.
I already have Git 1.9.4.msysgit.2 installed with Git Bash and Git Giu. I'm looking for some help as to what else I need installed to run even the simplest of bash commands. And how to run it.
I've looked at posts like bash pipes - I am trying to call script from c# but that uses cygwin. Can I do the same without it and if so, how do I go about it?
Goal
If what I'm asking above doesn't make sense or seems to ask separate questions, here my ultimate goal. I'm trying to write my own server-side git hook. When a developer pushes their commits to our GitHub repo, I want GitHub to call our callback url. I want my callback url to run a git pull command to update our staging server with what was just pushed.
I got to this question based on a previous question I asked at GitHub - setup auto deployment with remote server. based on answers there I'm trying to run a simple command, either but hard coding the command, or putting it in a script and running it, e.g.: cd $REPO_DIR && git pull origin $branch_name.
I am aware of Jenkins and other software, but I want to perform these commands myself vs. installing another software.
If further information is needed please feel free to ask.
Update 1
So based on a few answers below I've come up with the following
using System.Diagnostics;
Process process = new Process();
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
processStartInfo.FileName = #"C:\Program Files (x86)\Git\bin\bash.exe";
processStartInfo.WorkingDirectory = #"C:\myrepo\mysite";
processStartInfo.Arguments = "git status";
processStartInfo.RedirectStandardOutput = true;
processStartInfo.RedirectStandardError = true;
processStartInfo.UseShellExecute = false;
process.StartInfo = processStartInfo;
process.Start();
String error = process.StandardError.ReadToEnd();
String output = process.StandardOutput.ReadToEnd();
ViewBag.Error = error;
ViewBag.Ouput = output;
With the code above I am getting "C:/Program Files (x86)/Git/bin/bash.exe": git: No such file or directory. I know the exe is there. What's am I doing wrong?
Update 2
As per #SurgeonofDeath comment I followed this post http://blog.countableset.ch/2012/06/07/adding-git-to-windows-7-path/ and added the paths of Git to my environmental variables. However I still am getting the same issues. Any ideas?
Thanks.
Instead of calling the bash.exe, simply call git and pass the status as argument:
processStartInfo.FileName = "git";
processStartInfo.Arguments = "status";
perhaps i misunderstood your question but what about execve?
here is an excerpt of it's man page.
NAME
execve - execute program
SYNOPSIS
#include <unistd.h>
int execve(const char *filename, char *const argv[],
char *const envp[]);
DESCRIPTION
execve() executes the program pointed to by filename. filename must > be
either a binary executable, or a script starting with a line of > the
form:
#! interpreter [optional-arg]
Check your PATH environment variable and update it
C:/Program Files (x86)/Git/bin/bash.exe": git: No such file or directory
means that it's git which is not found by bash.
1. Check the PATH environment variable in bash (which is and should remain different from Windows one)
Adjust this
processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
to make the terminal visible.
In the terminal you will create with the Process.Start()
Type:
echo ${PATH}
2. Update your path
You could update the global path of windows (which requires a restart)
You could update the user path of windows (which should require a logoff, but I'm not sure).
You just set Path to what you like with System.Environment.SetEnvironmentVariable before starting the Process
Additional note:
If you have like me several versions of bash, command interpreters, git and so on, it could be really messy if you try to concatenate all the paths and hope to find the ideal order. You could see some weird behavior of you beloved commands until you realize it's not the one you intend to run ... think of FIND.exe... And I didn't even think of the user-friendly interface of windows to edit environment variables ...

Process.Start() does nothing

I have to start a VPN connection (Fortinet) by code.
I have a cmd file that establish the connection.
If I call the cmd file on the shell it works pretty fine.
When I call it via Process.Start it does nothing.
It doesn't throw any exception, it seems to execute but VPN does not connect.
On the standard output I can read the echo I put on the cmd file (so it is executing the right file).
I launched a ping -d to see when the vpn goes up, when I call it via shell it goes up in a few seconds, via C# it is not.
I also tried a sleep(30000) but nothing.
My cmd (ConnectFile.cmd):
#echo off
#echo Connecting to VPN
"C:\Program Files (x86)\Fortinet\SslvpnClient\FortiSSLVPNclient.exe" connect -s "vpn myvpn"
My code (connectFile and disconnectFile are strings that contain the full path of the cmd files):
try
{
var startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = connectFile;
startInfo.WorkingDirectory = System.IO.Path.GetDirectoryName(connectFile) ?? "";
System.Diagnostics.Process process = System.Diagnostics.Process.Start(startInfo);
System.Threading.Thread.Sleep(30000);
base.GetFiles(folder);
}
finally
{
System.Diagnostics.Process.Start(disconnectFile);
}
You have to separate the parameters. FileName is for the exe file, not the whole shell command (you're explicitly saying not to use the shell). So put the parameters to the Arguments property in ProcessStartInfo.
In your case, the parameters should be:
FileName - C:\Program Files (x86)\Fortinet\SslvpnClient\FortiSSLVPNclient.exe (no quotes)
Arguments - connect -s "vpn myvpn" (again, no quoting)
Second, you have to read the standard output if you capture it. If the output buffer gets full before you read it, the called process will stop working - it has to wait for the buffer to be emptied. If you're sure the application will actually finish at some point, simply remove the Thread.Sleep and call ReadToEnd right away. Otherwise, use eg. asynchronous reading to get the data.
Also, it's usually a good idea to set WorkingDirectory. Even if the application doesn't need any data from the working directory, it's safer, since only admins can change Program Files - this helps against DLL inject hacks.

psexec via Process gives different exitcode than psexec via cmd

I'm currently working on an application that checks whether a APP with a certain name exist on an IIS server. I use PsExec to execute this command.
While I was testing this through the command line, I noticed that when an APP does not exist the appcmd exits with ExitCode 1. Likewise it exits with 0 when an APP does exist.
I wanted to use this behavior too so I don't need to do output redirection. I only care about whether the APP exists or not. PsExec uses the exitcode of the command it calls as its own exitcode. I tried this with the command line and checked the result with echo %errorlevel% and it works just fine.
But I run into a problem with the following code.
Process process = new Process();
process.StartInfo.FileName = #"psexec";
string appcmd = #"C:\windows\system32\inetsrv\appcmd";
process.StartInfo.Arguments = String.Format(#"{0} -u {1} -p {2} -S {3} LIST APP ""{4}""",
ip, username, password, appcmd, appname);
process.Start();
process.WaitForExit();
Console.WriteLine(process.ExitCode);
This executes just fine. But it does not return the exitcode that PsExec (should?) gives. It always returns 0. So now I can't use the trick I found earlier to check whether an APP exists or not.
I there a known solution for this? Is there a similar solution? Or should I go with output redirection?
Not really a solution to the problem. But because web applications in IIS must have a unique name, creating an application that already exists will result in an error but nothing will have changed.
This means that it works perfectly fine if I always try to create a new APP. If it doesn't exist it will be made, if it already exists nothing will happen.

Modify remote machine input.properties file from web page

i have build script in remote machine.but i want to start the build from my local machine.so for this i need to update the input.properties file in remote machine and then run the batch file to start the build process. For this i have created one web page
so how can i modify the remote input.properties file and run the batch file in C#.
please give me some suggestion for this.
thanks in advance...
You need to edit the properties file remotely, using a Stream Reader / Stream Writer. There are many ways to do that. You should be able to solve that yourself.
Once you are happy that the properties file is updated correctly you will need to use PSEXEC service to launch the Batch file locally on the User's machine. So in this case, the batch file needs to be copied over to the remote machine.
What I normally do is write the Batch file your intending on using to the remote machine on the fly, and as soon as I can see that the associated process has finished, I remove the batch file from the local machine.
PSEXEC will be ran at your end, you use it to connect up to the end users machine and fire the batch file.
You can create a process like below :-
Process p = new Process();
p.StartInfo.CreateNoWindow = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = "C:\\psexec.exe";
p.StartInfo.Arguments = "\\\\" + computerName + " C:\\YourBatFile.bat";
p.Start();
p.WaitForExit();
This will open a process on the local machine, that will launch your batch file.
I would recommend learning about the PSEXEC Service, its how I've always launched remote processed.
Hope this helps.

execute an EXE on the server

I have an exe which I call from the command line. Is it possible to execute that file on the server? On the computer if the file is located in the folder abc, I go to folder abc and than I execute the batch. Hw do I do this in C#
Code example below, make sure you have your permissions setup correctly:
System.Diagnostics.Process yourProcess = new System.Diagnostics.Process();
// Set the directory
yourProcess.StartInfo.WorkingDirectory = Request.MapPath("~/"); //or wherever your file is
// Set the filename
yourProcess.StartInfo.FileName = Request.MapPath("bla.exe");
// Start the process
yourProcess.Start();
ASP Net - Run Application (EXE) from ASP.Net C#
In server side code certainly, Process.Start(MyExeFile) will do that but, as long as the user account you are running your stuff on can execute it.

Categories

Resources