SQL CLR calling Process.Start hangs or fails - c#

I have checked and there are many posts similar but I cannot solve this. This is a SQL CLR proc to run an exe that parses PDF files. I can run same code as myself in console app. Permissions are not an issue. I am dumping to event log and the ProcessStartInfo is full formed. UseShellExecute - I am not certain. I have also created a .bat file to execute the code - run it manually - it runs fine. Via this CLR program ? Hangs or runs right away but does nothing. At wits end. My goal was to create the CLR using the Nuget from itext but I had a real hard time installing. SQL CLR doesnt support it but I tried anyway.
Thanks in advance.
[Microsoft.SqlServer.Server.SqlProcedure]
public static void PDFToCSVViaExe_CLR()
{
ProcessStartInfo startInfo = new ProcessStartInfo();
string args = #"\\app\Systems\Universal";
args = " \"" + args + "\"" + " \"" + "*" + "\"" + " \"" + "LVM" + "\"";
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = true;
startInfo.FileName = "c:\\SqlCLR\\PDFRipper\\PDFToCSV.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = args;
EventLog.WriteEntry(".NET Runtime", startInfo.FileName.ToString()+" " + args, EventLogEntryType.Warning, 1000);
string folder = "C:\\SqlCLR\\PDFRipper\\LVM.bat";
try
{
//using (new ImpersonationNamespace.Impersonation("domain", "user", "password"))
{
EventLog.WriteEntry(".NET Runtime", System.Security.Principal.WindowsIdentity.GetCurrent().Name + " OR " + Environment.UserName, EventLogEntryType.Warning, 1000);
folder = System.IO.Path.GetDirectoryName(folder);
if (!Directory.Exists(folder))
{
throw (new Exception("Directory does not exist for " + folder));
}
else
{ EventLog.WriteEntry(".NET Runtime", folder + " exists.", EventLogEntryType.Warning, 1000); }
// Start the process with the info we specified.
// Call WaitForExit and then the using statement will close.
using (Process exeProcess = Process.Start(startInfo))
{
exeProcess.WaitForExit();
}
}
}
catch (Exception ex)
{
using (EventLog EventLog = new EventLog("Application"))
{
EventLog.Source = "Application";
//eventLog.WriteEntry(ex.Message);
EventLog.WriteEntry(".NET Runtime", ex.Message + "Trace" + ex.StackTrace, EventLogEntryType.Warning, 1000);
//eventLog.WriteEntry(".NET Runtime", ex.Message, EventLogEntryType.Warning, 1000);
}
}

Related

Why does my WinForms code work fine but service fails to find file?

I want to make a Windows service that will monitor a path for a file. When one appears, it reads it and runs the program in the file. The structure of the command files is delay;path;filename;arguments. When testing this as a winforms app, it works great. But when I moved it to a service, it dies saying it cannot find the file.
I tried changing the service to run as my own AD account. I also tried adding code to log to the eventlog whether or not it can see the command file and the executable the command file should be running. While I know it's a terrible idea for production, just to test I set all related directories and files to have everyone:f NTFS permissions, but to no avail.
void onCreation(object sender, FileSystemEventArgs e) {
try {
Thread.Sleep(100);
if (File.Exists(e.FullPath)) {
log("Located cmd file [" + e.FullPath + "]", EventLogEntryType.Information);
} else {
log("Couldn't find cmd file [" + e.FullPath + "]", EventLogEntryType.Information);
}
string[] cmd = File.ReadAllText(e.FullPath).Split(';');
Process proc = new Process();
proc.StartInfo.WorkingDirectory = cmd[1];
proc.StartInfo.FileName = cmd[2];
proc.StartInfo.Arguments = cmd[3];
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
Dictionary<string, object> processData = new Dictionary<string, object>(){{"delay",cmd[0]},{"proc", proc},{"file",e.FullPath}};
Thread tmp = new Thread(new ParameterizedThreadStart(processThread));
tmp.Start(processData);
} catch (Exception ex) {
log("Error during onCreation: " + ex.Message, EventLogEntryType.Error);
}
}
void processThread(object procdata) {
Dictionary<string, object> processData = (Dictionary<string, object>)procdata;
try {
int delay = System.Convert.ToInt16(processData["delay"]);
Thread.Sleep(delay);
Process p = (Process)processData["proc"];
if (!File.Exists(p.StartInfo.WorkingDirectory + "\\" + p.StartInfo.FileName)) {
log("Couldn't find proc file [" + p.StartInfo.WorkingDirectory + "\\" + p.StartInfo.FileName + "]", EventLogEntryType.Information);
} else {
log("Located proc file [" + p.StartInfo.WorkingDirectory + "\\" + p.StartInfo.FileName + "]", EventLogEntryType.Information);
}
p.Start();
try {
File.Delete(processData["file"].ToString());
} catch (Exception ex) {
log("** Exception clearing file [" + processData["file"].ToString() + "]: " + ex.Message, EventLogEntryType.Warning, true);
}
} catch (Exception ex) {
log("Error during processThread: " + ex.Message, EventLogEntryType.Error);
log("Process data: [" + processData["delay"].ToString() + "][" + processData["file"].ToString() + "][" + ((Process)processData["proc"]).StartInfo.WorkingDirectory + "][" + ((Process)processData["proc"]).StartInfo.FileName + "][" + ((Process)processData["proc"]).StartInfo.Arguments + "]", EventLogEntryType.Information);
}
}
I have my config setting the listenpath to d:\misc\sites----.com\cmds then I say "Alexa, trigger fan test" and my web server generates a file in that folder like: 0;d:\misc\iot;wemo.exe;10.0.0.72 on; for it to process. It sees it and I get the following eventlog entries:
Located cmd file [d:\sites\----\www\cmds\15659086948907.dat]
Located proc file [d:\misc\iot\wemo.exe]
Error during processThread: The system cannot find the file specified
Process data: [d:\sites\----\www\cmds\15659086948907.dat][d:\misc\iot][wemo.exe][10.0.0.72 off]
What is it about being in a service that is making it fail? Thanks!

Diagnostic Process ends with exit code 1 but same action on command prompt works

My code uses a C# Diagnostic Process to run a GDAL process.
This process ends with an exit code 1.
But running from a command prompt works.
Where's my mistake?
Already tested (see code below):
files to transform exists,
directory to write to exists and "My programme" has access rights,
the GDAL library exists.
This is my code:
private string AddSrs(string tempFile, string User)
{
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
string geoserverDatadir = ConfigurationManager.AppSettings["geoserverDatadir"];
string dirOut = Path.Combine(geoserverDatadir, User, Guid.NewGuid().ToString());
string fileOut = Path.Combine(dirOut, (Path.GetFileNameWithoutExtension(tempFile) + ".geoTiff"));
Directory.CreateDirectory(dirOut);
if (File.Exists(fileOut))
{
File.Delete(fileOut);
}
string binDirectory = ConfigurationManager.AppSettings["binDirectory"];
startInfo.FileName = Path.Combine(binDirectory, "gdal_translate.exe");
string args = String.Format(#"-a_srs EPSG:28992 {0}{1}{0} {0}{2}{0}", "\"", tempFile, fileOut);
startInfo.Arguments = args;
process.StartInfo = startInfo;
if(!File.Exists(startInfo.FileName))
{
_log.Error("file not exists: " + startInfo.FileName));
}
if (!File.Exists(tempFile))
{
_log.Error("file not exists: " + tempFile));
}
if (!Directory.Exists(dirOut))
{
_log.Error("directory not exists: " + dirOut));
}
try
{
// Attempt to get a list of security permissions from the folder.
// This will raise an exception if the path is read only or do not have access to view the permissions.
System.Security.AccessControl.DirectorySecurity ds = Directory.GetAccessControl(dirOut);
}
catch (UnauthorizedAccessException ex)
{
_log.Error("no access rights for directory: " + dirOut));
}
try
{
process.Start();
int processTimeOut = 1000;
if (!process.WaitForExit(processTimeOut))
{
process.Kill();
_log.Error("Process killed by timeOut: " + processTimeOut));
return string.Empty;
}
else
{
var exitCode = process.ExitCode;
_log.Error("Process ended. Exitcode: " + exitCode));
return fileOut;
}
}
catch (Exception ex)
{
_log.Error(ex.Message));
_log.Error(ex.StackTrace));
return string.Empty;
}
}
EDIT:
This is the full command as logged in my logfile:
D:\OSGeo4W64\bin\gdal_translate.exe -a_srs EPSG:28992 "D:\data\Temp\Merkator\Hengelo Veldwijk Zuid Revisie.temp" "D:\data\Geoserver\data\Merkator\aa84dc6d-aff2-4254-975a-3ede8eea5c6d\Hengelo Veldwijk Zuid Revisie.geoTiff"
And this is the same command pasted in commandline (works with and without admin rights):
C:\Users\Administrator>D:\OSGeo4W64\bin\gdal_translate.exe -a_srs EPSG:28992 "D:\data\Temp\Merkator\Hengelo Veldwijk Zuid Revisie.temp" "D:\data\Geoserver\data\Merkator\aa84dc6d-aff2-4254-975a-3ede8eea5c6d\Hengelo Veldwijk Zuid Revisie.geoTiff"
Input file size is 1273, 378
0...10...20...30...40...50...60...70...80...90...100 - done.
INFO:
The problem exists on a (virtual) server. On my computer (debug-mode) this code works fine.

