Bring process to focus c# (ASP.net) - c#

I have created a web application that will call a window based application using:
#region Process
public static string shell_exec(string path, string args)
{
var p = new ProcessStartInfo();
// Redirect the output stream of the child process.
p.UseShellExecute = false;
p.LoadUserProfile = true;
p.RedirectStandardOutput = true;
p.FileName = path;
p.Arguments = args;
p.WindowStyle = ProcessWindowStyle.Normal;
var pc = Process.Start(p);
WindowHelper.BringProcessToFront(pc);
string output = pc.StandardOutput.ReadToEnd();
pc.WaitForExit();
return output;
}
#endregion
this is published using IIS Express server, the process.start() calls the application and shows in the top most (obviously because i set the property topmost true) but not in the taskbar (didn't activate the load event or not focused)
I also used bringprocesstofront function but didn't do anything:
const int SW_RESTORE = 9;
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr handle);
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool ShowWindow(IntPtr handle, int nCmdShow);
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool IsIconic(IntPtr handle);
public static void BringProcessToFront(Process process)
{
IntPtr handle = process.MainWindowHandle;
if (IsIconic(handle))
{
ShowWindow(handle, SW_RESTORE);
}
SetForegroundWindow(handle);
}
am i missing something in my code?
The external process im calling is an application that will register a persons fingerprint (using DPFP digital persona, creating it in window based unless there is for web or javascript)

Related

How to open an application that is in the taskbar?

I have Bluestacks opened in my taskbar, and I wanted to put it at the top of my screen, how can i do it?
InitializeComponent();
bool bluestack = false;
// Getting all the processes and then if bluestacks is up
// switch to it else start bluestacks.
Process[] processlist = Process.GetProcesses();
foreach (Process theprocess in processlist){
if (theprocess.ProcessName == "Bluestacks")
bluestack = true;
}
this.Hide();
if (!bluestack) {
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
"C:/ProgramData/BlueStacks/Client/Bluestacks.exe");
Process.Start(new ProcessStartInfo(path));
} else {}
Let me spoonfeed you once. Please learn from this.
First we will be needing these:
using System.Diagnostics; //PROCESS
using System.Runtime.InteropServices; //DLL IMPORT
using System.IO; //PATH
And of course DLLIMPORT will enter the scene:
//FOR FINDING WINDOW
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
//FOR FOCUSING WINDOW
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
//FOR MAXIMIZING WINDOW
private const int SW_MAXIMIZE = 3;
[DllImport("USER32.DLL")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
And Lets change some lines on your actual code:
Process[] processlist = Process.GetProcesses();//getting all the processes and then if bluestacks is up switch to it else start bluestacks
change it to..
Process[] processlist = Process.GetProcessesByName("Bluestacks");//YOU SHOULD GET SPECIFIC PROC NAME TO MAKE IT EASIER AND LESSER PERMISSION ISSUE
And lets modify this:
foreach (Process theprocess in processlist)
{
if (theprocess.ProcessName == "Bluestacks")
bluestack = true;
}
Into..
foreach (Process theprocess in processlist)
{
bluestack = true; //SINCE WE SPECIFIED THE PROCESS, THIS WILL ONLY EXECUTE IF THE TARGET APP IS RUNNING
theprocess.WaitForInputIdle();
IntPtr extWindow = theprocess.MainWindowHandle;
//FOCUS WINDOW
SetForegroundWindow(extWindow);
//BONUS: USE THIS TO MAXIMIZE WINDOW
//ShowWindow(theprocess.MainWindowHandle, SW_MAXIMIZE);
}
Here is the complete code, again guys, I put a little effort on this answer so Please learn from this.
using System;
using System.Windows.Forms;
using System.Diagnostics; //PROCESS
using System.Runtime.InteropServices; //DLL IMPORT
using System.IO; //PATH
namespace ShowApp
{
public partial class Main : Form
{
//FOR FINDING WINDOW
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
//FOR FOCUSING WINDOW
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
//FOR MAXIMIZING WINDOW
private const int SW_MAXIMIZE = 3;
[DllImport("USER32.DLL")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
public Main()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
bool bluestack = false;
Process[] processlist = Process.GetProcessesByName("Bluestacks");//YOU SHOULD GET SPECIFIC PROC NAME TO MAKE IT EASIER AND LESSER PERMISSION ISSUE
foreach (Process theprocess in processlist)
{
bluestack = true; //SINCE WE SPECIFIED THE PROCESS, THIS WILL ONLY EXECUTE IF THE TARGET APP IS RUNNING
theprocess.WaitForInputIdle();
IntPtr extWindow = theprocess.MainWindowHandle;
//FOCUS WINDOW
SetForegroundWindow(extWindow);
//BONUS: USE THIS TO MAXIMIZE WINDOW
//ShowWindow(theprocess.MainWindowHandle, SW_MAXIMIZE);
}
this.Hide();
if (!bluestack)
{
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "C:/ProgramData/BlueStacks/Client/Bluestacks.exe");
Process.Start(new ProcessStartInfo(path));
}
else
{
}
}
}
}
After starting the proccess, I would start by getting the window handle of that process
Then, I would use SetWindowPos to set it to be the topmost
Notice that this requires using PInvoke. The 3 links should point you in the right direction.

