Run a command line command from WPF application - wpf

After seeing a youtube video I tested this code:
string cmd1 = #"xcopy c:\A\*.* c:\b";
Process ps = new Process();
ps.StartInfo.FileName = "cmd.exe";
ps.StartInfo.CreateNoWindow = true;
ps.StartInfo.RedirectStandardInput = true;
ps.StartInfo.RedirectStandardOutput = true;
ps.StartInfo.UseShellExecute = false;
ps.Start();
ps.StandardInput.WriteLine(cmd1);
ps.StandardInput.Flush();
ps.StandardInput.Close();
ps.WaitForExit();
Console.WriteLine(ps.StandardOutput.ReadToEnd());
The command is executed but i see no output.
What do i need to do to make visible the cmd window and the command output?
Thanks

If you want to execute your command in the cmd.exe window, you can do it like this.
var process = new Process();
var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = #"/K xcopy c:\A\*.* c:\b"
};
process.StartInfo = startInfo;
process.Start();
Note that /K keeps the command line window open, replace it with /C to automatically close it after copying.
If you want to start xcopy without showing the console window and collecting the output to show it where you want, use this.
var process = new Process();
var startInfo = new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Hidden,
FileName = "xcopy",
Arguments = #"c:\A\*.* c:\b",
RedirectStandardOutput = true
};
process.StartInfo = startInfo;
process.Start();
var output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
// Print the output to Standard Out
Console.WriteLine(output);
// Print the ouput to e.g. Visual Studio debug window
Debug.WriteLine(output);
Note that this only works as expected, if your B folder exists folder does not already contain any of your files. Otherwise, the window will stay open, because you are asked, whether the directory should be created and the files should be overwritten. To not overcomplicate this by writing input, you could use the following arguments for xcopy.
Arguments = #"c:\A\*.* c:\b\ /Y /I"
The /Y switch will overwrite files without asking and /I will create a non-existing directory. It is mandatory for this to work to have a trailing backslash on your destination directory path (c:\b\ instead of c:\b).

Related

How to achieve same print functionality of Silverlight into WPF?

We are migrating our SilverLight application into WPF, in our application for printing we have used System.Windows.Printing. Same namespace is not available in WPF it has System.Drawing.Printing namespace, due to this existing functionality is not working as expected. We need to write the new printing for this. Is there any way we can achieve the same without writing new code.
Implementation of printing a file with a choice of printer in WPF
private static void PrintFile(string pathToFile)
{
PrintDialog pDialog = new PrintDialog();
bool? print = pDialog.ShowDialog();
if (print == true)
{
string printerName = pDialog.PrintQueue.FullName;
Process p = new Process
{
StartInfo = new ProcessStartInfo()
{
Arguments = "\"" + printerName + "\"",
CreateNoWindow = true,
Verb = "PrintTo",
FileName = pathToFile
}
};
p.Start();
}
}

how to start console application with windows application and read (monitoring) command line - line by line real time in c#

I have a console application which generating rows line by line:
Data1
Data2
Data3
...
and when its over command line will be cleared, it reapeats infinitelly (the datas can change)
I have to watch the console application's command line with windows aplication real time and work for the lines data (for example save it to list ox line by line)! It is possible?
You basically need to subscribe to the output streams of that console application, to be able to get each line printed on the console.
What you need to do is to create the Windows Forms application (WPF would also work) and start the console application from there.
If you don't want to show your current console application as a visible window, remember to set CreateNoWindow to true.
Here's how to start the console application:
var processStartInfo = new ProcessStartInfo(fileName, arguments);
processStartInfo.UseShellExecute = false;
processStartInfo.ErrorDialog = false;
processStartInfo.RedirectStandardOutput = true; // We handle the output
processStartInfo.CreateNoWindow = true; // If you want to hide the console application so it only works in the background.
// Create the actual process
currentProcess = new Process();
currentProcess.EnableRaisingEvents = true;
currentProcess.StartInfo = processStartInfo;
// Start the process
bool processDidStart = currentProcess.Start();
We need a BackgroundWorker to read the output from the console application in the background.
outputReader = TextReader.Synchronized(currentProcess.StandardOutput);
outputWorker.RunWorkerAsync();
Now you're able to get all the output from the console application in real time and use it to create a list or whatever you want to.
void outputWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Work until cancelled
while (outputWorker.CancellationPending == false)
{
int count = 0;
char[] buffer = new char[1024];
do
{
StringBuilder builder = new StringBuilder();
// Read the data from the buffer and append to the StringBuilder
count = outputReader.Read(buffer, 0, 1024);
builder.Append(buffer, 0, count);
outputWorker.ReportProgress(0, new OutputEvent() { Output = builder.ToString() });
} while (count > 0);
}
}
The processed data is available through the ProgressChanged event of the BackgroundWorker.
void outputWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.UserState is OutputEvent)
{
var outputEvent = e.UserState as OutputEvent;
/* HERE YOU CAN USE THE OUTPUT LIKE THIS:
* outputEvent.Output
*
* FOR EXAMPLE:
* yourList.Add(outputEvent.Output);
*/
}
}
The above code is taken and modified to your purposes from the following Codeproject.com article in case it ceases to exist in the future: Embedding a Console in a C# Application.

