📄 process.cs
字号:
//==========================================================================================
//
// OpenNETCF.Diagnostics.Process
// Copyright (c) 2003-2004, OpenNETCF.org
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the OpenNETCF.org Shared Source License.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the OpenNETCF.org Shared Source License
// for more details.
//
// You should have received a copy of the OpenNETCF.org Shared Source License
// along with this library; if not, email licensing@opennetcf.org to request a copy.
//
// If you wish to contact the OpenNETCF Advisory Board to discuss licensing, please
// email licensing@opennetcf.org.
//
// For general enquiries, email enquiries@opennetcf.org or visit our website at:
// http://www.opennetcf.org
//
//==========================================================================================
using System;
using System.Runtime.InteropServices;
using OpenNETCF.Win32;
namespace OpenNETCF.Diagnostics
{
/// <summary>
/// Provides access to local and remote processes and enables you to start and stop local system processes.
/// </summary>
/// <remarks>A <see cref="Process"/> component provides access to a process that is running on a computer.
/// A process, in the simplest terms, is a running application.
/// A thread is the basic unit to which the operating system allocates processor time.
/// A thread can execute any part of the code of the process, including parts currently being executed by another thread.</remarks>
public class Process : System.ComponentModel.Component, IDisposable
{
//process is still active
private const int StillActive = 0x00000103;
//handle to process
private ProcessInfo m_pinfo;
//structure used when starting - contains filename etc
private ProcessStartInfo m_pstart;
//flag to market when process has been killed
private bool m_exited;
private const int SYS_HANDLE_BASE = 64;
private const int SH_WIN32 = 0;
private const int SH_CURTHREAD = 1;
private const int SH_CURPROC = 2;
private const uint SYSHANDLE_OFFSET = 0x004;
private const uint PUserKDataARM = 0xFFFFC800;
private const uint PUserKDataX86 = 0x00005800;
#region Constructor
/// <summary>
/// Initializes a new instance of the OpenNETCF.Diagnostics.Process class.
/// </summary>
public Process()
{
m_pstart = new ProcessStartInfo();
m_pinfo = new ProcessInfo();
m_exited = false;
}
#endregion
#region Dispose
/// <summary>
/// Releases all resources used by the <see cref="Process"/>.
/// </summary>
/// <remarks>Calling <b>Dispose</b> allows the resources used by the <see cref="Process"/> to be reallocated for other purposes.</remarks>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases the unmanaged resources used by the <see cref="Process"/> and optionally releases the managed resources.
/// </summary>
/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
protected override void Dispose(bool disposing)
{
//close process handle
CloseHandle((IntPtr)m_pinfo.hProcess);
base.Dispose (disposing);
}
#endregion
#region Get Process By Id
/// <summary>
/// Returns a new <see cref="Process"/> component, given the identifier of a process on the device.
/// <para><b>New in v1.1</b></para>
/// </summary>
/// <param name="processId">The system-unique identifier of a process resource.</param>
/// <returns>A <see cref="Process"/> component that is associated with the local process resource identified by the processId parameter.</returns>
public static Process GetProcessById(int processId)
{
//create new process
Process newprocess = new Process();
//assign process id
newprocess.m_pinfo.dwProcessID = processId;
//open handle
newprocess.m_pinfo.hProcess = OpenProcess(0, false, (IntPtr)processId);
//return process instance
return newprocess;
}
#endregion
#region Get Process From Hwnd
/*public static Process GetProcessFromHwnd(IntPtr Hwnd)
{
int pid = GetWindowThreadProcessId(Hwnd, IntPtr.Zero);
return GetProcessFromId(pid);
}*/
#endregion
#region Start
/// <summary>
/// Starts a process resource by specifying the name of a document or application file and associates the resource with a new OpenNETCF.Diagnostics.Process component.
/// </summary>
/// <param name="fileName">The name of a document or application file to run in the process.</param>
/// <param name="arguments">Command line arguments to pass when starting the process.</param>
public static Process Start(string fileName, string arguments)
{
return Process.Start(new ProcessStartInfo(fileName, arguments));
}
/// <summary>
/// Starts a process resource by specifying the name of a document or application file and associates the resource with a new OpenNETCF.Diagnostics.Process component.
/// </summary>
/// <param name="fileName">The name of a document or application file to run in the process.</param>
/// <returns>A new OpenNETCF.Diagnostics.Process component that is associated with the process resource, or null, if no process resource is started (for example, if an existing process is reused).</returns>
public static Process Start(string fileName)
{
return Process.Start(new ProcessStartInfo(fileName));
}
/// <summary>
/// Starts the process resource that is specified by the parameter containing process start information (for example, the file name of the process to start) and associates the resource with a new OpenNETCF.Diagnostics.Process component.
/// </summary>
/// <param name="startInfo">The OpenNETCF.Diagnostics.ProcessStartInfo that contains the information that is used to start the process, including the file name and any command line arguments.</param>
/// <returns>A new OpenNETCF.Diagnostics.Process component that is associated with the process resource, or null if no process resource is started (for example, if an existing process is reused).</returns>
public static Process Start(ProcessStartInfo startInfo)
{
Process newprocess = new Process();
newprocess.m_pstart = startInfo;
newprocess.Start();
return newprocess;
}
/// <summary>
/// Starts (or reuses) the process resource that is specified by the OpenNETCF.Diagnostics.Process.StartInfo property of this OpenNETCF.Diagnostics.Process component and associates it with the component.
/// </summary>
/// <returns><b>true</b> if a process resource is started; <b>false</b> if no new process resource is started (for example, if an existing process is reused).</returns>
public bool Start()
{
if(m_pstart.UseShellExecute)
{
//create a shellexecute structure
ShellExecuteInfo sei = new ShellExecuteInfo();
//pin strings
GCHandle hfile = GCHandle.Alloc((m_pstart.FileName + '\0').ToCharArray(), GCHandleType.Pinned);
sei.lpFile = (IntPtr)((int)hfile.AddrOfPinnedObject() + 4);
//windowstyle
sei.nShow = (int)m_pstart.WindowStyle;
//pin arguments
GCHandle hargs = new GCHandle();
if(m_pstart.Arguments!=null)
{
hargs = GCHandle.Alloc((m_pstart.Arguments + '\0').ToCharArray(), GCHandleType.Pinned);
sei.lpParameters = (IntPtr)((int)hargs.AddrOfPinnedObject() + 4);
}
//pin verb
GCHandle hverb = new GCHandle();
if(m_pstart.Verb!=null)
{
hverb = GCHandle.Alloc(m_pstart.Verb.ToCharArray(), GCHandleType.Pinned);
sei.lpVerb = (IntPtr)((int)hverb.AddrOfPinnedObject() + 4);
}
//call api function
bool result = ShellExecuteEx(sei);
//store the process handle
this.m_pinfo.hProcess = sei.hProcess;
//free pinned handles
if(hfile.IsAllocated)
{
hfile.Free();
}
if(hargs.IsAllocated)
{
hargs.Free();
}
if(hverb.IsAllocated)
{
hverb.Free();
}
//return status
return result;
}
else
{
return CreateProcess(m_pstart.FileName, m_pstart.Arguments, IntPtr.Zero, IntPtr.Zero, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, m_pinfo);
}
}
#endregion
#region Kill
/// <summary>
/// Immediately stops the associated process.
/// </summary>
/// <exception cref="System.ComponentModel.Win32Exception">The associated process could not be terminated.</exception>
/// <exception cref="System.InvalidOperationException">The process has already exited.</exception>
/// <event></event>
public void Kill()
{
if(!m_exited)
{
IntPtr hProcess = OpenProcess(0, false, this.Handle);
//if successfully terminated
if(TerminateProcess(hProcess, 0))
{
CloseHandle(hProcess);
//raise Exited event
OnExited();
}
else
{
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error(), "The associated process could not be terminated");
}
}
else
{
throw new InvalidOperationException("The process has already exited.");
}
}
#endregion
#region Wait For Exit
/// <summary>
/// Instructs the <see cref="Process"/> component to wait indefinitely for the associated process to exit.
/// </summary>
/// <remarks>WaitForExit is used to make the current thread wait until the associated process terminates.
/// This overload of <see cref="Process.WaitForExit"/> instructs the <see cref="Process"/> component to wait an infinite amount of time for the process to exit.
/// This can cause an application to stop responding.</remarks>
public void WaitForExit()
{
//wait for infinity
WaitForExit(int.MinValue);
}
/// <summary>
/// Instructs the <see cref="T:OpenNETCF.Diagnostics.Process"/> component to wait the specified number of milliseconds for the associated process to exit.
/// </summary>
/// <param name="milliseconds">The amount of time, in milliseconds, to wait for the associated process to exit.
/// The maximum is the largest possible value of a 32-bit integer, which represents infinity to the operating system.</param>
/// <returns>true if the associated process has exited; otherwise, false.</returns>
public bool WaitForExit(int milliseconds)
{
//wait time
uint wait;
//catch max value and convert to infinite flag
if(milliseconds==int.MaxValue | milliseconds==int.MinValue)
{
wait = uint.MaxValue;
}
else if(milliseconds < 0)
{
wait = uint.MaxValue;
}
else
{
wait = Convert.ToUInt32(milliseconds);
}
int result = WaitForSingleObject((IntPtr)this.m_pinfo.hProcess, wait);
if(result==0)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -