Start a process

G

GTi

I have small program that always must be running when a user is logged on.
Since users can close this program I must create a program that always check
if this program is running.
So I created a program in C# (my first!!) and it works with one major
problem.
This program detects when the desktop program is not running and starts it
again. All works as expected
BUT
The desktop program is running as a SYSTEM user.
That is not what I wanted....
So I need to find a way to start this desktop program as the current logged
on user (it can be different users)

Can this be done in C#?

GTi




using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Xml;

public class Win32
{
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_CLOSE = 0xF060;
[DllImport("user32.dll")] public static extern int FindWindow(string
lpClassName, string lpWindowName);
[DllImport("user32.dll")] public static extern int SendMessage(int hWnd,
uint Msg, int wParam, int lParam);
[DllImport("user32.dll")] public static extern int GetDesktopWindow();
}


namespace attenWat
{
public class Service1 : System.ServiceProcess.ServiceBase
{

private System.Timers.Timer timer1=null;
private System.Timers.Timer newFileVersionChecker=null;
private System.ComponentModel.IContainer components=null;
public Service1()
{
InitializeComponent();
}

// The main entry point for the process
static void Main()
{
System.ServiceProcess.ServiceBase[] ServicesToRun;
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new Service1() };
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.timer1 = new System.Timers.Timer();
this.newFileVersionChecker = new System.Timers.Timer();
((System.ComponentModel.ISupportInitialize)(this.timer1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.newFileVersionChecker)).BeginInit();
// timer1
this.timer1.Enabled = true;
this.timer1.Interval = 10000;
this.timer1.Elapsed += new
System.Timers.ElapsedEventHandler(this.timer1_Elapsed_1);


// newFileVersionChecker
this.newFileVersionChecker.Enabled = true;
this.newFileVersionChecker.Interval = 60000;
this.newFileVersionChecker.Elapsed += new
System.Timers.ElapsedEventHandler(this.newFileVersionChecker_Elapsed);
// Service1
this.ServiceName = "AttendanceService";
((System.ComponentModel.ISupportInitialize)(this.timer1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.newFileVersionChecker)).EndInit();
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

/// <summary>
/// Set things in motion so your service can do its work.
/// </summary>

protected override void OnStart(string[] args)
{
// TODO: Add code here to start your service.
}


/// <summary>
/// Stop this service.
/// </summary>
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop your
service.
}



////////////////////////////////////////////////////////////////////////////////////////
private void timer1_Elapsed_1(object sender, System.Timers.ElapsedEventArgs
e)
{
if((Win32.GetDesktopWindow()!=0) &&
(Win32.FindWindow("TUN.Attendance.Windows.Class",null)==0))
{
Process myProcess = new Process();
try
{
string myDocumentsPath =
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
// need to find a way to start this program in the current user environment
myProcess.StartInfo.Verb = "Open";
myProcess.StartInfo.UseShellExecute = true;
// myProcess.StartInfo.FileName = myDocumentsPath + \\tun\\attendance.exe;
// myProcess.Start();
}
catch(Win32Exception err)
{
string dummyString = err.Message; // Avoid warning message
// MessageBox.Show(err.Message+"\r\n"+myProcess.StartInfo.FileName, "Check
the path.", MessageBoxButtons.OK);
}
}
}

private void newFileVersionChecker_Elapsed(object sender,
System.Timers.ElapsedEventArgs e)
{
// Application.StartupPath;
}
}
}
 
L

Landi

How is your desktop program being started at first? Is it being started by
the detector program? Or do you have a short cut to the all users/startup
folder?

--
(e-mail address removed)
http://dowhileloop.com website development
http://publicjoe.dowhileloop.com -- C# Tutorials

GTi said:
I have small program that always must be running when a user is logged on.
Since users can close this program I must create a program that always check
if this program is running.
So I created a program in C# (my first!!) and it works with one major
problem.
This program detects when the desktop program is not running and starts it
again. All works as expected
BUT
The desktop program is running as a SYSTEM user.
That is not what I wanted....
So I need to find a way to start this desktop program as the current logged
on user (it can be different users)

Can this be done in C#?

GTi




using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Xml;

