|
Yeah, same problem but I have a solution:
I was stepping through the control's code (running on IE7 and Vista sp1) and
noticed that it works when placing a breakpoint at
appWin = p.MainWindowHandle;
(Line 147, i think) and stepping through execution.
I'm unsure of the exact cause, but it looks like it needs a second or so of delay
to get the proper handle when running with Vista and IE7.
Modifying the parameter for WaitForInputIdle() doesn't seem to help.
I modified the control to the following:
System.Threading.Thread.Sleep(1000);
Dirty, i know, but it works
|
|
|
|
|
Should we replace the WaitForInputIdle() with the sleep(1000) command ? I did that and still it opens the IE in separate window!!!
|
|
|
|
|
No, put it right before appwin=p.MainWindowHandle;
System.Threading.Thread.Sleep(1000);
appWin = p.MainWindowHandle;
|
|
|
|
|
i've tried this and change the value from 1000 to 30000 on "System.Threading.Thread.Sleep(1000);" but doesn't effect anything
|
|
|
|
|
ahaa, its work.
I just forgot to change the AppControl reference to the new one that has been modified.
Thanks
|
|
|
|
|
Would a splash screen on the called process cause this not to work
I keep getting en error stating
Cannot Process the request because the process has exited
And the app opens in its own window
|
|
|
|
|
I use this applicacion to host an exe (like notepad) in a form called 'form1'.
My problem is that, when I call “form1.hide ();" or "form1.visible=false" , the .exe process contained in this form is destroyed. Method "handledestroyed" for this process is automatically called. However, I dont want to kill it. Only hide.
So, how can I hide the form maintaining the process associated with it?
Regards
putzol
|
|
|
|
|
This is really cool, thanks so much for posting this.
Andres Becerra
|
|
|
|
|
I've applied this to a figure window in matlab but it appears the the background does not get erased after resize or overlap of another window.
Any ideas?
Greg
|
|
|
|
|
Yes somehow, the PAINT messages don't get through the child window, Im trying to put PuTTy windows inside this one and i've to force the repaint,
Also the window style does not get update and the caption bar is also draw.
|
|
|
|
|
A call to PInvoke function 'AppControl!AppControl.ApplicationControl::SetWindowLong' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
How does this get a fix?
Steve
|
|
|
|
|
|
Replace:
[DllImport ("user32.dll", EntryPoint = "SetWindowLong", SetLastError = true)]
private static extern long SetWindowLong (IntPtr hwnd, int nIndex, long dwNewLong);
by:
[DllImport ("user32.dll", EntryPoint = "SetWindowLong", SetLastError = true)]
private static extern int SetWindowLong (IntPtr hwnd, int nIndex, int dwNewLong);
|
|
|
|
|
Have you had any luck fixing this yet?
Thanks,
HRP
|
|
|
|
|
How i can fix this?? Thanks
Bye
|
|
|
|
|
Hi,
Not sure if it's still relevant, but in order to run it under VS2005 and to avoid this error, change the declartion of SetWindowLong to the following:
[DllImport("user32.dll", EntryPoint = "SetWindowLongA", SetLastError = true)]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
You would also need to change the call to the function so it will cast the const to IntPtr.
Sagy
|
|
|
|
|
replace the "long" with "uint"
|
|
|
|
|
1.can't start programe that have login window.
2.How sart a progame with command line.
Thanks,
Tsewang
caixrz
|
|
|
|
|
Great post, thanks everybody.
I added a public property exeParametros and used it in the process start method to send the parameters. It works opening a file with the notepad.
p = System.Diagnostics.Process.Start(this.exeName, exeParametros);
I attach the modified code:
using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace ExeEmbedder
{
[
ToolboxBitmap(typeof(ApplicationControl), "AppControl.bmp"),
]
public class ApplicationControl : System.Windows.Forms.Panel
{
bool created = false;
IntPtr appWin;
private string exeName = "";
[
Category("Data"),
Description("Name of the executable to launch"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)
]
public string ExeName
{
get
{
return exeName;
}
set
{
exeName = value;
}
}
private string exeParametros = "";
[
Category("Data"),
Description("String para pasar al ejecutable"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)
]
public string ExeParametros
{
get
{
return exeParametros;
}
set
{
exeParametros = value;
}
}
public ApplicationControl()
{
}
[DllImport("user32.dll", EntryPoint="GetWindowThreadProcessId", SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
private static extern long GetWindowThreadProcessId(long hWnd, long lpdwProcessId);
[DllImport("user32.dll", SetLastError=true)]
private static extern IntPtr FindWindow (string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError=true)]
private static extern long SetParent (IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", EntryPoint="GetWindowLongA", SetLastError=true)]
private static extern long GetWindowLong (IntPtr hwnd, int nIndex);
[DllImport("user32.dll", EntryPoint="SetWindowLongA", SetLastError=true)]
private static extern long SetWindowLong (IntPtr hwnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", SetLastError=true)]
private static extern long SetWindowPos(IntPtr hwnd, long hWndInsertAfter, long x, long y, long cx, long cy, long wFlags);
[DllImport("user32.dll", SetLastError=true)]
private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
[DllImport("user32.dll", EntryPoint="PostMessageA", SetLastError=true)]
private static extern bool PostMessage(IntPtr hwnd, uint Msg, long wParam, long lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWindowVisible(IntPtr hWnd);
private const int SWP_NOOWNERZORDER = 0x200;
private const int SWP_NOREDRAW = 0x8;
private const int SWP_NOZORDER = 0x4;
private const int SWP_SHOWWINDOW = 0x0040;
private const int WS_EX_MDICHILD = 0x40;
private const int SWP_FRAMECHANGED = 0x20;
private const int SWP_NOACTIVATE = 0x10;
private const int SWP_ASYNCWINDOWPOS = 0x4000;
private const int SWP_NOMOVE = 0x2;
private const int SWP_NOSIZE = 0x1;
private const int GWL_STYLE = (-16);
private const int WS_VISIBLE = 0x10000000;
private const int WM_CLOSE = 0x10;
private const int WS_CHILD = 0x40000000;
protected override void OnSizeChanged(EventArgs e)
{
this.Invalidate();
base.OnSizeChanged (e);
}
protected override void OnVisibleChanged(EventArgs e)
{
if (created == false)
{
created = true;
appWin = IntPtr.Zero;
Process p = null;
try
{
p = System.Diagnostics.Process.Start(this.exeName, exeParametros);
while (p.MainWindowHandle == IntPtr.Zero || !IsWindowVisible(p.MainWindowHandle))
{
System.Threading.Thread.Sleep(10);
p.Refresh();
}
p.WaitForInputIdle();
appWin = p.MainWindowHandle;
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message, "Error");
}
SetParent(appWin, this.Handle);
SetWindowLong(appWin, GWL_STYLE, WS_VISIBLE);
MoveWindow(appWin, 0, 0, this.Width, this.Height, true);
}
base.OnVisibleChanged (e);
}
protected override void OnHandleDestroyed(EventArgs e)
{
if (appWin != IntPtr.Zero)
{
PostMessage(appWin, WM_CLOSE, 0, 0);
System.Threading.Thread.Sleep(1000);
appWin = IntPtr.Zero;
}
base.OnHandleDestroyed (e);
}
protected override void OnResize(EventArgs e)
{
if (this.appWin != IntPtr.Zero)
{
MoveWindow(appWin, 0, 0, this.Width, this.Height, true);
}
base.OnResize (e);
}
}
}
|
|
|
|
|
Can I get the code for AppControl dll
|
|
|
|
|
Hi, thank you for this example. I have tried to lunch it with visual cSgarp, but he doesn't work. He return me an error at this line:
this.Controls.Add(this.applicationControl1);
Can you help me?
I have also tried to insert your code in my application, but he return me n error at this code:
SetWindowLong(appWin, GWL_STYLE, WS_VISIBLE);
thank you
|
|
|
|
|
Hi Sheikko,
you can try to compile it with visual studio 2003,it will be O.K.
|
|
|
|
|
I get the same error in Visual studio 2005 is there any way to make it work in 2005. I dont have 2003 and have a large program in 2005 working already. ty
|
|
|
|
|
Yeah id like it to work for 2008
|
|
|
|
|
Here's the "translation" of the file "AppControl.cs" in VB.Net :
'**********************************************************************
Imports System
Imports System.Collections
imports System.ComponentModel
imports System.Diagnostics
imports System.Drawing
imports System.Data
imports System.Windows.Forms
imports System.Runtime.InteropServices
Public Class AppControl
Inherits System.Windows.Forms.Panel
Private Shadows created As Boolean = False
Private appWin As IntPtr
Private sExeName As String = ""
Public Property ExeName() As String
Get
Return sExeName
End Get
Set(ByVal value As String)
sExeName = value
End Set
End Property
#Region "External Definition + Constants"
<DllImport("user32.dll", EntryPoint:="GetWindowThreadProcessId", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> Private Shared Function GetWindowThreadProcessId(ByVal hWnd As Long, ByVal lpdwProcessId As Long) As Long
End Function
<DllImport("user32.dll", SetLastError:=True)> Private Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True)> Private Shared Function SetParent(ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As Long
End Function
<DllImport("user32.dll", EntryPoint:="GetWindowLongA", SetLastError:=True)> Private Shared Function GetWindowLong(ByVal hwnd As IntPtr, ByVal nIndex As Integer) As Long
End Function
<DllImport("user32.dll", EntryPoint:="SetWindowLongA", SetLastError:=True)> Private Shared Function SetWindowLong(ByVal hwnd As IntPtr, ByVal nIndex As Integer, ByVal dwNewLong As IntPtr) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True)> Private Shared Function SetWindowPos(ByVal hwnd As IntPtr, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
End Function
<DllImport("user32.dll", SetLastError:=True)> Private Shared Function MoveWindow(ByVal hwnd As IntPtr, ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal repaint As Boolean) As Boolean
End Function
<DllImport("user32.dll", EntryPoint:="PostMessageA", SetLastError:=True)> Private Shared Function PostMessage(ByVal hwnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
End Function
Private Const SWP_NOOWNERZORDER As Integer = 512
Private Const SWP_NOREDRAW As Integer = 8
Private Const SWP_NOZORDER As Integer = 4
Private Const SWP_SHOWWINDOW As Integer = 64
Private Const WS_EX_MDICHILD As Integer = 64
Private Const SWP_FRAMECHANGED As Integer = 32
Private Const SWP_NOACTIVATE As Integer = 16
Private Const SWP_ASYNCWINDOWPOS As Integer = 16384
Private Const SWP_NOMOVE As Integer = 2
Private Const SWP_NOSIZE As Integer = 1
Private Const GWL_STYLE As Integer = (-16)
Private Const WS_VISIBLE As Integer = 268435456
Private Const WM_CLOSE As Integer = 16
Private Const WS_CHILD As Integer = 1073741824
#End Region
#Region "Overrides functions"
Protected Overrides Sub OnSizeChanged(ByVal e As EventArgs)
Me.Invalidate()
MyBase.OnSizeChanged(e)
End Sub
Protected Overrides Sub OnVisibleChanged(ByVal e As EventArgs)
''// If control needs to be initialized/created
If (created = False) Then
''// Mark that control is created
created = True
'// Initialize handle value to invalid
appWin = IntPtr.Zero
'// Start the remote application
Dim p As Process
Try
'// Start the process
p = System.Diagnostics.Process.Start(Me.ExeName)
'// Wait for process to be created and enter idle condition
p.WaitForInputIdle()
'// Get the main handle
appWin = p.MainWindowHandle
Catch ex As Exception
MessageBox.Show(Me, ex.Message, "Error")
End Try
'// Put it into this form
SetParent(appWin, Me.Handle)
'// Remove border and whatnot
SetWindowLong(appWin, GWL_STYLE, WS_VISIBLE)
'// Move the window to overlay it on this window
MoveWindow(appWin, 0, 0, Me.Width, Me.Height, True)
End If
MyBase.OnVisibleChanged(e)
End Sub
Protected Overrides Sub OnHandleDestroyed(ByVal e As EventArgs)
'// Stop the application
If (appWin <> IntPtr.Zero) Then
'// Post a close message
PostMessage(appWin, WM_CLOSE, 0, 0)
'// Delay for it to get the message
System.Threading.Thread.Sleep(1000)
'// Clear internal handle
appWin = IntPtr.Zero
End If
MyBase.OnHandleDestroyed(e)
End Sub
Protected Overrides Sub OnResize(ByVal e As EventArgs)
If (Me.appWin <> IntPtr.Zero) Then
MoveWindow(appWin, 0, 0, Me.Width, Me.Height, True)
End If
MyBase.OnResize(e)
End Sub
#End Region
End Class
'**********************************************************************
Hope that can be help somebody
|
|
|
|
|