Attach a PDF File to a Print Dialog

I'm trying to attach a PDF File to a Print Dialog, but I haven't find out the way to do it.
I'm using a WPF app, and I have some code related with printing and looks like this:
private void Imprimir()
{
try
{
FixedDocument document = null;
PageContent pageContent = null;
FixedPage fixedPage = null;
PrintDialog printDlg = new PrintDialog();
if (printDlg.ShowDialog() != true)
return;
document.DocumentPaginator.PageSize = new System.Windows.Size(1400, 1450);
fixedPage.Width = document.DocumentPaginator.PageSize.Width;
fixedPage.Height = document.DocumentPaginator.PageSize.Height;
fixedPage.Margin = new Thickness(96, 96, 0, 0);
fixedPage.Children.Add(this);
((System.Windows.Markup.IAddChild)pageContent).AddChild(fixedPage);
document.Pages.Add(pageContent);
printDlg.PrintDocument(document.DocumentPaginator, "Impresion Cierre");
fixedPage.Children.Clear();
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.Message);
}
}
But, by this way I'm just printing a UI Element added to Fixed Page.
I've looked for other codes, but I find nothing.
So, I donĀ“t know if is possible to add a PDF File stored locally to the Print Dialog ?
Thanks for the help...
Well you cannot do this using PrintDialog. There are several options, depending on your goals:
var printQueue = LocalPrintServer.GetDefaultPrintQueue();
using (var input = File.OpenRead("path_to_your.pdf")) {
using (var job = printQueue.AddJob()) {
using (var output = job.JobStream) {
input.CopyTo(output);
}
}
}
Will silently send print job for your file to local print queue. Print job is configurable.
Alternatively you can use adobe reader to handle that for you (or another pdf reader installed on user's machine) but starting process with path to your pdf as FileName and Verb="print".
One more option is to use third party tools (like ghostscript) which can help you with that.

How to execute batch file from Java code?

im trying to invoke a batch file from java code. I have tried answers from the SO forum.
File ff = new File(".");
String pt = ff.getCanonicalPath()+"\\Selenium APIs";
String pt1 = ff.getCanonicalPath()+"\\Selenium APIs\\Start Selenium Server.bat";
String[] command = {"cmd.exe", "/C", "Start", pt1};`enter code here`
Process p = Runtime.getRuntime().exec(command);
p.waitFor();
when executed a cmd opens with the path name, but content of batch file is not executed.
Try this (set timeout according to your requirements):
...
String[] command = new String[]{"cmd", "/c", pt1};
Process process = Runtime.getRuntime().exec(command);
Timer timer = new Timer();
timer.schedule(new InterruptScheduler(Thread.currentThread()), 60000);
try {
process.waitFor();
} catch (InterruptedException e) {
process.destroy();
throw new TimeoutException("Command not terminated in 60 sec");
} finally {
timer.cancel();
}

Uninstalling a ClickOnce application silently

We have an production application that is deployed using Visual Studio's built-in ClickOnce deployment tool. I am writing a batch file to uninstall the application:
rundll32.exe dfshim.dll,ShArpMaintain AppName.application, Culture=neutral,
PublicKeyToken=XXXXXX, processorArchitecture=x86
The batch file works and the application's uninstall is called. However, I'm looking to do this silently. I have tried /Q /q /S /s /Silent but with no joy.
How can I do this?
I do not want to hide the batch file window. Only the ClickOnce window.
Since there seemed to be no good solution for this, I implemented a new ClickOnce uninstaller. It can be called via command-line, from .NET, or integrated into a WiX setup project as custom action.
https://github.com/6wunderkinder/Wunder.ClickOnceUninstaller
We used this for our Wunderlist 2.1 release, where we switched from ClickOnce to a Windows Installer package. It's integrated into the installation process and completely transparent to the user.
I can confirm that WMIC doesn't work for ClickOnce applications. They are just not listed in there...
I thought of putting this here as I've been working on finding how to resolve this for a long time now and couldn't find a complete solution.
I'm rather new in this whole programming thing but I think this could give ideas of how to proceed.
It basically verifies if the application is currently running, and if so, it kills it. Then it checks the registry to find the uninstall string, put it in a batch file and wait for the process to end. Then it does Sendkeys to automatically agree to uninstall. That's it.
namespace MyNameSpace
{
public class uninstallclickonce
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
private Process process;
private ProcessStartInfo startInfo;
public void isAppRunning()
{
// Run the below command in CMD to find the name of the process
// in the text file.
//
// WMIC /OUTPUT:C:\ProcessList.txt PROCESS get Caption,Commandline,Processid
//
// Change the name of the process to kill
string processNameToKill = "Auto-Crop";
Process [] runningProcesses = Process.GetProcesses();
foreach (Process myProcess in runningProcesses)
{
// Check if given process name is running
if (myProcess.ProcessName == processNameToKill)
{
killAppRunning(myProcess);
}
}
}
private void killAppRunning(Process myProcess)
{
// Ask the user if he wants to kill the process
// now or cancel the installation altogether
DialogResult killMsgBox =
MessageBox.Show(
"Crop-Me for OCA must not be running in order to get the new version\nIf you are ready to close the app, click OK.\nClick Cancel to abort the installation.",
"Crop-Me Still Running",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Question);
switch(killMsgBox)
{
case DialogResult.OK:
//Kill the process
myProcess.Kill();
findRegistryClickOnce();
break;
case DialogResult.Cancel:
//Cancel whole installation
break;
}
}
private void findRegistryClickOnce()
{
string uninstallRegString = null; // Will be ClickOnce Uninstall String
string valueToFind = "Crop Me for OCA"; // Name of the application we want
// to uninstall (found in registry)
string keyNameToFind = "DisplayName"; // Name of the Value in registry
string uninstallValueName = "UninstallString"; // Name of the uninstall string
//Registry location where we find all installed ClickOnce applications
string regProgsLocation =
"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
using (RegistryKey baseLocRegKey = Registry.CurrentUser.OpenSubKey(regProgsLocation))
{
//Console.WriteLine("There are {0} subkeys in here", baseLocRegKey.SubKeyCount.ToString());
foreach (string subkeyfirstlevel in baseLocRegKey.GetSubKeyNames())
{
//Can be used to see what you find in registry
// Console.WriteLine("{0,-8}: {1}", subkeyfirstlevel, baseLocRegKey.GetValueNames());
try
{
string subtest = baseLocRegKey.ToString() + "\\" + subkeyfirstlevel.ToString();
using (RegistryKey cropMeLocRegKey =
Registry.CurrentUser.OpenSubKey(regProgsLocation + "\\" + subkeyfirstlevel))
{
//Can be used to see what you find in registry
// Console.WriteLine("Subkey DisplayName: " + cropMeLocRegKey.GetValueNames());
//For each
foreach (string subkeysecondlevel in cropMeLocRegKey.GetValueNames())
{
// If the Value Name equals the name application to uninstall
if (cropMeLocRegKey.GetValue(keyNameToFind).ToString() == valueToFind)
{
uninstallRegString = cropMeLocRegKey.GetValue(uninstallValueName).ToString();
//Exit Foreach
break;
}
}
}
}
catch (System.Security.SecurityException)
{
MessageBox.Show("security exception?");
}
}
}
if (uninstallRegString != null)
{
batFileCreateStartProcess(uninstallRegString);
}
}
// Creates batch file to run the uninstall from
private void batFileCreateStartProcess(string uninstallRegstring)
{
//Batch file name, which will be created in Window's temps foler
string tempPathfile = Path.GetTempPath() + "cropmeuninstall.bat";
if (!File.Exists(#tempPathfile))
{
using (FileStream createfile = File.Create(#tempPathfile))
{
createfile.Close();
}
}
using (StreamWriter writefile = new StreamWriter(#tempPathfile))
{
//Writes our uninstall value found earlier in batch file
writefile.WriteLine(#"Start " + uninstallRegstring);
}
process = new Process();
startInfo = new ProcessStartInfo();
startInfo.FileName = tempPathfile;
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
File.Delete(tempPathfile); //Deletes the file
removeClickOnceAuto();
}
// Automation of clicks in the uninstall to remove the
// need of any user interactions
private void removeClickOnceAuto()
{
IntPtr myWindowHandle = IntPtr.Zero;
for (int i = 0; i < 60 && myWindowHandle == IntPtr.Zero; i++)
{
Thread.Sleep(1500);
myWindowHandle = FindWindow(null, "Crop Me for OCA Maintenance");
}
if (myWindowHandle != IntPtr.Zero)
{
SetForegroundWindow(myWindowHandle);
SendKeys.Send("+{TAB}"); // Shift + TAB
SendKeys.Send("{ENTER}");
SendKeys.Flush();
}
}
}
}
You could try to use Hidden Start.
You can not suppress the uninstall dialog for a ClickOnce application. You can write a small .NET application to uninstall the ClickOnce application and programmatically hit the button on the dialog, so no action is required by the user. That's about the best you can do.
Don't over complicate it & keep it simple - this works on both Windows XP & 7:
Go to Add/Remove Programs and make note of the exact name of the program.
Open Notepad and paste the text below:
wmic product where name="PROGRAM NAME" uninstall
but make sure to type the exact name of the program in between the quotation marks and chose Save As /All Files and name the file Uninstall.bat and then test it out to make sure it works.

Resources