running a exe file from web api on iis server not working

I want to execute an exe file on to The Web API as and when user request comes. It is working perfectly but when I am hosting web API to server the exe file is not executed when user request comes. What to do for executing the exe file from web API on IIS server?
Here is the process starting code:
public static void Start(long campaign_id, long contact_id, string startDate, string endDate, string user)
{
try
{
//WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.WorkingDirectory = #"C:\";
startInfo.Arguments = "/c sparkclr-submit --master " + ConfigurationManager.AppSettings["SparkMaster"] + " --driver-class-path " + AppDomain.CurrentDomain.BaseDirectory + "Engine\\mysql.jar " + "--exe CmAnalyticsEngine.exe " + AppDomain.CurrentDomain.BaseDirectory + "Engine " + campaign_id + " " + contact_id + " " + startDate + " " + endDate + " " + user;
process.StartInfo = startInfo;
process.Start();
}
catch (Exception e)
{
LogWritter.WriteErrorLog(e);
}
}
How are you starting the exe? You have any error logs?
You can try using the verb runas in Process.Start to execute the exe file as an Administrator.
ProcessStartInfo proc = new ProcessStartInfo();
proc.WindowStyle = ProcessWindowStyle.Normal;
proc.FileName = myExePath;
proc.CreateNoWindow = false;
proc.UseShellExecute = false;
proc.Verb = "runas"; //this is how you pass this verb

