How to provide page range in process print request - c#

I have a document which I am sending to print using below c# code
p.StartInfo = new ProcessStartInfo()
{
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
Verb = "print",
FileName = FileToPrintPath//put the correct path here
};
p.Start();
Now, I have a condition where instead of printing whole document I want to print juts from page number 2 to 5. How can I do this?

I don't know the direct answer to your question but you can easily figure this out with using the code below. Show a dialog and choose page number, number of copies etc. and see how it appears in printDialog1.PrinterSettings. once you know the format, remove the dialog code and hardcode it into Arguments:
using (PrintDialog printDialog1 = new PrintDialog())
{
if (printDialog1.ShowDialog() == DialogResult.OK)
{
var info = new ProcessStartInfo(**FILENAME**);
info.Arguments = "\"" + printDialog1.PrinterSettings.PrinterName + "\"";
// Use the debugger a message dialog to see
// contents of printDialog1.PrinterSettings
}
}
I wrote a quick test and here is what was stored in PrinterSettings:
[PrinterSettings Microsoft XPS Document Writer Copies=1 Collate=False Duplex=Simplex FromPage=0 LandscapeAngle=270 MaximumCopies=1 OutputPort=PORTPROMPT: ToPage=0]
So you need to pass FromPage and ToPage:
info.Arguments = "\"" + printDialog1.PrinterSettings.PrinterName + "\"" + "FromPage=2 ToPage=5";
In your code:
p.StartInfo = new ProcessStartInfo()
{
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
Verb = "print",
FileName = FileToPrintPath,//put the correct path here,
Arguments = "\"Printer Name Goes Here\" FromPage=2 ToPage=5";
};
Please not they are space separated arguments and if your printer name has spaces, you need to put the printer name within quotations.

Related

Issue WSL commands and read returned value from C#

I am writing a code to execute some commands against wsl, parsing and reading the returned value is important.
Project is a .net core console app 3.1
wsl2 is enabled on the system
for example, listing all the available wsl images on my local machine i am using a snippet found in an answer provided in another "kind of related" SO post.
using (var proc = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = #"cmd.exe",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
CreateNoWindow = true,
}
})
{
proc.Start();
proc.StandardInput.WriteLine("wsl --list");
System.Threading.Thread.Sleep(500);
proc.StandardInput.Flush();
proc.StandardInput.Close();
proc.WaitForExit(5000);
var c = proc.StandardOutput.ReadToEnd();
Console.WriteLine(c);
Console.ReadLine();
}
now the expected output should be
what i am getting is
if i inspect using breakpoint i get this in "var c"
Ideally i want to be able to have a list that contains the 2 dockers items inside C#, changing the wait time didn't help.
in the ProcessStartInfo you have to set
StandardOutputEncoding = Encoding.Unicode;
StandardErrorEncoding = Encoding.Unicode;
for direct call of wsl use additionally:
FileName = #"wsl.exe";
Arguments = #"-l -v";

C# Create Detached Process on Linux

I am writing a software update process on Linux. Application is .NET 5 RC1 (Sept 15 2020 release). When a certain packet is received by my application, it downloads the software update to a sub-folder then spawns off the executable to perform the software update.
Unfortunately, using Process.Start and ProcessStartInfo seems to create a process that is attached to the main process. Since the software update must stop the process in order to update it, it also gets stopped because it is a child of the process, having been spawned via Process.Start.
How do I create a detached process on Linux? On Windows I am using PInvoke and the CreateProcess API with the DETACHED_PROCESS flag, see the following:
var processInformation = new ProcessUtility.PROCESS_INFORMATION();
var startupInfo = new ProcessUtility.STARTUPINFO();
var sa = new ProcessUtility.SECURITY_ATTRIBUTES();
sa.Length = Marshal.SizeOf(sa);
CreateProcess(null, "\"" + fileName + "\" " + arguments, ref sa, ref sa, false, DETACHED_PROCESS, IntPtr.Zero, Path.GetDirectoryName(fileName), ref startupInfo, out processInformation);
Here is my code for Linux. I had read that appending & to a process on Linux creates it detached, but that does not appear to be the case.
ProcessStartInfo info = new ProcessStartInfo
{
// Linux uses " &" to detach the process
Arguments = arguments + " &",
CreateNoWindow = true,
FileName = fileName,
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Hidden,
WorkingDirectory = Path.GetDirectoryName(fileName)
};
Process.Start(info);
I was unable to get nohup or disown to work from C#. Killing the parent process always resulted in the child process being terminated as well.
I ended up using at, which can be installed via sudo apt install at. The atd service is installed and will stay running even when rebooted.
Here is the C# code that I used:
// the following assumes `sudo apt install at` has been run.
string fileName = "[your process to execute]";
string arguments = "[your command line arguments for fileName]";
string argumentsEscaped = arguments.Replace("\"", "\\\"");
string fullArgs = $"-c \"echo sudo \\\"{fileName}\\\" {argumentsEscaped} | at now\"";
ProcessStartInfo info = new()
{
Arguments = fullArgs,
CreateNoWindow = true,
FileName = "/bin/bash",
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Hidden,
WorkingDirectory = Path.GetDirectoryName(fileName)
};
using var process = Process.Start(info);
process.WaitForExit();
// make sure to check process.ExitCode == 0
For me, setsid in combination with & makes a spawned child process out-living its parent process when invoked via sh -c.
Example:
var command = $"dotnet \"PathToDll\" param1 param2";
process.StartInfo = new ProcessStartInfo
{
Arguments = $"-c \"setsid {command.Replace("\"", "\\\"")} &\"",
CreateNoWindow = true,
FileName = "/bin/sh",
};
process.Start();
This was tested on Debian and Ubuntu.
Slightly refactored version of #jjxtra solution, so it's easier to understand what's going on in the arguments.
Btw, the echo is not an example, but the way of executing at command.
string command = $"actual command to run";
string atdCommand = $#"echo \""{command}\"" | at now";
string bashCommand = $#"-c ""{atdCommand}"" ";
ProcessStartInfo psi = new ProcessStartInfo
{
FileName = "/bin/bash",
Arguments = bashCommand,
...
};

