Problem trying to position a process window - please advise

G

garyusenet

For this first time today I used the System.Diagnositcs namespace to
launch a program from my c# code. The program launches OK but I have
something which has completely stumped me.

The SetWindowPos method does not work. If I run the code as it is
presented below, app.exe launches in its own window and is displayed at
the top left part of the screen. However it isn't repositioned which is
what the last piece of code should do. HOWEVER if i end my c# program
and leave app.exe open - and then comment out the launchapp() part of
Form1_load and just run my c# program again the window is moved as
expected. So for some reason the SetWindowPos method is only working if
app.exe is open BEFORE I run my c# code, and not when I use my C# code
to open app.exe. Any ideas why this is please?

NB
The original (originalapp.exe) ran in fullscreen. Somebody wrote a
programme app.exe which runs originalapp.exe in a window. This is the
reason why I have to use FindWindow to find the Hwnd of originalapp.exe
from within app.exe and can't just query the process p for it's Hwnd.

Thanks very much for comments,

Gary-



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace WindowsApplication1
{

public partial class Form1 : Form
{

#region static bool SetWindowPos (hWnd, hWndInsertAfter, X, Y,
cx, cy, uFlags) *via imported dll*
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr
hWndInsertAfter,
int X, int Y, int cx, int cy, uint uFlags);
private const int HWND_TOP = 0;
#endregion

#region static int FindWindow(_ClassName, _WindowName) *via
imported dll*
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError =
true)]
private static extern int FindWindow(string _ClassName,
string _WindowName);
#endregion

#region static void GetWindowText(h, s, nMaxCount) *via
imported dll*
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError =
true)]
public static extern void GetWindowText(int h,
StringBuilder s, int nMaxCount);
#endregion


public Form1()
{
InitializeComponent();
}


private void launchapp()
{
Process p = new Process();
p.StartInfo.FileName = @"C:\Program
Files\app\directory\app.exe";
p.StartInfo.WorkingDirectory = @"C:\Program
Files\app\directory\";
p.StartInfo.WindowStyle =
System.Diagnostics.ProcessWindowStyle.Hidden;
p.Start();
return;
}


private void Form1_Load(object sender, EventArgs e)
{

launchapp();

// window handle, place window at top of Z order, WP left,
WP top, width, height
int handle = FindWindow(null, "Title of Application
Window");
SetWindowPos((IntPtr)handle, (IntPtr)HWND_TOP, 5, 5, 5,
5,0);


}


}
}
 
D

Dustin Campbell

Have you tried debugging this in conjunction with Spy++ to see if you are
actually getting the correct window handle? Also, have you checked the return
values of your Win32 API calls to see if they are returning success?

Best Regards,
Dustin Campbell
Developer Express Inc.
 
D

Dustin Campbell

The original (originalapp.exe) ran in fullscreen. Somebody wrote a
programme app.exe which runs originalapp.exe in a window. This is the
reason why I have to use FindWindow to find the Hwnd of
originalapp.exe
from within app.exe and can't just query the process p for it's Hwnd.
Thanks very much for comments,

Why not improve your search by using FindWindowEx so that you can narrow
your search to the children of Process.MainWindowHandle?

Best Regards,
Dustin Campbell
Developer Express Inc
 
G

garyusenet

Dustin thankyou, I have queried the return value of my SetWindowPos and
it is returning false when I run it first time, and True when I cancel
my program, comment out the launchapp, and rerun the program. So it's
the SetWindowPos that's failing first time around.

I'll look into spy++ that you mentioned now, and see if it sheds any
light on why this is.

Many Thanks,

Gary-
 
G

garyusenet

Unfonruntely i don't seem to have spy++ i'm using Visual C# express and
don't think it comes with that tool. I have VS 2005 at home in the
attic i think but i'll have to find it.

In the meantime, i'll try to use that other function you mentioned.

Thanks,

Gary-
 
G

garyusenet

I dont really understand the difference between FindWindow and
FindWindowEx, i'm new to all of this - so it's quite confusing.

Gary-
 
D

Dustin Campbell

Dustin thankyou, I have queried the return value of my SetWindowPos
and it is returning false when I run it first time, and True when I
cancel my program, comment out the launchapp, and rerun the program.
So it's the SetWindowPos that's failing first time around.

I'll look into spy++ that you mentioned now, and see if it sheds any
light on why this is.

Is the handle returned by FindWindow (and being passed into SetWindowPos)
valid?

Best Regards,
Dustin Campbell
Developer Express Inc
 
D

Dustin Campbell

For this first time today I used the System.Diagnositcs namespace to
launch a program from my c# code. The program launches OK but I have
something which has completely stumped me.

The SetWindowPos method does not work. If I run the code as it is
presented below, app.exe launches in its own window and is displayed
at the top left part of the screen. However it isn't repositioned
which is what the last piece of code should do. HOWEVER if i end my c#
program and leave app.exe open - and then comment out the launchapp()
part of Form1_load and just run my c# program again the window is
moved as expected. So for some reason the SetWindowPos method is only
working if app.exe is open BEFORE I run my c# code, and not when I use
my C# code to open app.exe. Any ideas why this is please?

Is it possible that the problem is because your "launchapp" code makes the
window hidden?

Best Regards,
Dustin Campbell
Developer Express Inc.
 
D

Dustin Campbell

I dont really understand the difference between FindWindow and
FindWindowEx, i'm new to all of this - so it's quite confusing.

FindWindowEx allows you to specify a few extra parameters to narrow your
search. If the window that your searching for is parented by another window
(as you said in your original post), you should be able to use FindWindowEx
to locate that window and pass the Process.MainWindowHandle as the parent
window. Here's how I define both APIs in C#:

[DllImport("user32.dll")]
static extern IntPtr FindWindow([MarshalAs(UnmanagedType.LPTStr)] string
lpClassName, [MarshalAs(UnmanagedType.LPTStr)] string lpWindowName);

[DllImport("user32.dll")]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter,
[MarshalAs(UnmanagedType.LPTStr)] string lpszClass, [MarshalAs(UnmanagedType.LPTStr)]
string lpszWindow);

Using the code that you original posted (untested!!):

private Process launchapp()
{
Process p = new Process();
p.StartInfo.FileName = @"C:\Program Files\app\directory\app.exe";
p.StartInfo.WorkingDirectory = @"C:\Program Files\app\directory\";
p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
p.Start();
return p;
}

private void Form1_Load(object sender, EventArgs e)
{
launchapp();

// window handle, place window at top of Z order, WP left, WP top, width,
height
int handle = FindWindowEx(p.MainWindowHandle, IntPtr.Zero, null, "Title
of Application Window");
SetWindowPos((IntPtr)handle, (IntPtr)HWND_TOP, 5, 5, 5, 5,0);
}

Best Regards,
Dustin Campbell
Developer Express Inc.
 
G

garyusenet

After much investigation and armed with your kind advice Dustin I have
found the problem.

There is a delay between the launch of app.exe and the availability of
the Hwnd that i'm searching for.

I have managed to overcome this by using the following: -

while (handle == 0)
{
handle = FindWindow(null, "title of application");
}

//here i make the calls to the api's only once my hwnd has a value that
isn't 0.

The only problem with this is it causes a fairly significant delay
between the time of launching my c# code, and the app.exe actually
being launched. (Which surprised me because my P.Start() is actually
BEFORE the while code i have placed above.

Any ideas why this delay may be happening and how i might overcome it?

Thanks,

Gary-
 
D

Dustin Campbell

After much investigation and armed with your kind advice Dustin I have
found the problem.

There is a delay between the launch of app.exe and the availability of
the Hwnd that i'm searching for.

I have managed to overcome this by using the following: -

while (handle == 0)
{
handle = FindWindow(null, "title of application");
}
//here i make the calls to the api's only once my hwnd has a value
that isn't 0.

The only problem with this is it causes a fairly significant delay
between the time of launching my c# code, and the app.exe actually
being launched. (Which surprised me because my P.Start() is actually
BEFORE the while code i have placed above.

Any ideas why this delay may be happening and how i might overcome it?

You could get a similar effect by calling Process.WaitForInputIdle() after
calling Process.Start(). Assuming that the process that your starting has
a GUI (it appears to), this will block your thread until it is ready.

Process.Start() does just that -- it starts the process. After starting the
process, there is initialization that takes place in that process before
the main window is created. However, the Process.Start() call will have already
returned by the time that happens. There's no way to actually speed up the
start of that process -- you simply don't have control of that.

A simple solution to keep your application from blocking might be to just
use a System.Windows.Forms.Timer on your form and check for the handle ever
10 milliseconds or so.

Best Regards,
Dustin Campbell
Developer Express Inc
 
G

garyusenet

Dustin. Process.WaitForInputIdle();

Is doing exactly what I needed. It's achieving the same effect as my
while loop, but it isn't creating the significant (approx 10 second)
delay.

Thank you,

Your advice has been invaluable.

Gary-
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top