I'm using a small C# executable to launch a java jar. I want to recover the exit code returned by the jar so i can restart the jar if i need to.
However the c# application keeps showing a black console window and i can't get rid of it, does anyone know how to fix this?
I'm using t he following C# code to start the process
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "jre/bin/java.exe";
p.StartInfo.Arguments = "-Djava.library.path=bin -jar readermanager.jar";
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
p.waitForExit();
return p.ExitCode;
The console window only keeps visible when using the waitForExit(); method. Without it (and withoud p.ExitCode) the console windows closes. I also tried setting the StartInfo.WindowStyle to Hidden and Minimized but both don't have any effect on the window.
Just change the output type of your C# program to be a "Windows Application" instead of a "Console Application". A C# Windows application doesn't really care if you actually display any windows.
From How to run a C# console application with the console hidden
System.Diagnostics.ProcessStartInfo start =
new System.Diagnostics.ProcessStartInfo();
start.FileName = dir + #"\Myprocesstostart.exe";
start.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
But if that does not work, how about this: http://social.msdn.microsoft.com/Forums/eu/csharpgeneral/thread/ea8b0fd5-a660-46f9-9dcb-d525cc22dcbd
using System.Runtime.InteropServices;
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName,string lpWindowName);
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
IntPtr hWnd = FindWindow(null, "Window caption here");
if(hWnd != IntPtr.Zero)
{
//Hide the window
ShowWindow(hWnd, 0); // 0 = SW_HIDE
}
if(hWnd != IntPtr.Zero)
{
//Show window again
ShowWindow(hWnd, 1); //1 = SW_SHOWNORMA
}
Related
I want to display a tiff file using shell execute. I am assuming the default app is the photoviewer. My Problem is that when i want to kill the process with photoviewer.Kill() i get an System.InvalidOperationException. When setting a breakpoint after photoViewer.Start() i realised that photoviewer does not conatain an Id.
I there a sufficent way to kill it? As it runs via dllhost.exe i do not want to retrun all processes named dllhost and kill them all since i do not know what else is run by dllhost.
Process photoViewer = new Process();
private void StartProcessUsingShellExecute(string filePath)
{
photoViewer.StartInfo = new ProcessStartInfo(filePath);
photoViewer.StartInfo.UseShellExecute = true;
photoViewer.Start();
}
I have another approach without shell execute but this approach seems to have dpi issues.
Approach without shell execute
Found a solution, may help anyone with a similar problem.
When i looked into the task manager i found that the windows 10 photoviewer runs detached from the application via dllhost. So since i have 4 dllhost processes up and running and just want to close the window. I do:
private void StartProcessAsShellExecute(string filePath)
{
photoViewer.StartInfo = new ProcessStartInfo(filePath);
photoViewer.StartInfo.UseShellExecute = true;
photoViewer.Start();
Process[] processes = Process.GetProcessesByName("dllhost");
foreach (Process p in processes)
{
IntPtr windowHandle = p.MainWindowHandle;
CloseWindow(windowHandle);
// do something with windowHandle
}
viewerOpen = true;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
//I'd double check this constant, just in case
static uint WM_CLOSE = 0x10;
public void CloseWindow(IntPtr hWindow)
{
SendMessage(hWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}
that closes all dllhost windows (of which i have just 1, the photoviewer)
I'm making a windows bot in C#, part of him is running apps by for e.g. !d command it runs Discord app or !sp runs Spotify app. Whene I am doing it by cmd some of them runs fine but some like Discord and Visual Studio Code depends on console that means if I close the console the app is gonna be shutdown aswell.
if (input == "!d") {
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = #"C:\Users\User\AppData\Local\Discord\app-0.0.296\Discord.exe";
Process.Start(start);
Run();
}
This code I am using for starting the apps. Should I use something another in C# to make app independent on cmd? Or maybe it's just apps fault?
You can write a small host application that will run the target process and wait for exit. Then your bot application can run the host and exit immediately.
Code for the host app - the first argument is the path to the target application. I'm using Windows API to hide console window:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace AppHost
{
class Program
{
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
const int SW_HIDE = 0;
private static void Main(string[] args)
{
var handle = GetConsoleWindow();
ShowWindow(handle, SW_HIDE);
var start = new ProcessStartInfo { FileName = args[0] };
var process = Process.Start(start);
process.WaitForExit();
}
}
}
Code for the bot - please note that path to the target application needs to be in double quotes:
var start = new ProcessStartInfo
{
FileName = "AppHost.exe",
Arguments = #"""C:\Program Files (x86)\Microsoft VS Code\Code.exe""",
};
var process = Process.Start(start);
I have this code:
Process myProcess = new Process();
myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.FileName = "rdpclip.exe";
myProcess.Start();
to start an exe file which is located in system32
I always get an error that, the system file cannot be found. In windows 2008 server.
Even if I set the StartupInfo.FileName="c:\\windows\\system32\\rdpclip.exe" it still does not find the file !?
It works if I place the file in other folder, but in System32 it does not start. I just need to kill this process and start again, but I never thought that in C# is such a pain to do such a simple thing ?!
This error is misleading because it usually means you to do not have permission to that folder. Try building your program, then right click the resulting .exe and click 'run as administrator'.
Try this (you'll need to import System.Runtime.InteropServices):
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);
IntPtr ptr = IntPtr.Zero;
if(Wow64DisableWow64FsRedirection(ref ptr))
{
Process myProcess = new Process();
myProcess.StartInfo.UseShellExecute = true;
myProcess.StartInfo.FileName = "rdpclip.exe";
myProcess.Start();
Process.Start(myProcess);
Wow64RevertWow64FsRedirection(ptr);
}
I think starting a process minimized should be simple but I had no luck with outlook. How can I start Outlook minimized?
My attempt was this:
[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
static void Main(string[] args)
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "OUTLOOK.EXE";
IntPtr hWnd = Process.Start(startInfo).Handle;
bool state = false;
if (!hWnd.Equals(IntPtr.Zero))
state = ShowWindowAsync(hWnd, 2);
// window values: http://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx
Console.WriteLine(state.ToString());
Console.Read();
}
Have you tried using ProcessStartInfo.WindowStyle, setting it to ProcessWindowStyle.Minimized?
I have found out that if you wait until Outlook have started and you send the command below the window will minimize to tray. Now the only thing to accomplish in order to minimize outlook is to loop till it is ready :-)
var hWnd = Process.Start(startInfo);
ShowWindowAsync(hWnd.MainWindowHandle, 2);
I have solved it but I like to hear your comments if you think the solution can be improved.
I also have posted the solution on my blog with some more details at http://jwillmer.de/blog/2012/08/01/how-to-start-outlook-minimized-with-c/
[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
// console application entry point
static void Main()
{
// check if process already runs, otherwise start it
if(Process.GetProcessesByName("OUTLOOK").Count().Equals(0))
Process.Start("OUTLOOK");
// get running process
var process = Process.GetProcessesByName("OUTLOOK").First();
// as long as the process is active
while (!process.HasExited)
{
// title equals string.Empty as long as outlook is minimized
// title starts with "öffnen" (engl: opening) as long as the programm is loading
string title = Process.GetProcessById(process.Id).MainWindowTitle;
// "posteingang" is german for inbox
if (title.ToLower().StartsWith("posteingang"))
{
// minimize outlook and end the loop
ShowWindowAsync(Process.GetProcessById(process.Id).MainWindowHandle, 2);
break;
}
//wait awhile
Thread.Sleep(100);
// place for another exit condition for example: loop running > 1min
}
}
You can use this
this.Application.ActiveExplorer ().WindowState = Outlook.OlWindowState.olMinimized;
It minimizing your corrent outlook window
(this = ThisAddIn class)
I am trying to capture a newly launched application using GetForegroundWindow() using P/Invoke in C#. However, all i get is explorer.exe window handle instead of the actual process window handle (such as notepad.exe or wordpad.exe) that was launched.
Actually i am trying to log user entered text when user opens "notepad" at the same time i want to get the actual handle of the "notepad" instance (if multiple notepad instances are open) in which user is attempting to write something.
i.e I launch notepad.exe from start menu on Windows 7 Ultimate x64 with my C#.Net based application running for keys pressed. I have setup application key hooks in my application so that on text changed event, the application attempts to get the foreground window. The problem is: It gets explorer.exe instead of notepad.exe.
The code works for already-open windows perfectly but it doesn't work for newly launched instances of any application such as chrome, notepad, wordpad or any other. Instead of logging text against the correct application, it logs text for explorer.exe. Here is my code:
private string GetActiveWindowTitle()
{
const int nChars = 256;
IntPtr handle = IntPtr.Zero;
StringBuilder Buff = new StringBuilder(nChars);
handle = GetForegroundWindow();
if (GetWindowText(handle, Buff, nChars) > 0)
{
return Buff.ToString();
}
return null;
}
Process GetActiveProcess()
{
Process[] AllProcess = Process.GetProcesses();
String title = GetActiveWindowTitle();
foreach (Process pro in AllProcess)
{
if (title.Equals(pro.MainWindowTitle))
{
return pro;
}
}
return Process.GetCurrentProcess();
}
string GetActiveProcessFileName()
{
IntPtr hwnd = GetForegroundWindow();
SetForegroundWindow(hwnd);
uint pid;
GetWindowThreadProcessId(hwnd, out pid);
Process p = Process.GetProcessById((int)pid);
//p.MainModule.FileName.Dump();
return p.ProcessName;
}
ProcessInfo GetActiveProcessInfo()
{
IntPtr hwnd = GetForegroundWindow();
const int nChars = 256;
StringBuilder Buff = new StringBuilder(nChars);
uint pid;
GetWindowThreadProcessId(hwnd, out pid);
Process p = Process.GetProcessById((int)pid);
ProcessInfo pi = new ProcessInfo();
if (GetWindowText(hwnd, Buff, nChars) > 0)
{
pi.ProcessTitle = Buff.ToString();
}
pi.ProcessName = p.ProcessName;
pi.ProcessHandle = (int)p.MainWindowHandle;
return pi;
}
GetActiveProcessInfo returns explorer.exe instead of correct application i.e notepad.exe because the GetForegroundWindow() read explorer.exe as foreground window. The same code reads the correct application window when i type in existing open applications and donot launch a new instance of teh application.
I read somewhere that there is some race-condition problem. if this is the case, how can i solve this?
Please help me. I am really stuck on this very long.
Thanks.
Ok. Guys. The problem was not with GetForegroundWindow(). Maybe that's why i didnt get any answer for that. I debugged the issue in detail and located the problem. The answer can be found here with corrected code.
Solution with Code