public class Win32
{
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_CLOSE = 0xF060;
[DllImport("user32.dll")] public static extern int FindWindow(string
lpClassName, string lpWindowName);
[DllImport("user32.dll")] public static extern int SendMessage(int hWnd,
uint Msg, int wParam, int lParam);
[DllImport("user32.dll")] public static extern int GetDesktopWindow();
}


namespace attenWat
{
public class Service1 : System.ServiceProcess.ServiceBase
{

private System.Timers.Timer timer1=null;
private System.Timers.Timer newFileVersionChecker=null;
private System.ComponentModel.IContainer components=null;
public Service1()
{
InitializeComponent();
}

// The main entry point for the process
static void Main()
{
System.ServiceProcess.ServiceBase[] ServicesToRun;
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new Service1() };
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.timer1 = new System.Timers.Timer();
this.newFileVersionChecker = new System.Timers.Timer();
((System.ComponentModel.ISupportInitialize)(this.timer1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.newFileVersionChecker)).Beg
inInit();
// timer1
this.timer1.Enabled = true;
this.timer1.Interval = 10000;
this.timer1.Elapsed += new
System.Timers.ElapsedEventHandler(this.timer1_Elapsed_1);


// newFileVersionChecker
this.newFileVersionChecker.Enabled = true;
this.newFileVersionChecker.Interval = 60000;
this.newFileVersionChecker.Elapsed += new
System.Timers.ElapsedEventHandler(this.newFileVersionChecker_Elapsed);
// Service1
this.ServiceName = "AttendanceService";
((System.ComponentModel.ISupportInitialize)(this.timer1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.newFileVersionChecker)).End
Init();
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

/// <summary>
/// Set things in motion so your service can do its work.
/// </summary>

protected override void OnStart(string[] args)
{
// TODO: Add code here to start your service.
}


/// <summary>
/// Stop this service.
/// </summary>
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop your
service.
}



////////////////////////////////////////////////////////////////////////////
////////////
private void timer1_Elapsed_1(object sender, System.Timers.ElapsedEventArgs
e)
{
if((Win32.GetDesktopWindow()!=0) &&
(Win32.FindWindow("TUN.Attendance.Windows.Class",null)==0))
{
Process myProcess = new Process();
try
{
string myDocumentsPath =
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
// need to find a way to start this program in the current user environment
myProcess.StartInfo.Verb = "Open";
myProcess.StartInfo.UseShellExecute = true;
// myProcess.StartInfo.FileName = myDocumentsPath + \\tun\\attendance.exe;
// myProcess.Start();
}
catch(Win32Exception err)
{
string dummyString = err.Message; // Avoid warning message
// MessageBox.Show(err.Message+"\r\n"+myProcess.StartInfo.FileName, "Check
the path.", MessageBoxButtons.OK);
}
}
}

private void newFileVersionChecker_Elapsed(object sender,
System.Timers.ElapsedEventArgs e)
{
// Application.StartupPath;
}
}
}
 
N

Nick Malik [Microsoft]

Landi has a good point... if your "detector" app is started as part of a
startup sequence, and not as a service, then it will run under the
credentials of the current user, which means that it will start any
downstream app as the current user.

--
--- Nick Malik [Microsoft]
MCSD, CFPS, Certified Scrummaster
http://blogs.msdn.com/nickmalik

Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a
programmer helping programmers.
--
GTi said:
I have small program that always must be running when a user is logged on.
Since users can close this program I must create a program that always
check if this program is running.
So I created a program in C# (my first!!) and it works with one major
problem.
This program detects when the desktop program is not running and starts it
again. All works as expected
BUT
The desktop program is running as a SYSTEM user.
That is not what I wanted....
So I need to find a way to start this desktop program as the current
logged on user (it can be different users)

Can this be done in C#?

GTi




using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Xml;

public class Win32
{
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_CLOSE = 0xF060;
[DllImport("user32.dll")] public static extern int FindWindow(string
lpClassName, string lpWindowName);
[DllImport("user32.dll")] public static extern int SendMessage(int hWnd,
uint Msg, int wParam, int lParam);
[DllImport("user32.dll")] public static extern int GetDesktopWindow();
}


