Applikation wird unter Vista immer extern gestartet, mit XP geht es reibungslos...

20/12/2007 - 08:58 von Volkan Senguel | Report spam
Hallo zusammen

Projektbedingt wird benötigt dass eine externe Anwendung (Cyberlink
PowerDVD) in einer Winform làuft wie wenn es ein UserControl wàre.

Dazu habe ich bei CodeProject.com eine Demo Anwendung gefunden und diese
entsprechend angepasst und geàndert.
Unter XP funktioniert dies auch zuverlàssig aber unter Vista wird die App
(PoerDVD) immer extern gestartet (!!?)

Da ich leider nicht erkennen kann warum dieses Verhalten ist schreibe ich
hier mal den SourceCode von der Winform und con der Klasse rein, vielleicht
sieht jemand warum dass so ist

-Klasse--
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 AppControl
{
[
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;
}
}

public ApplicationControl()
{
}


[DllImport("user32.dll", EntryPoint="GetWindowThreadProcessId",
SetLastError=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 int SetWindowLong (IntPtr hwnd, int nIndex, IntPtr
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, IntPtr
wParam, IntPtr lParam);

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;

/// <summary>
/// Force redraw of control when size changes
/// </summary>
/// <param name="e">Not used</param>
protected override void OnSizeChanged(EventArgs e)
{
this.Invalidate();
base.OnSizeChanged (e);
}


/// <summary>
/// Creeate control when visibility changes
/// </summary>
/// <param name="e">Not used</param>
protected override void OnVisibleChanged(EventArgs e)
{

// If control needs to be initialized/created
if (created == false)
{

// Mark that control is created
created = true;

// Initialize handle value to invalid
appWin = IntPtr.Zero;

// Start the remote application
Process p = null;
try
{

// Start the process
p = System.Diagnostics.Process.Start(this.exeName);

// Wait for process to be created and enter idle condition
p.WaitForInputIdle();

// Get the main handle
appWin = p.MainWindowHandle;
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message, "Error");
}

// Put it into this form
SetParent(appWin, this.Handle);

// Remove border and whatnot
SetWindowLong(appWin, GWL_STYLE, new IntPtr(WS_VISIBLE));

// Move the window to overlay it on this window
MoveWindow(appWin, 0, 0, this.Width, this.Height, true);

}

base.OnVisibleChanged (e);
}


/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnHandleDestroyed(EventArgs e)
{
// Stop the application
if (appWin != IntPtr.Zero)
{

// Post a colse message
PostMessage(appWin, WM_CLOSE, new IntPtr(0), new IntPtr(0));

// Delay for it to get the message
System.Threading.Thread.Sleep(1000);

// Clear internal handle
appWin = IntPtr.Zero;

}

base.OnHandleDestroyed (e);
}


/// <summary>
/// Update display of the executable
/// </summary>
/// <param name="e">Not used</param>
protected override void OnResize(EventArgs e)
{
if (this.appWin != IntPtr.Zero)
{
MoveWindow(appWin, 0, 0, this.Width, this.Height, true);
}
base.OnResize (e);
}
}
}

-Form

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace WindowsApplication1
{
public class Form1 : System.Windows.Forms.Form
{
private AppControl.ApplicationControl applicationControl1;
private System.ComponentModel.Container components = null;

public Form1()
{
InitializeComponent();
}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code

private void InitializeComponent()
{
this.applicationControl1 = new AppControl.ApplicationControl();
this.SuspendLayout();
//
// applicationControl1
//
this.applicationControl1.Dock =
System.Windows.Forms.DockStyle.Fill;
this.applicationControl1.ExeName =
@"C:\Programme\CyberLink\PowerDVD\PowerDVD.exe";
this.applicationControl1.Location = new System.Drawing.Point(0,
0);
this.applicationControl1.Name = "applicationControl1";
this.applicationControl1.Size = new System.Drawing.Size(915,
637);
this.applicationControl1.TabIndex = 0;
this.applicationControl1.PreviewKeyDown += new
System.Windows.Forms.PreviewKeyDownEventHandler(this.applicationControl1_PreviewKeyDown);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(915, 637);
this.Controls.Add(this.applicationControl1);
this.Name = "Form1";
this.Text = "Testform";
this.KeyDown += new
System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);

}
#endregion

[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void Form1_Load(object sender, EventArgs e)
{

}
}
}
-

Vielen Dank für jeden Tip warum dies unter Vista immer extern gestartet wird
(Security???)
Volkan
 

Lesen sie die antworten

#1 Frank Dzaebel
20/12/2007 - 10:21 | Warnen spam
Hallo Volkan,

p = System.Diagnostics.Process.Start(this.exeName);
p.WaitForInputIdle();



Das ist das Problem.
"p" kann ggf. sofort wieder geschlossen werden und
ein einen anderen neuen Prozess aufmachen.
Deswegen sind solche Konstrukte eigentlich
eh nur sehr vorsichtig zu benutzen.

Ist es denn *nur* für das iexplore gedacht?
Dann würde man in der (.NET 2.0) App
schlicht das WebBrowser Control benutzen.


ciao Frank
Dipl.Inf. Frank Dzaebel [MCP/MVP C#]
http://Dzaebel.NET

Ähnliche fragen