使用
System.Diagnostics.Process.Start()
启动进程的方式并不有效,因为生成的进程会在创建窗口后立即退出。.cpl小程序不是标准可执行文件,需要操作系统 shell 和启动器才能启动。
然而,可以使用
Rundll32.exe
创建一个稳定的进程,它将生成一些线程来托管小程序控件和 GDI+ 支持。
尽管如此,要想访问小程序窗口仍然需要进行一些 P/Invoke 操作,因为
rundll
没有窗口,也没有引用它帮助创建的窗口,所以
Process.MainWindowHandle = 0
。
文档参考 MSDN EnumThreadWndProc() 回调函数, EnumThreadWindows(), GetWindowRect(), GetWindowText(), SetWindowPos()
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
ProcessStartInfo psInfo = new ProcessStartInfo() ;
Process sysClockProcess = new Process() ;
sysClockProcess.Start();
sysClockProcess.WaitForInputIdle();
string windowTitle = "Date and Time";
int maxLenght = 256;
SetWindowPosFlags flags = SetWindowPosFlags.NoSize |
SetWindowPosFlags.AsyncWindowPos |
SetWindowPosFlags.ShowWindow;
EnumThreadWindows((uint)sysClockProcess.Threads[0].Id, (hWnd, lParam) =>
return true;
}, ref windowTitle);
sysClockProcess.Exited += (s, ev) => Time: ");
sysClockProcess.Dispose();
};
Win32 声明:
// SetWindowPos() flags
[Flags]
public enum SetWindowPosFlags : uint
{
NoSize = 0x0001,
NoActivate = 0x0010,
ShowWindow = 0x0040,
DeferErase = 0x2000,
AsyncWindowPos = 0x4000
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
//Callback for `EnumThreadWindows()`.
public delegate bool EnumThreadWndProc([In] IntPtr hWnd, [In] IntPtr lParam);
[DllImport("user32.dll")]
static extern bool EnumThreadWindows([In] uint dwThreadId, [In] EnumThreadWndProc lpfn, [In] ref string lParam);
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, [Out] StringBuilder lpString, [In] int nMaxCount);
[DllImport("user32.dll", SetLastError = true)]
static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
[DllImport("user32.dll", SetLastError=true)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);