namespace attenWat
{
public class Service1 : System.ServiceProcess.ServiceBase
{

private System.Timers.Timer timer1=null;
private System.Timers.Timer newFileVersionChecker=null;
private System.ComponentModel.IContainer components=null;
public Service1()
{
InitializeComponent();
}

// The main entry point for the process
static void Main()
{
System.ServiceProcess.ServiceBase[] ServicesToRun;
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new
Service1() };
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.timer1 = new System.Timers.Timer();
this.newFileVersionChecker = new System.Timers.Timer();
((System.ComponentModel.ISupportInitialize)(this.timer1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.newFileVersionChecker)).BeginInit();
// timer1
this.timer1.Enabled = true;
this.timer1.Interval = 10000;
this.timer1.Elapsed += new
System.Timers.ElapsedEventHandler(this.timer1_Elapsed_1);


// newFileVersionChecker
this.newFileVersionChecker.Enabled = true;
this.newFileVersionChecker.Interval = 60000;
this.newFileVersionChecker.Elapsed += new
System.Timers.ElapsedEventHandler(this.newFileVersionChecker_Elapsed);
// Service1
this.ServiceName = "AttendanceService";
((System.ComponentModel.ISupportInitialize)(this.timer1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.newFileVersionChecker)).EndInit();
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

/// <summary>
/// Set things in motion so your service can do its work.
/// </summary>

protected override void OnStart(string[] args)
{
// TODO: Add code here to start your service.
}


/// <summary>
/// Stop this service.
/// </summary>
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop your
service.
}



////////////////////////////////////////////////////////////////////////////////////////
private void timer1_Elapsed_1(object sender,
System.Timers.ElapsedEventArgs e)
{
if((Win32.GetDesktopWindow()!=0) &&
(Win32.FindWindow("TUN.Attendance.Windows.Class",null)==0))
{
Process myProcess = new Process();
try
{
string myDocumentsPath =
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
// need to find a way to start this program in the current user
environment
myProcess.StartInfo.Verb = "Open";
myProcess.StartInfo.UseShellExecute = true;
// myProcess.StartInfo.FileName = myDocumentsPath + \\tun\\attendance.exe;
// myProcess.Start();
}
catch(Win32Exception err)
{
string dummyString = err.Message; // Avoid warning message
// MessageBox.Show(err.Message+"\r\n"+myProcess.StartInfo.FileName, "Check
the path.", MessageBoxButtons.OK);
}
}
}

private void newFileVersionChecker_Elapsed(object sender,
System.Timers.ElapsedEventArgs e)
{
// Application.StartupPath;
}
}
}
 
G

GTi

The detector is a windows service.
The desktop program is started by the registry RUN key.

So the detector is running under the SERVICE user
and the desktop program is running as the logged on user.

Any idea how the detector can start a progrm running
as the logged on user without knowing the user/password.


Nick Malik said:
Landi has a good point... if your "detector" app is started as part of a
startup sequence, and not as a service, then it will run under the
credentials of the current user, which means that it will start any
downstream app as the current user.

--
--- Nick Malik [Microsoft]
MCSD, CFPS, Certified Scrummaster
http://blogs.msdn.com/nickmalik

Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a
programmer helping programmers.
--
GTi said:
I have small program that always must be running when a user is logged on.
Since users can close this program I must create a program that always
check if this program is running.
So I created a program in C# (my first!!) and it works with one major
problem.
This program detects when the desktop program is not running and starts
it again. All works as expected
BUT
The desktop program is running as a SYSTEM user.
That is not what I wanted....
So I need to find a way to start this desktop program as the current
logged on user (it can be different users)

Can this be done in C#?

GTi




using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Xml;

public class Win32
{
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_CLOSE = 0xF060;
[DllImport("user32.dll")] public static extern int FindWindow(string
lpClassName, string lpWindowName);
[DllImport("user32.dll")] public static extern int SendMessage(int hWnd,
uint Msg, int wParam, int lParam);
[DllImport("user32.dll")] public static extern int GetDesktopWindow();
}