Executing Process not working

The situation:
I want to modify the folder quotas on my FileServer through a process executing dirquota.exe
The Problem:
The Process being executed gives no result at all
So Far:
I've redirected the process and arguments being executed on my FileServer to take a closer look what's happening exactly on the serverside.
The executed process gave no exception and everything went just fine, it seemed..
When looking at the current folder quota's on my FileServer nothing has changed..I decided to copy paste my arguments in a CMD.exe on the server, then it all went fine...
I cannot figure why it is not working on my FileServer, probably somthing simple but I need some help here
Important Info:
I'm installing a Windows Service on my FileServer and calling the Method through SOUPUI (This is all working fine).
The installed service is running as a Domain admin and has all the required rights to perform these actions
The Class
public class Quota
{
public string FolderLocation;
public int SizeInMB;
public string FileServerName;
}
The Method
public string SetFolderQuota(Quota quota)
{
Process QuotaProcess = new Process();
QuotaProcess.StartInfo.RedirectStandardOutput = false;
QuotaProcess.StartInfo.FileName = #"cmd.exe";
QuotaProcess.StartInfo.UseShellExecute = true;
QuotaProcess.StartInfo.Arguments = "/C " + "dirquota Quota Add /PATH:" + '"' + quota.FolderLocation + '"' + " /Limit:" + quota.SizeInMB + "mb" + " /remote:" + quota.FileServerName;
try
{
QuotaProcess.Start();
}
catch(Exception Ex)
{
return Ex.Message;
}
return "Correctly Executed: " + QuotaProcess.StartInfo.FileName + QuotaProcess.StartInfo.Arguments;
}
Found The Problem
dirquota.exe is redirected using Windows-on Windows 64-bit redirection. What's happening is that my launch request (from a 32-bit process) is being redirected to %windir%\SysWOW64\dirquota.exe. Since there's no 32-bit version of this particular executable on 64-bit installs, the launch fails. To bypass this process and allow my 32-bit process to access the native (64-bit) path, I have to reference %windir%\sysnative instead
The Code
public string SetFolderQuota(Quota quota)
{
string FileLocation = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows),#"sysnative\dirquota.exe");
Process QuotaProcess = new Process();
QuotaProcess.StartInfo.RedirectStandardOutput = false;
QuotaProcess.StartInfo.FileName = FileLocation;
QuotaProcess.StartInfo.UseShellExecute = true;
QuotaProcess.StartInfo.Arguments = " Quota Add /PATH:" + '"' + quota.FolderLocation + '"' + " /Limit:" + quota.SizeInMB + "mb" + " /remote:" + quota.FileServerName;
try
{
QuotaProcess.Start();
}
catch(Exception Ex)
{
return Ex.Message + Environment.NewLine + "FileLocation: " + FileLocation;
}
return "Correctly Executed: " + QuotaProcess.StartInfo.FileName + QuotaProcess.StartInfo.Arguments;
}
Best if you can redirect the output of Process to a log file and see what is the actual exception..
ProcessStartInfo process = new ProcessStartInfo
{
CreateNoWindow = false,
UseShellExecute = false,
RedirectStandardOutput = true,
FileName = #"cmd.exe",
Arguments = "/C " + "dirquota Quota Add /PATH:" + '"' + quota.FolderLocation + '"' + " /Limit:" + quota.SizeInMB + "mb" + " /remote:" + quota.FileServerName
};
Process p = Process.Start(process);
string output = p.StandardOutput.ReadToEnd();
Log the value of output to get the exact exception caused by execution of this command

UseShellExecute unable to find file

public void BuildMod()
{
var startIngo = new ProcessStartInfo();
startIngo.WorkingDirectory = ModBuilderLoc;
startIngo.FileName = "ModPack Builder.exe";
startIngo.Arguments = "\"" +
LoadedMod.Directory.Substring(Folders.MyDocuments.Length + 28)
+ "\"" + " " + "true";
startIngo.WindowStyle = ProcessWindowStyle.Normal; //TODO: Set to hidden
//startIngo.UseShellExecute = false;
//startIngo.RedirectStandardOutput = true;
try
{
Process proc = new Process();
proc.StartInfo = startIngo;
proc.Start();
//proc.StandardOutput.ReadLine();
proc.WaitForExit();
MessageBox.Show("Build successful", "Build Info");
}
catch (Win32Exception)
{
MessageBox.Show("Could not find \"ModPack Builder.exe\" in \""
+ ModBuilderLoc +"\", change from menu bar");
}
}
This works perfectly fine, unless I uncomment the comments, which makes the program read the first line to my program's console.
When the comments are uncommented, a Win32 exception is caught, which I do not want happening.

Categories

Resources