How to Start a process that interacts with the server's desktop in ASP.NET 3.5 through IIS7?

There are lots of answers, try this-that, but nothing works. Access denied.
We are starting an application on the server, and automating it to do certain Quick tasks. Of course I can start it... (but it cannot run hidden, it must run in a real-desktop mode).
I've tried all manner of different elevation/impersonation techniques. Yes I've selected the IIS-Interact with desktop box. In the web.config I've got the impersonation flag...
Here is relevant code with some commented out attempts:
private const int WM_CLOSE = 16;
private const int BN_CLICKED = 245;
private const int LB_GETTEXT = 0x0189;
private const int LB_GETTEXTLEN = 0x018A;
private const int WM_SETTEXT = 0X000C;
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
public const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
WindowsImpersonationContext impersonationContext;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
protected static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
protected static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
protected static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr GetProcessWindowStation();
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr GetThreadDesktop(int dwThreadId);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern int GetCurrentThreadId();
public void findOurProcess(string filePath)
{
IntPtr hwnd = IntPtr.Zero;
IntPtr hwnd_select = IntPtr.Zero;
IntPtr hwndChild = IntPtr.Zero;
DateTime timer;
TimeSpan diff;
int processid;
string username = "Programmer";
clsImpersonate cls = new clsImpersonate();
try
{
IntPtr token = cls.ImpersonateUser(username, Environment.MachineName, "RoboMan");
using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(token))
{
//Process process = new Process();
//ProcessStartInfo info = new ProcessStartInfo();
//info.FileName = fileName;
//info.Arguments = argument;
//process.StartInfo = info;
//process.Start();
//if (impersonateValidUser("Programmer", "", "Roboman"))
//if (impersonateValidUser(username, "DESKTOP", "Roboman"))
//{
ProcessStartInfo psi = new ProcessStartInfo("OUR PROCESS");
//psi.UserName = username;
//psi.Domain = Environment.MachineName;
//psi.Password = new System.Security.SecureString();
//psi.Password.AppendChar('R');
//psi.Password.AppendChar('o');
//psi.Password.AppendChar('b');
//psi.Password.AppendChar('o');
//psi.Password.AppendChar('m');
//psi.Password.AppendChar('a');
//psi.Password.AppendChar('n');
psi.Arguments = "-batch";
psi.WorkingDirectory = "OUR DIRECTORY";
psi.UseShellExecute = false;
//myProcess.StartInfo.CreateNoWindow = true; //Maybe?
//myProcess.Start();
//The following security adjustments are necessary to give the new
//process sufficient permission to run in the service's window station
//and desktop. This uses classes from the AsproLock library also from
//Asprosys.
//IntPtr hWinSta = GetProcessWindowStation();
//WindowStationSecurity ws = new WindowStationSecurity(hWinSta,
// System.Security.AccessControl.AccessControlSections.Access);
////ws.AddAccessRule(new WindowStationAccessRule(username,
// // WindowStationRights.AllAccess, System.Security.AccessControl.AccessControlType.Allow));
//ws.AddAccessRule(new WindowStationAccessRule(username,
// WindowStationRights.CreateDesktop, System.Security.AccessControl.AccessControlType.Allow));
//ws.AcceptChanges();
//IntPtr hDesk = GetThreadDesktop(GetCurrentThreadId());
//DesktopSecurity ds = new DesktopSecurity(hDesk,
// System.Security.AccessControl.AccessControlSections.Access);
//ds.AddAccessRule(new DesktopAccessRule(username,
// DesktopRights.AllAccess, System.Security.AccessControl.AccessControlType.Allow));
//ds.AcceptChanges();
using (Process process = Process.Start(psi))
{
processid = process.Id;
}
the cls.ImpersonateUser The above attempts to run an elevated section of code as another user. But fails. You can see I've attempted to use this version as well. ImpersonateValidUser Example
The AsProSys code would also throw an Access-denied exception right on the ws.AcceptChanges();
WebServers run as Windows Services. And Windows services are by default prohibited from accessing the Desktop as of Windows Vista.
In addition to the general Service Limitations, webservers are also customary run in the most limited userrights possible. Readaccess to it's programm and content directory is about the best they get. They are always on, so they are highly vulnerable to hacking.
As I understand currently you try to start a Dekstop applciation from a Webserver. And that is pretty much a no-go. If that did work, I would first wonder how quickly I can uninstall it. And then how I did not manage to limits right in the first place to prevent this. For every admin that will ever have to run your Webpage: Stop trying to do that!
Instead just have a Helper application that is normally installed on the Windows. Have it start automatically via the TaskSheduler on user login. and have it and the WebServer communicate via Pipes, the Loopback device or similar IPC ways that are acceptable for a WebServer.

Bring browser to front that is started by ShellExec/Process.Start

The complex solution below is justified by the need of bringing a browser window to front. It is working ~90% of the time. The problem is the 10%, when it doesn't.
I have an application that is running on a different desktop than the user's active one (it is a screensaver).
I also have a windows service that receives events from the screensaver. This service then does the following:
Impersonates the currently logged in user and starts a helper application with a URL in the command line arguments.
The helper application is started by CreateProcessAsUser - this is also the justification for the helper, I need to use ShellExec, so a separate process have to be used.
This helper application does the following:
Waits until the user's current desktop becomes active. It does a while loop with some sleep until then.
Then it finds out the user's default browser
Starts the default browser using ShellExec (Process.Start in C#), and passes the browser some command line arguments and the URL.
The actual command line invoked by the helper application is this:
cmd /C start "" C:\PathToBrowser\Browser.exe URL -someargument
Up to this point everything is working except one important thing: The browser is not brought to front in all possible cases.
Is there anything further than this, that I could do with these browsers to force them to come to front? My problem is this:
Let's say I start Chrome from command line. Chrome will just send a message to the already running instance, and quit. So I can't rely on the PID and the hWnd of the process I started, it will not be the same as the one actually showing the webpage.
Any help would be much appreciated.
Thanks to cubrr for the help, his idea worked with some extension from my part. First of all, I have to find out the Title of the webpage that will be displayed within the browser. After this I have to use EnumWindows to find the newly opened browser window, and call SetForegroundWindow on it.
My solution is based on these other sources:
How to use EnumWindows to find a certain window by partial title.
Get the title from a webpage.
Bring to forward window when minimized
The solution suggested by cubrr, using FindWindow (you have to know the exact window title to be able to use this):
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool IsIconic(IntPtr handle);
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr handle, int nCmdShow);
void Main()
{
const int SW_RESTORE = 9;
var hWnd = FindWindow(null, "Google - Google Chrome");
if (IsIconic(hWnd))
ShowWindow(hWnd, SW_RESTORE);
SetForegroundWindow(hWnd);
}
Here is the final code I ended up using:
public class MyClass
{
private const int SW_RESTORE = 9;
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool BringWindowToTop(IntPtr hWnd);
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
private static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
[DllImport("user32.dll")]
private static extern bool IsIconic(IntPtr handle);
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr handle, int nCmdShow);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
public static string GetWebPageTitle(string url)
{
// Create a request to the url
HttpWebRequest request = HttpWebRequest.Create(url) as HttpWebRequest;
// If the request wasn't an HTTP request (like a file), ignore it
if (request == null) return null;
// Use the user's credentials
request.UseDefaultCredentials = true;
// Obtain a response from the server, if there was an error, return nothing
HttpWebResponse response = null;
try { response = request.GetResponse() as HttpWebResponse; }
catch (WebException) { return null; }
// Regular expression for an HTML title
string regex = #"(?<=<title.*>)([\s\S]*)(?=</title>)";
// If the correct HTML header exists for HTML text, continue
if (new List<string>(response.Headers.AllKeys).Contains("Content-Type"))
if (response.Headers["Content-Type"].StartsWith("text/html"))
{
// Download the page
WebClient web = new WebClient();
web.UseDefaultCredentials = true;
string page = web.DownloadString(url);
// Extract the title
Regex ex = new Regex(regex, RegexOptions.IgnoreCase);
return ex.Match(page).Value.Trim();
}
// Not a valid HTML page
return null;
}
public static void BringToFront(string title)
{
try
{
if (!String.IsNullOrEmpty(title))
{
IEnumerable<IntPtr> listPtr = null;
// Wait until the browser is started - it may take some time
// Maximum wait is (200 + some) * 100 milliseconds > 20 seconds
int retryCount = 100;
do
{
listPtr = FindWindowsWithText(title);
if (listPtr == null || listPtr.Count() == 0)
{
Thread.Sleep(200);
}
} while (--retryCount > 0 || listPtr == null || listPtr.Count() == 0);
if (listPtr == null)
return;
foreach (var hWnd in listPtr)
{
if (IsIconic(hWnd))
ShowWindow(hWnd, SW_RESTORE);
SetForegroundWindow(hWnd);
}
}
}
catch (Exception)
{
// If it fails at least we tried
}
}
public static string GetWindowText(IntPtr hWnd)
{
int size = GetWindowTextLength(hWnd);
if (size++ > 0)
{
var builder = new StringBuilder(size);
GetWindowText(hWnd, builder, builder.Capacity);
return builder.ToString();
}
return String.Empty;
}
public static IEnumerable<IntPtr> FindWindowsWithText(string titleText)
{
IntPtr found = IntPtr.Zero;
List<IntPtr> windows = new List<IntPtr>();
EnumWindows(delegate(IntPtr wnd, IntPtr param)
{
if (GetWindowText(wnd).Contains(titleText))
{
windows.Add(wnd);
}
return true;
}, IntPtr.Zero);
return windows;
}
[STAThread]
public static int Main(string[] args)
{
try
{
if (args.Count() == 0)
return 0;
// ...
// Wait until the user's desktop is inactive (outside the scope of this solution)
// ...
String url = args[0];
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
// ...
// Get the path to the default browser from registry, and create a StartupInfo object with it.
// ...
process.StartInfo = startInfo;
process.Start();
try
{
process.WaitForInputIdle();
}
catch (InvalidOperationException)
{
// if the process exited then it passed the URL on to the other browser process.
}
String title = GetWebPageTitle(url);
if (!String.IsNullOrEmpty(title))
{
BringToFront(title);
}
return 0;
}
catch (System.Exception ex)
{
return -1;
}
}
}

How do I open maximized internet explorer?

I have to open maximized internet explorer using C#. I have tried the following:
try
{
var IE = new SHDocVw.InternetExplorer();
object URL = "http://localhost/client.html";
IE.ToolBar = 0;
IE.StatusBar = true;
IE.MenuBar = true;
IE.AddressBar = true;
IE.Width = System.Windows.Forms.SystemInformation.VirtualScreen.Width;
IE.Height = System.Windows.Forms.SystemInformation.VirtualScreen.Height;
IE.Visible = true;
IE.Navigate2(ref URL);
ieOpened = true;
break;
}
catch (Exception)
{
}
I can open with different sizes, but I couldn't find how to open maximized IE. I have checked the msdn, there is no property to for maximize.
Please give me some suggestions.
PS: I am developing C# console application, .Net4.5, and VS2012
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace Maximize_IE
{
class Program
{
[DllImport("user32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
static void Main(string[] args)
{
var IE = new SHDocVw.InternetExplorer();
object URL = "http://google.com/";
IE.ToolBar = 0;
IE.StatusBar = true;
IE.MenuBar = true;
IE.AddressBar = true;
IE.Visible = true;
ShowWindow((IntPtr)IE.HWND, 3);
IE.Navigate2(ref URL);
//ieOpened = true;
}
}
}
I would use the process method.
You could start any executable and
It has a property which starts your process maximized
ProcessStartInfo startInfo = new ProcessStartInfo("IExplore.exe");
startInfo.WindowStyle = ProcessWindowStyle.Maximized;
startInfo.Arguments = "www.google.com";
Process.Start(startInfo);
Quick google of "csharp maximize SHDocVw window" gives this example:
[DllImport ("user32.dll")]
private static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);
private const int SW_MAXIMISE = 3;
public void OpenWindow()
{
SHDocVw.InternetExplorer ie = new SHDocVw.InternetExplorer(); //Instantiate the class.
ShowWindow((IntPtr)ie.HWND, SW_MAXIMISE); //Maximise the window.
ie.Visible = true; //Set the window to visible.
}
try this:
var proc = new Process
{
StartInfo = {
UseShellExecute = true,
FileName = "http://localhost/client.html",
WindowStyle = ProcessWindowStyle.Maximized
}
};
proc.Start();

Opening a process in C# with hidden window

I have a function for starting processes on a local machine:
public int StartProcess(string processName, string commandLineArgs = null)
{
Process process = new Process();
process.StartInfo.FileName = processName;
process.StartInfo.Arguments = commandLineArgs;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.ErrorDialog = false;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.Start();
return process.Id;
}
It is supposed to start the process without opening a new window. Indeed, when I test it with timeout.exe no console window is opened. But when I test it with notepad.exe or calc.exe their windows still open.
I saw online that this method works for other people. I'm using .NET 4.0 on Windows 7 x64.
What am I doing wrong?
The CreateNoWindow flag applies to Console processes only.
See here for the details:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx
Secondly applications can ignore the WindowStyle argument - it has effect the first time the new application calls ShowWindow, but subsequent calls are under the control of the application.
Following program will show/hide the window:
using System.Runtime.InteropServices;
class Program
{
[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
const int SW_HIDE = 0;
const int SW_SHOW = 5;
static void Main()
{
// The 2nd argument should be the title of window you want to hide.
IntPtr hWnd = FindWindow(null, "Untitled - Notepad");
if (hWnd != IntPtr.Zero)
{
//ShowWindow(hWnd, SW_SHOW);
ShowWindow(hWnd, SW_HIDE); // Hide the window
}
}
}
Source: http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/1bc7dee4-bf1a-4c41-802e-b25941e50fd9
You need to remove the process.StartInfo.UseShellExecute = false
public int StartProcess(string processName, string commandLineArgs = null)
{
Process process = new Process();
process.StartInfo.FileName = processName;
process.StartInfo.Arguments = commandLineArgs;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.ErrorDialog = false;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.Start();
return process.Id;
}

Categories