namespace attenWat
{
public class Service1 : System.ServiceProcess.ServiceBase
{

private System.Timers.Timer timer1=null;
private System.Timers.Timer newFileVersionChecker=null;
private System.ComponentModel.IContainer components=null;
public Service1()
{
InitializeComponent();
}

// The main entry point for the process
static void Main()
{
System.ServiceProcess.ServiceBase[] ServicesToRun;
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new
Service1() };
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.timer1 = new System.Timers.Timer();
this.newFileVersionChecker = new System.Timers.Timer();
((System.ComponentModel.ISupportInitialize)(this.timer1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.newFileVersionChecker)).BeginInit();
// timer1
this.timer1.Enabled = true;
this.timer1.Interval = 10000;
this.timer1.Elapsed += new
System.Timers.ElapsedEventHandler(this.timer1_Elapsed_1);


// newFileVersionChecker
this.newFileVersionChecker.Enabled = true;
this.newFileVersionChecker.Interval = 60000;
this.newFileVersionChecker.Elapsed += new
System.Timers.ElapsedEventHandler(this.newFileVersionChecker_Elapsed);
// Service1
this.ServiceName = "AttendanceService";
((System.ComponentModel.ISupportInitialize)(this.timer1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.newFileVersionChecker)).EndInit();
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

/// <summary>
/// Set things in motion so your service can do its work.
/// </summary>

protected override void OnStart(string[] args)
{
// TODO: Add code here to start your service.
}


/// <summary>
/// Stop this service.
/// </summary>
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop your
service.
}



////////////////////////////////////////////////////////////////////////////////////////
private void timer1_Elapsed_1(object sender,
System.Timers.ElapsedEventArgs e)
{
if((Win32.GetDesktopWindow()!=0) &&
(Win32.FindWindow("TUN.Attendance.Windows.Class",null)==0))
{
Process myProcess = new Process();
try
{
string myDocumentsPath =
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
// need to find a way to start this program in the current user
environment
myProcess.StartInfo.Verb = "Open";
myProcess.StartInfo.UseShellExecute = true;
// myProcess.StartInfo.FileName = myDocumentsPath +
\\tun\\attendance.exe;
// myProcess.Start();
}
catch(Win32Exception err)
{
string dummyString = err.Message; // Avoid warning message
// MessageBox.Show(err.Message+"\r\n"+myProcess.StartInfo.FileName,
"Check the path.", MessageBoxButtons.OK);
}
}
}

private void newFileVersionChecker_Elapsed(object sender,
System.Timers.ElapsedEventArgs e)
{
// Application.StartupPath;
}
}
}
 
W

Willy Denoyette [MVP]

GTi said:
The detector is a windows service.
The desktop program is started by the registry RUN key.

So the detector is running under the SERVICE user
and the desktop program is running as the logged on user.

Any idea how the detector can start a progrm running
as the logged on user without knowing the user/password.

Yes, but you have to PInvoke "CreateProcessWithToken" Win32 API supplying
the token handle of the interactive logon.

Willy.
 
G

GTi

Willy Denoyette said:
Yes, but you have to PInvoke "CreateProcessWithToken" Win32 API supplying
the token handle of the interactive logon.

Willy.


Willy,
Ok.... how?
Sorry, but I'm not that familiar with C# yet
And I have never used CreateProcessWithToken before.
How can I get the hToken for the current Desktop User?

And why do I have to PInvoke(*) a Win32 function into C#
Why doesn't C# have this function available in the Namespace(*).
Looks like C# is not finish yet so it have to borrow win32 functions.

Any hints?


(*)
I'm not so familiar with all the C# expression yet, so if I use wrong
phrases please correct me.

GTi
 
N

Nick Malik [Microsoft]

Hello GTi,
The detector is a windows service.
The desktop program is started by the registry RUN key.

This is what Landi was suggesting you should change.

Don't run the detector as a windows service. Run it as a console app in the
backgroud using the same registry RUN key.

--
--- Nick Malik [Microsoft]
MCSD, CFPS, Certified Scrummaster
http://blogs.msdn.com/nickmalik

Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a
programmer helping programmers.
 
G

GTi

Nick Malik said:
Hello GTi,


This is what Landi was suggesting you should change.

Don't run the detector as a windows service. Run it as a console app in
the backgroud using the same registry RUN key.

--
--- Nick Malik [Microsoft]
MCSD, CFPS, Certified Scrummaster
http://blogs.msdn.com/nickmalik

Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a
programmer helping programmers.

OK - then the detector is a non invisible window.
The desktop program will check if the detector is running,
If not started, then start the detector program.
Same to the detector program. If the desktop program is not
running, then start the desktop program.
In that way both will watch each other.

No I must find out how I create a window program in C#
It's easy with C++...

