Running a batch file from an ASP.Net page - asp.net

I'm trying to run a batch file on a server via an ASP.Net page, and it's driving my crazy. When I run the below code, nothing happnes - I can see from some log statements that this code runs, but the .bat file that I pass to the function never runs.
Could anybody please tell me what I'm doing wrong?
public void ExecuteCommand(string batchFileLocation)
{
Process p = new Process();
// Create secure password
string prePassword = "myadminpwd";
SecureString passwordSecure = new SecureString();
char[] passwordChars = prePassword.ToCharArray();
foreach (char c in passwordChars)
{
passwordSecure.AppendChar(c);
}
// Set up the parameters to the process
p.StartInfo.FileName = #"C:\\Windows\\System32\cmd.exe";
p.StartInfo.Arguments = #" /C " + batchFileLocation;
p.StartInfo.LoadUserProfile = true;
p.StartInfo.UserName = "admin";
p.StartInfo.Password = passwordSecure;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
// Run the process and wait for it to complete
p.Start();
p.WaitForExit();
}
In the 'Application' Event Viewer log on the server, every time I try to run this, the following issue seems to occur:
Faulting application cmd.exe, version 6.0.6001.18000, time stamp 0x47918bde, faulting module kernel32.dll, version 6.0.6001.18000, time stamp 0x4791a7a6, exception code 0xc0000142, fault offset 0x00009cac, process id 0x8bc,application start time 0x01cc0a67825eda4b.
UPDATE
The following code works fine (it runs the batch file):
Process p = new Process();
p.StartInfo.FileName = batchFileLocation;
p.StartInfo.WorkingDirectory = Path.GetDirectoryName(batchFileLocation);
p.StartInfo.UseShellExecute = false;
// Run the process and wait for it to complete
p.Start();
p.WaitForExit();
This however doesn't (when i try to run as a specific user):
Process p = new Process();
// Create secure password
string prePassword = "adminpassword";
SecureString passwordSecure = new SecureString();
char[] passwordChars = prePassword.ToCharArray();
foreach (char c in passwordChars)
{
passwordSecure.AppendChar(c);
}
p.StartInfo.FileName = batchFileLocation;
p.StartInfo.WorkingDirectory = Path.GetDirectoryName(batchFileLocation);
p.StartInfo.UseShellExecute = false;
p.StartInfo.UserName = "admin";
p.StartInfo.Password = passwordSecure;
// Run the process and wait for it to complete
p.Start();
p.WaitForExit();

Just call the batch file directly:
p.StartInfo.FileName = batchFileLocation;
Also, make sure the WorkingDirectory is set to the right location:
p.StartInfo.WorkingDirectory= Path.GetDirectoryName(batchFileLocation);

A little google on "Faulting application cmd.exe" points me to this IIS forum.
It seems that you cannot create a new process in the background under IIS, unless you use the CreateProcessWithLogon method. (I have not tested this).

Related

Android 10 - unable to take PersistableUriPermission on a file that I created in getExternalFilesDir()

