How to open an application that is in the taskbar? - c#

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.

Related

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 process to focus c# (ASP.net)

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)

Exception when trying to call Console.Clear() after opening a console a second time

I'm trying to open a console from a winform application from a button click. I'm doing this via the code below.
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AllocConsole();
[DllImport("kernel32.dll")]
static extern Boolean FreeConsole();
private void button1_Click(object sender, EventArgs e)
{
int userInput = 0;
AllocConsole();
do
{
Console.Clear();
Console.WriteLine("Hello World");
Console.WriteLine("Select 1 or 2");
int.TryParse(Console.ReadLine(), out userInput);
} while (userInput != 1 && userInput != 2);
FreeConsole();
}
The first time the console is opened, it works fine. Attempting to open the console a second time will work fine, but once Console.Clear(); is called, I get:
An unhandled exception of type 'System.IO.IOException' occurred in mscorlib.dll
Additional information: The handle is invalid.
The same exception will be thrown on Console.WriteLine(); and Console.ReadLine();.
I've tried the proposed solutions from this, this, and this, but I end up with the same "handle is invalid." error on Console.Clear();.
Some additional code I've tried:
[DllImport("kernel32.dll",
EntryPoint = "GetStdHandle",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll",
EntryPoint = "AllocConsole",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int AllocConsole();
[DllImport("kernel32.dll")]
static extern Boolean FreeConsole();
private const int STD_OUTPUT_HANDLE = -11;
private const int MY_CODE_PAGE = 437;
private void button1_Click(object sender, EventArgs e)
{
int userInput = 0;
AllocConsole();
IntPtr stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
SafeFileHandle safeFileHandle = new SafeFileHandle(stdHandle, true);
FileStream fileStream = new FileStream(safeFileHandle, FileAccess.Write);
Encoding encoding = System.Text.Encoding.GetEncoding(MY_CODE_PAGE);
StreamWriter standardOutput = new StreamWriter(fileStream, encoding);
standardOutput.AutoFlush = true;
Console.SetOut(standardOutput);
Stream streamIn = Console.OpenStandardInput();
TextReader readerIn = new StreamReader(streamIn);
Console.SetIn(readerIn);
do
{
Console.Clear();
Console.WriteLine("Hello World");
Console.WriteLine("Select 1 or 2");
int.TryParse(Console.ReadLine(), out userInput);
} while (userInput != 1 && userInput != 2);
FreeConsole();
}
This seems to be ok for Console.WriteLine(); and Console.ReadLine(); but I still can't get around the exception being thrown by Console.Clear();. Can anyone tell me if I'm missing something?
I doubt it is possible to attach/detach to console multiple times. As far as I understand the code of private static IntPtr ConsoleInputHandle (the same goes for ConsoleOutputHandle), the handle is initialized once on first usage, so when you detach the process from console and re-attach it once again the handle is invalid.
So imho it is not feasible to use Console class as you want (nor do I know any live examples of programs working both as console and Win32 app - the most applications I've seen provide two versions of .exe).
If you really need Windows console I guess you can try to provide your own console wrapper above Windows API. If you need only the looks of console you can go with rendering of your own "console-like" window.

Minimize Window function only works when stepping through in Debugger (C# - Console)

**EDIT: When I put a breakpoint in my MinimizePlayer() method, and step through it, it minimizes the wmplayer process. But it does not without stepping through. I don't know why. **
I had a similar script on my Linux machine where I automated some tasks that I use every time I boot up. I was able to start Rhythmbox, begin playing my playlist, and minimize the process.
Well, I'm trying the same thing on my new Windows 10 machine, and I don't know how to minimize the wmplayer.exe process from my script.
This is what I have so far. It works fine, I just want wmplayer to be minimized:
using System;
using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;
namespace Playlist
{
class Program
{
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, WindowShowStyle nCmdShow);
private enum WindowShowStyle:uint
{
Hide = 0,
ShowMinimized = 2,
Minimize = 6
}
static void Main(string[] args)
{
Run();
}
public static void Run()
{
String username = Environment.UserName;
username = char.ToUpper(username[0]) + username.Substring(1);
Console.WriteLine("Hello " + username);
Thread.Sleep(2000);
Console.WriteLine("Opening Playlist...");
Thread.Sleep(2000);
Process.Start("wmplayer.exe", "C:\\Users\\" + username + "\\Music\\A_ChillstepMix.mp3");
//Thread.Sleep(2000);
//Console.WriteLine("Opening your IDE...");
//Thread.Sleep(2000);
//Process.Start("C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\Common7\\IDE\\devenv.exe");
//Thread.Sleep(2000);
MinimizePlayer();
Thread.Sleep(2000);
Console.WriteLine("Goodbye...");
Thread.Sleep(2000);
System.Environment.Exit(0);
}
public static void MinimizePlayer()
{
Process[] ps = Process.GetProcesses();
foreach(Process p in ps)
{
if(p.ProcessName.Contains("wmplayer"))
{
IntPtr h = p.MainWindowHandle;
ShowWindow(h, WindowShowStyle.Minimize);
}
}
}
}
}
You can specify the WindowStyle of the process you are starting if you use the ProcessStartInfo object:
var psi = new System.Diagnostics.ProcessStartInfo();
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Minimized;
psi.FileName = "wmplayer.exe";
System.Diagnostics.Process.Start(psi);
Ok, I got it. I needed to add Thread.Sleep() before the MinimizePlayer() method. Working code is as follows (I commented out the Visual Studio stuff while debugging to speed things up):
using System;
using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;
namespace Playlist
{
class Program
{
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, WindowShowStyle nCmdShow);
private enum WindowShowStyle:uint
{
Hide = 0,
ShowMinimized = 2,
Minimize = 6
}
static void Main(string[] args)
{
Run();
}
public static void Run()
{
String username = Environment.UserName;
username = char.ToUpper(username[0]) + username.Substring(1);
Console.WriteLine("Hello " + username);
Thread.Sleep(2000);
Console.WriteLine("Opening Playlist...");
Thread.Sleep(2000);
Process.Start("wmplayer.exe", "C:\\Users\\" + username + "\\Music\\A_ChillstepMix.mp3");
//Thread.Sleep(2000);
//Console.WriteLine("Opening your IDE...");
//Thread.Sleep(2000);
//Process.Start("C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\Common7\\IDE\\devenv.exe");
Thread.Sleep(2000);
Console.WriteLine("Minimizing Player...");
Thread.Sleep(2000);
MinimizePlayer();
Thread.Sleep(2000);
Console.WriteLine("Goodbye...");
Thread.Sleep(5000);
System.Environment.Exit(0);
}
public static void MinimizePlayer()
{
Process[] ps = Process.GetProcesses();
foreach(Process p in ps)
{
if(p.ProcessName.Contains("wmplayer"))
{
IntPtr h = p.MainWindowHandle;
ShowWindow(h, WindowShowStyle.Minimize);
}
}
}
}
}

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;
}
}
}

Categories