C# Console Application: How do I open a textfile maximized?

Hello! (I'm new to StackOverflow)
I have a question concerning C# Console.
I want to open a .txt File which is in the same directory.
This is my Code (the name of the text file is README.txt):
string path = System.IO.Directory.GetCurrentDirectory() + #"\README.txt";
string[] FileContents = System.IO.File.ReadAllLines(path);
System.Diagnostics.Process.Start(path);
The code works fine, but I want the text file to be opened maximized. How do I make this?
By specifying the ProcessStartInfo parameters:
string notepadPath = Environment.SystemDirectory + "\\notepad.exe";
var startInfo = new ProcessStartInfo(notepadPath)
{
WindowStyle = ProcessWindowStyle.Maximized,
Arguments = "README.txt"
};
Process.Start(startInfo);

C# Process.Start() - target app can't find file

I'm trying to start application "GA.exe", but on start it's taking data from file "acc.txt".
If I start it normallly (via double click :-)) it works, but if I use code below it say "Can't find acc.txt".
My first idea:
Process.Start(pathToGA.exe);
Second idea:
ProcessStartInfo pinfo = new ProcessStartInfo()
{
Arguments = FolderWithGA.exePath,
FileName = pathToGA.exe,
};
And both don't work.
You should set ProcessStartInfo.WorkingDirectory to the directory that holds acc.txt and GA.exe:
ProcessStartInfo pinfo = new ProcessStartInfo()
{
Arguments = FolderWithGA.exePath,
FileName = pathToGA.exe,
WorkingDirectory = FolderWithGA
};

Is there anyway to specify a PrintTo printer when spawning a process?

What I Have
I am currently writing a program which takes a specified file and the performs some action with it. Currently it opens it, and/or attaches it to an email and mails it to specified addresses.
The file can either be of the formats: Excel, Excel Report, Word, or PDF.
What I am currently doing is spawning a process with the path of the file and then starting the process; however I also am trying to fix a bug feature that I added which adds the verb 'PrintTo' to the startup information, depending on a specified setting.
What I Need
The task I am trying to accomplish is that I would like to have the document open and then print itself to a specified printer named within the program itself. Following that up, the file should then close itself automatically.
If there is no way to do this generically, we might be able to come up with a way to do it for each separate file type.
What you Need
Here is the code I'm using:
ProcessStartInfo pStartInfo = new ProcessStartInfo();
pStartInfo.FileName = FilePath;
// Determine wether to just open or print
if (Print)
{
if (PrinterName != null)
{
// TODO: Add default printer.
}
pStartInfo.Verb = "PrintTo";
}
// Open the report file unless only set to be emailed.
if ((!Email && !Print) || Print)
{
Process p = Process.Start(pStartInfo);
}
How I'm doing...
Still stumped... might call it like Microsoft does,'That was by design'.
The following works for me (tested with *.doc and *.docx files)
the windows printto dialog appears by using the "System.Windows.Forms.PrintDialog" and for the "System.Diagnostics.ProcessStartInfo" I just take the selected printer :)
just replace the FILENAME with the FullName (Path+Name) of your Office file. I think this will also work with other files...
// Send it to the selected printer
using (PrintDialog printDialog1 = new PrintDialog())
{
if (printDialog1.ShowDialog() == DialogResult.OK)
{
System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo(**FILENAME**);
info.Arguments = "\"" + printDialog1.PrinterSettings.PrinterName + "\"";
info.CreateNoWindow = true;
info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
info.UseShellExecute = true;
info.Verb = "PrintTo";
System.Diagnostics.Process.Start(info);
}
}
Theoretically, according to an article on MSDN you should be able to change it to be along the lines of (untested):
// Determine wether to just open or print
if (Print)
{
if (PrinterName != null)
{
pStartInfo.Arguments = "\"" + PrinterName + "\"";
}
pStartInfo.CreateNoWindow = true;
pStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
pStartInfo.UseShellExecute = true;
pStartInfo.WorkingDirectory = sDocPath;
pStartInfo.Verb = "PrintTo";
}
get from Rowland Shaw:
ProcessStartInfo startInfo = new ProcessStartInfo(Url)
{
Verb = "PrintTo",
FileName = FilePath,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = true,
Arguments = "\"" + PrinterName+ "\"",
};
Process.Start(startInfo);
FilePath look like 'D:\EECSystem\AttachedFilesUS\53976793.pdf'
PrinterName is your printer name
copy the code,it will work.

Categories