Using the below code snippet, we created a file in Android 10, in a sub-folder under getExternalFilesDir(). However, immediately after creation, if we try to take persistableUriPermission, it throws an exception "No such permission exists....".
We need that check to know if that file will be available for read later in a common utility, else we have to make a copy. Please let us know what we might be doing wrong and how to fix this. Appreciate your help.
ParcelFileDescriptor filePFD =
cxt.getContentResolver().openFileDescriptor(Uri.parse(pathFileToSend), "r");
FileDescriptor fd = filePFD.getFileDescriptor();
FileInputStream fIn = new FileInputStream(fd);
File fileBaseFolder = new File(Utils.GetRootDirectory().getAbsolutePath(), Utils.DESTINATION);
if (!fileBaseFolder.exists())
fileBaseFolder.mkdirs();
if (fileBaseFolder.exists()) {
File copyFile = new File(fileBaseFolder.getAbsolutePath(), nameOfFile);
FileOutputStream fOut = new FileOutputStream(copyFile);
byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = fIn.read(data)) != -1) {
total += count;
fOut.write(data, 0, count);
}
fOut.close();
Uri copiedFileUri =
FileProvider.getUriForFile(cxt,
cxt.getString(R.string.file_provider_authority),
copyFile);
if (null != copiedFileUri)
{
try {
/*At this line, an exception is thrown - No persistable permissions exist.. */
cxt.getContentResolver().takePersistableUriPermission(copiedFileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
} catch (Exception e) {
e.printStackTrace();
}
}
takePersistableUriPermission() is for Uri values that you get from the Storage Access Framework (e.g., ACTION_OPEN_DOCUMENT). It will not work for FileProvider. And, you do not need permissions to work with getExternalFilesDir() on Android 4.4 and higher.

Powershell runquery in clients machine ASP.NET

I want to get the program names installed from Windows Store(client side). Heres my code. First of all is it possible? Secondly if yes why my code is not working?
StringBuilder stringBuilder = new StringBuilder();
var shell = PowerShell.Create();
// Add the script to the PowerShell object
shell.Commands.AddScript("Import-Module Appx");
shell.Commands.AddScript("Get-AppxPackage ");
Command c = new Command("Out-String");
c.Parameters.Add("width", 150);
shell.Commands.AddCommand(c);
// var results = shell.Invoke();
Collection<PSObject> results = shell.Invoke();
foreach (PSObject obj in results)
{
stringBuilder.AppendLine(obj.ToString());
}
No results returned (Only one and it is empty . )

Why (on a specific server) would ADO,NET get a Time Out exception after db result is returned and the reader is being closed?

I have some strange behavior occurring in an ASP.NET application that I am trying to fix.
I am getting the following error from code:
Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
I am familiar with this error and many of it's causes. All of my typical avenues of trouble shooting have failed.
Here are some of the dynamics:
The server was recently re-built. So it could be a server configuration issue.
This error only happens on a specific web server. When I run the application it locally, and from other servers it is fast. I cannot re-pro perf issues with the proc in MSSMS from my machine.
This tells me that it is specific to this server.
When I run The same proc using the OSql command--line utility It works. Fast.
This indicates that it is likely something .NET related, NOT db related
Prior to this code executing, I have executed other Stored procedures on this server, and on this same DB.
This suggests the proc may be related , but is not a "server X cannot talk to server Y"
I have gotten confirmation From DB owners that the DB has received the command, executed (>1second )it and returned the data.
By tracing the code, I see the results are returned and it is not until I try to close the data reader that the error occurs.
In fact I see it takes 36 milliseconds to execute the stored procedure and iterate through the result.
It looks like the call to DataReader.Close is what is taking time, and eventually timing out.
I have increased the max Pool from 31 to 100.
Here is a sample of what my code looks like, how it is structured. I have been hacking at it for trouble shooting: I have added the explict close to ensure I know where the error occurs. There may be syntax issues: I have made it generic, and may have introduced bugs in doing so.
public double GetMyData()
{
double returnValue;
// Used in logging to see if code was reached & how long it took.
System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();
using (SqlConnection cn = Connections.GetSqlConnection())
{
cn.Open();
using (SqlCommand cmd = getSQLCommmand("SomeProcName"))
{
Log.Log.WriteTrace(string.Format("Execute {0} ","SomeProcName"),0);
s.Start();
SqlDataReader dr= null;
try
{
dr = cmd.ExecuteReader();
s.Stop();
Log.Log.WriteTrace("Timer", "ExecuteReader done " + s.ElapsedMilliseconds + "ms ", 0);
s.Start();
if (dr != null)
{
if (dr.Read())
{
returnValue =
Conversion.DBNullToDouble(
dr[0]);
}
s.Stop();
Log.Log.WriteTrace("Timer", "dr.read done (result:" + returnValue + ")" + s.ElapsedMilliseconds + "ms ", 0); // I get Here
}
}catch(Exception ex)
{
Log.Log.PersistException(ex);
}
//}
if(dr!=null && !dr.IsClosed)
dr.Close();// This times out
if (cn != null && cn.State !=ConnectionState.Closed)
cn.Close();
Log.Log.WriteTrace("DONE "),
;
}
}
return (returnValue);
}
UPDATE
dr.Close(); takes 2 minutes to execute. Just on this server. Locally it takes less than a second.
UPDATE
Per the accepted answer's comments: I have a proc that has multiple records. I am taking the fist one. Calling cmd.Cancel() has not fixed, but has drastically reduced the time taken to close the data reader. Exploring this should help me fix the problem. I do not know why this is only happening on this server, as the server is a dev server.
I see few problems in your code.
Try to use the Reader in a using statement it closes and disposes when finishing it.
You are closing 2 times the connection (when using
if (cn != null && cn.State !=ConnectionState.Closed)
cn.Close();
and in the using (SqlConnection cn = Connections.GetSqlConnection()) -- this one do it for you at the end of the statement
In your code you are not checking if the DataReader.HasRows So if your Sproc doesn't return a value it will throw an exception in the if (dr.Read()) so that could be the reason that's why you are getting sometimes the time out exception
If you only want to retrieve the value of the first column of the first row you should take a look to ExecuteScalar
Finally
I would rewrite your code like this (using DataReader)
public double GetMyData()
{
double returnValue;
// Used in logging to see if code was reached & how long it took.
System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();
using (SqlConnection cn = Connections.GetSqlConnection())
{
cn.Open();
using (SqlCommand cmd = getSQLCommmand("SomeProcName"))
{
Log.Log.WriteTrace(string.Format("Execute {0} ","SomeProcName"),0);
s.Start();
using(SqlDataReader dr = cmd.ExecuteReader())
{
s.Stop();
Log.Log.WriteTrace("Timer", "ExecuteReader done " + s.ElapsedMilliseconds + "ms ", 0);
s.Start();
if (dr != null)
{
if(dr.HasRows)
{
if (dr.Read())
{
returnValue =
Conversion.DBNullToDouble(
dr[0]);
}
}
s.Stop();
Log.Log.WriteTrace("Timer", "dr.read done (result:" + returnValue + ")" + s.ElapsedMilliseconds + "ms ", 0); // I get Here
}
}
}
}
return (returnValue);
}
Or (with ExecuteScalar)
public double GetMyData()
{
double returnValue;
// Used in logging to see if code was reached & how long it took.
System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();
using (SqlConnection cn = Connections.GetSqlConnection())
{
cn.Open();
using (SqlCommand cmd = getSQLCommmand("SomeProcName"))
{
Log.Log.WriteTrace(string.Format("Execute {0} ","SomeProcName"),0);
s.Start();
try
{
returnValue = Conversion.DBNullToDouble(cmd.ExecuteScalar());
s.Stop();
}
catch(Exception ex)
{
Log.Log.PersistException(ex);
}
}
}
return (returnValue);
}

imagemagick file paths? Getting a 'The system cannot find the file specified error'

I cannot figure out where I need to put files for ImageMagick to process them. I am trying to use it in my ASP.NET MVC website and having zero luck having it find my files to process. And if it does how do I specify where they will be output?
I have been looking here and I mut be missing something:
http://www.imagemagick.org/script/command-line-processing.php
Here is my code to call the process:
//Location of the ImageMagick applications
private const string pathImageMagick = #"C:\Program Files\ImageMagick-6.7.3-8";
private const string appImageMagick = "MagickCMD.exe";
CallImageMagick("convert -density 400 SampleCtalog.pdf -scale 2000x1000 hi-res%d.jpg");
private static string CallImageMagick(string fileArgs)
{
ProcessStartInfo startInfo = new ProcessStartInfo
{
Arguments = fileArgs,
WorkingDirectory = pathImageMagick,
FileName = appImageMagick,
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true
};
using (Process exeProcess = Process.Start(startInfo))
{
string IMResponse = exeProcess.StandardOutput.ReadToEnd();
exeProcess.WaitForExit();
exeProcess.Close();
return !String.IsNullOrEmpty(IMResponse) ? IMResponse : "True";
}
}
We do something similar but use the environment variables (which is advantageous because it works on every system) to execute cmd.exe which we feed with convert and the parameters. This is how we create the ProcessStartInfo object:
// Your command
string command = "convert...";
ProcessStartInfo procStartInfo = new ProcessStartInfo {CreateNoWindow = true};
string fileName = Environment.GetEnvironmentVariable("ComSpec");
if (String.IsNullOrEmpty(fileName))
{
// The "ComSpec" environment variable is not present
fileName = Environment.GetEnvironmentVariable("SystemRoot");
if (!String.IsNullOrEmpty(fileName))
{
// Try "%SystemRoot%\system32\cmd.exe"
fileName = Path.Combine(Path.Combine(fileName, "system32"), "cmd.exe");
}
if ((String.IsNullOrEmpty(fileName)) || (!File.Exists(fileName)))
{
// If the comd.exe is not present, let Windows try to find it
fileName = "cmd";
}
}
procStartInfo.FileName = fileName;
procStartInfo.RedirectStandardInput = true;
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
Process proc = Process.Start(procStartInfo);
proc.StandardInput.WriteLine(command);
proc.StandardInput.Flush();
Then we read from proc.StandardOutput in order to get error messages and result codes. Afterwards, we destroy the objects.
Sorry if this is not 100%, I copied it from a more complex OO code.

DOS based printing through ASP.NET

Well my situation is like this:
I am generating a report as a text file at the server which needs to be printed using DOS mode on a dot matrix printer. I want to avoid Windows printing because it would be too slow. Is there a way in ASP.NET through which I can carry out DOS based printing as it is best suited for Dot matrix printers. I have scoured the net but could not come across any solution or pointers. Does any body have any pointers/solutions which they might have implemented or stumbled across.
This application is a Web based application.
Thanx.
If I understand you right, one option is to execute a batch file that would do the actual printing from ASP.NET. From here: (Obviously, you can omit some of the code writing the output to the page)
// Get the full file path
string strFilePath = “c:\\temp\\test.bat”;
// Create the ProcessInfo object
System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo("cmd.exe");
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardError = true;
psi.WorkingDirectory = “c:\\temp\\“;
// Start the process
System.Diagnostics.Process proc = System.Diagnostics.Process.Start(psi);
// Open the batch file for reading
System.IO.StreamReader strm = System.IO.File.OpenText(strFilePath);
// Attach the output for reading
System.IO.StreamReader sOut = proc.StandardOutput;
// Attach the in for writing
System.IO.StreamWriter sIn = proc.StandardInput;
// Write each line of the batch file to standard input
while(strm.Peek() != -1)
{
sIn.WriteLine(strm.ReadLine());
}
strm.Close();
// Exit CMD.EXE
string stEchoFmt = "# {0} run successfully. Exiting";
sIn.WriteLine(String.Format(stEchoFmt, strFilePath));
sIn.WriteLine("EXIT");
// Close the process
proc.Close();
// Read the sOut to a string.
string results = sOut.ReadToEnd().Trim();
// Close the io Streams;
sIn.Close();
sOut.Close();
// Write out the results.
string fmtStdOut = "<font face=courier size=0>{0}</font>";
this.Response.Write(String.Format(fmtStdOut,results.Replace(System.Environment.NewLine, "<br>")));
The answer from BobbyShaftoe is correct. Here's a pedantic version of it:
public static void CreateProcess(string strFilePath)
{
// Create the ProcessInfo object
var psi = new ProcessStartInfo("cmd.exe")
{
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
RedirectStandardError = true,
WorkingDirectory = "c:\\temp\\"
};
// Start the process
using (var proc = Process.Start(psi))
{
// Attach the in for writing
var sIn = proc.StandardInput;
using (var strm = File.OpenText(strFilePath))
{
// Write each line of the batch file to standard input
while (strm.Peek() != -1)
{
sIn.WriteLine(strm.ReadLine());
}
}
// Exit CMD.EXE
sIn.WriteLine(String.Format("# {0} run successfully. Exiting", strFilePath));
sIn.WriteLine("EXIT");
// Read the sOut to a string.
var results = proc.StandardOutput.ReadToEnd().Trim();
// Write out the results.
string fmtStdOut = "<font face=courier size=0>{0}</font>";
this.Response.Write(String.Format(fmtStdOut,results.Replace(System.Environment.NewLine, "<br>")));
}
}

Resources