Any help?
 
G

GTi

GTi said:
OK - then the detector is a non invisible window.
The desktop program will check if the detector is running,
If not started, then start the detector program.
Same to the detector program. If the desktop program is not
running, then start the desktop program.
In that way both will watch each other.

No I must find out how I create a window program in C#
It's easy with C++...

Any help?

Ok I got it....
But how can I change the class name.
the class name for the application is
WindowsForms10.Window.8.app4
I want to change it to a more familiar name.
 
W

Willy Denoyette [MVP]

GTi said:
Willy,
Ok.... how?
Sorry, but I'm not that familiar with C# yet
And I have never used CreateProcessWithToken before.
How can I get the hToken for the current Desktop User?

And why do I have to PInvoke(*) a Win32 function into C#
Why doesn't C# have this function available in the Namespace(*).
Looks like C# is not finish yet so it have to borrow win32 functions.

Any hints?


(*)
I'm not so familiar with all the C# expression yet, so if I use wrong
phrases please correct me.

GTi

First, C# is a programming language, ad as such it doesn't have "functions",
this is why .NET has the framework class library, just like C/C++ has an
extensive library set.
In another reply you pretend this is easy in C++, but that's not true as
it's not a language issue, your problem stems from the fact that you spawn
a process from a service that runs as SYSTEM, the result is that the newly
created process run's with the same identity.
Second, not all Win32 API's are wrapped by the framework, and will probably
never will (thank God), especially Win32 API's which are very rarely used,
are new and only available on a restricted number of OS'ses are not
included. However, to make it possible to call such API's .NET provides a
facility called PInvoke.
Now, CreateProcessWithToken is such an exotic Win32 API (only available on
W2K3), another API is CreateProcessAsUser and and CreateProcessWithLogon (XP
and W2K and W2K3) but these require login credentials, so if you are not
running W2K3 you are stuck anyway.
So, I would suggest you run the detector in the session of the logon user
(started from a login script) as a console program with an hidden command
windows, that way the processes you spawn inherit the context of the logon
user.


Willy.
 
G

GTi

Willy Denoyette said:
First, C# is a programming language, ad as such it doesn't have
"functions", this is why .NET has the framework class library, just like
C/C++ has an extensive library set.
In another reply you pretend this is easy in C++, but that's not true as
it's not a language issue, your problem stems from the fact that you
spawn a process from a service that runs as SYSTEM, the result is that the
newly created process run's with the same identity.
Second, not all Win32 API's are wrapped by the framework, and will
probably never will (thank God), especially Win32 API's which are very
rarely used, are new and only available on a restricted number of OS'ses
are not included. However, to make it possible to call such API's .NET
provides a facility called PInvoke.
Now, CreateProcessWithToken is such an exotic Win32 API (only available on
W2K3), another API is CreateProcessAsUser and and CreateProcessWithLogon
(XP and W2K and W2K3) but these require login credentials, so if you are
not running W2K3 you are stuck anyway.
So, I would suggest you run the detector in the session of the logon user
(started from a login script) as a console program with an hidden command
windows, that way the processes you spawn inherit the context of the logon
user.


Willy.

Willy,
Thanks for the info
In another reply you pretend this is easy in C++,...
C/C++ is not a easier language than C#
Only that I have used it in 15 years and "have it in my fingers".
But in time I'm sure I will love C# more than C/C++.

GTi
 
N

Nick Malik [Microsoft]

Hello GTi,
Ok I got it....
But how can I change the class name.
the class name for the application is
WindowsForms10.Window.8.app4
I want to change it to a more familiar name.

One of my assumptions was that the desktop app was not written by you.
However, from the statement above, it appears clear that the desktop app was
written by you. That changes a few things.

If it's your app, and the user isn't allowed to close it, why not just
reject the event to close the window except in cases where the OS is
shutting down?
The event you would want is the .Closing event
See the example in this page of the documentation:
http://msdn.microsoft.com/library/e...emcomponentmodelcanceleventargsclasstopic.asp

As for how to create a windows app in C#: try google with "tutorial .net
windows app c#"

--
--- Nick Malik [Microsoft]
MCSD, CFPS, Certified Scrummaster
http://blogs.msdn.com/nickmalik

Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a
programmer helping programmers.
--
 

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