My program prints silently via the PDF reader Foxit Reader in a new process.
On occasion, my program attempts to print two PDFs at the same time, which causes one of them to fail to print.
Here is my code:
string filename = "file.pdf";
string fileDir1 = #"C:\Program Files (x86)\Foxit Software\Foxit Reader\FoxitReader.exe";
Process pdfProcess = new Process();
pdfProcess.StartInfo.FileName = fileDir1;
pdfProcess.StartInfo.Arguments = string.Format(#"/t {0} {1}", filename ,"pos-80");
pdfProcess.StartInfo.CreateNoWindow = true;
pdfProcess.StartInfo.WorkingDirectory = Path.GetDirectoryName(fileDir1);
pdfProcess.Start();
if (!pdfProcess.WaitForExit(2500))
{
pdfProcess.Kill();
}
Please help me resolve this issue.
Make sure you have Foxit open.
using System.Diagnostics;
List<Process> Processlist = Process.GetProcesses().ToList();
This gives you a list of currently running processes.
foreach(Process p in Processlist)
{
Console.WriteLine("Process " + p.Id + " is named '" + p.ProcessName + "'");
}
When running the above code, you should see the name of the Foxit process in your output window.
Alternatively, put a break-point on the foreach line and hover over the list to see all the names that way.
bool IsFoxitProcessRunning = false;
foreach(Process p in Processlist)
{
if(p.ProcessName == "Foxit process name here") //Replace with the name of the foxit process
{
IsFoxitProcessRunning = true;
}
}
Now, only start a new Foxit process if one isn't already running.
if(!IsFoxitProcessRunning)
{
//insert code to run next foxit process here.
}
Notes:
You may need to implement a queue to keep track of pdfs waiting to run.
You may also wish to alert IT support if a Foxit is waiting more 5 or 10 mins to run.
You could choose to make Processlist a class attribute, and periodically refresh Processlist using a Timer, by calling Processlist = Process.GetProcesses().ToList(); on the Tick event. every 30 seconds or so while a PDF is waiting to be printed.
Related
I didnt found a good (free) and simple Solution for printing PDFs (for e.g. from a "Hot"-Folder (FileSystemWatcher) on a Server) with Acrobat and close Acrobat Reader. So i wrote my own and i hope it will help someone.
(Yes, u can use a old free Foxit Reader Version, but we had too much trouble with it, sometimes stuck in Memory without printing)
The Point was, after printing, the file must be moved to a archive dir, but Adobe did not close. So i never knowed when its done, or wait 30+ Seconds and kill (not so fine if the Server needs longer and takes to much time).
Here my Solution, i run the Process and wait until one of the subprocesses of my Adobe Process shows the recent open Window.
Thanks to mtijn for his "Process Searcher" solution https://stackoverflow.com/a/7189381/480982
var prz = Process.Start("C:\\Program Files (x86)\\Adobe\\Acrobat Reader DC\\Reader\\AcroRd32.exe", "/h /t \"" + YOURPDFFILE + "\" \"" + YOURPRINTER + "\"");
bool loop = true;
while (loop)
{
//u can use Thread.Sleep(x) too;
prz.WaitForExit(500);
ManagementObjectSearcher searcher = new ManagementObjectSearcher(
"SELECT * " +
"FROM Win32_Process " +
"WHERE ParentProcessId=" + prz.Id);
ManagementObjectCollection collection = searcher.Get();
if (collection.Count > 0)
{
foreach (var item in collection)
{
UInt32 childProcessId = (UInt32)item["ProcessId"];
if ((int)childProcessId != Process.GetCurrentProcess().Id)
{
Process childProcess = Process.GetProcessById((int)childProcessId);
//If a File is open the Title begins with "Filename - Adobe ...", but after print/closing the recent window starts with "Adobe Acr..."
if(childProcess.MainWindowTitle.StartsWith("Adobe Acrobat"))
{
loop = false;
break;
}
}
}
}
}
//"Recent" Window found, lets kill the Process
prz.Kill();
// Now here u can move or Delete the pdf file
My requirement is to open InternetExplorer, wait till the page loads, Close that particular instance of IE, and do the same for the rest of the urls.
The URL's are saved in an Array.
Attaching the code I have done so far.
I'm just opening the Browser, passing Url as a parameter, and killing the process.
Any Help would be appreciated.
foreach (var WebPage in YearUrlLoop)
{
ProcessStartInfo Browser = new ProcessStartInfo("IExplore.exe", WebPage);
Process p = Process.Start(Browser);
System.Threading.Thread.Sleep(5000);
p.WaitForExit();
Process[] ps = Process.GetProcessesByName("IEXPLORE");
foreach (Process prc in ps)
{
prc.Kill();
}
}
Is there a way to kill certain instances of the mstsc process.
For example, I rdp to pc1.xyz.com.au and pc2.xyz.com.au.
Now from c#, I want to kill or disconnect pc1.xyz.com.au.
Currently the code below kills all the instances of mstsc process.
Is there any way I can disconnect only certain mstsc instances.
private void terminateRDP()
{
foreach (var process in Process.GetProcessesByName("mstsc"))
{
process.Kill();
}
}
I tried saving the pid of the process that is opened but the capture pid that i captured is different than the one in the task bar. I am opening a .rdp file using code below.
Process rdcProcess = new Process();
rdcProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
rdcProcess.StartInfo.FileName = Environment.ExpandEnvironmentVariables(#"%SystemRoot%\system32\cmdkey.exe");
rdcProcess.StartInfo.Arguments = "/generic:TERMSRV/" + server + " /user:" + username + " /pass:" + password;
rdcProcess.Start();
rdcProcess.WaitForExit();
changeServerRDP(serverAddress);
if (getApplicationPath(serverList.SelectedItem.ToString()) != String.Empty)
{
changeServerRDPPath(getApplicationPath(serverList.SelectedItem.ToString()));
rdcProcess.StartInfo.FileName = Environment.ExpandEnvironmentVariables(#"%SystemRoot%\system32\mstsc.exe");
rdcProcess.StartInfo.Arguments = "C:\\rdp\\my.rdp";
rdcProcess.Start();
rdcProcess.WaitForExit();
//pids.Add(rdcProcess.Id);
//int procID = rdcProcess.Id;
//MessageBox.Show(procID.ToString());
//opened.Add(rdcProcess);
}
If you need to terminate RDP session, You can try: WTSDisconnectSession API
This stackoverflow link explains how to use it in C#
I have the following function:
public static void ExecuteNewProcess(string fileToExecute, Action<string> writeToConsole)
{
ProcessStartInfo startInfo = new ProcessStartInfo(fileToExecute);
Process processToExecute = new Process();
startInfo.UseShellExecute = true;
processToExecute.StartInfo = startInfo;
if (!File.Exists(fileToExecute))
{
throw new FileNotFoundException("File not found for execution");
}
if (processToExecute.Start())
{
Thread.Sleep(6000);
Process[] procs = Process.GetProcesses();
if (IsProcessOpen(Path.GetFileNameWithoutExtension(fileToExecute)))
{
writeToConsole(fileToExecute + " launched successfully...");
}
else
{
writeToConsole(fileToExecute + " started but not found.");
throw new Exception("Application started butnot found running...Delay = 6000, File Name = " + Path.GetFileNameWithoutExtension(fileToExecute));
}
}
else
{
writeToConsole("Error Launching application: " + fileToExecute);
throw new Exception("Application did not launch " + fileToExecute);
}
}
private static bool IsProcessOpen(string name)
{
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.Contains(name))
{
return true;
}
}
return false;
}
So the problem is that sometimes my application that I am trying to start with this function is not starting (It starts about 80% of the time). However I do go through the part of the code that checks to make sure it started and outputs as such. I am not sure why it is not starting. I double click the application when I see it doesnt start to make sure its a valid exe. It always is and starts fine. I have also tried using the shell and not using the shell. No difference.
I am thinking that processToExecute is getting cleaned up before the application has successfully started all the way. Just a guess though.
I appreciate your help in advance.
I put in a few sleeps to see if it was just happening too fast.
The reason 20% of time your application don't show up when started by Process because of the time the application takes load before we see the user Interface
So their are two ways through which you might be able to achieve it
1. start the process - > process.Start(); And then process.WaitForInputIdle();
OR
2. start the process - > process.Start(); And then Thread.Sleep(1000);
//make sure you give reasonable milliseconds
I am running a separate process that minimizes a folder of javascript files. This process creates a new file for each of the js files with "_min.js" appended to it. The next step is to delete the old js files (the ones without "_min.js"). For some reason File.Delete cannot delete these files.
It would appear that some process still has a handle on these files. I get a System.UnauthorizedAccessException exception when I attempt the delete. I have sufficient privileges to this folder. Can someone tell me what I am overlooking?
I am running the process several times in this loop.
foreach (var fileInfo in jsFiles)
{
var outFileName = fileInfo.FullName.Replace(".js", "_min.js");
var compressorPath = "\"C:\\Dev\\Team Interactive Tools\\trunk\\Infrastructure\\MsBuild\\lib\\yuicompressor-2.4.2.jar\"";
StringBuilder stringBuilder = new StringBuilder("-jar " + compressorPath + " ");
stringBuilder.Append("\"" + fileInfo.FullName + "\"");
stringBuilder.Append(" -o " + "\"" + outFileName + "\"");
Process p = new Process();
p.StartInfo.FileName = "\"C:\\Program Files (x86)\\Java\\jre6\\bin\\java\"";
p.StartInfo.Arguments = stringBuilder.ToString();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
}
return true;
}
Then I try to remove the orginals:
private void RemoveOrginalJs(FileInfo[] files)
{
foreach (var fileInfo in files)
{
File.Delete(fileInfo.FullName);
}
}
I am tried Process.close() after each process run but it makes no differance.
I don't know the tool that you are starting, but waiting for its completion somehow seems the right thing to do:
p.Start();
p.WaitForExit();
Maybe the threads still have the file locked? Do you wait for them to finish before you try and delete?
Try Process.Kill() and delete afterwards.
Further you have to check if the script isn't running in another process aswell. To determinate this, try using Unlocker.