CreateProcessAsUser,C#写的windows服务弹框提示消息或者启动子进程
时间: 2024-03-02 16:51:00 浏览: 26
您好,针对您的问题,可以使用以下代码实现:
```csharp
using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Windows.Forms;
namespace WindowsServiceDialog
{
public partial class ServiceDialog : Form
{
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool CreateProcessAsUser(
IntPtr hToken,
string lpApplicationName,
string lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
bool bInheritHandles,
uint dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(
IntPtr ProcessHandle,
uint DesiredAccess,
out IntPtr TokenHandle);
[DllImport("userenv.dll", SetLastError = true)]
private static extern bool CreateEnvironmentBlock(
out IntPtr lpEnvironment,
IntPtr hToken,
bool bInherit);
[DllImport("userenv.dll", SetLastError = true)]
private static extern bool DestroyEnvironmentBlock(
IntPtr lpEnvironment);
private const uint TOKEN_QUERY = 0x0008;
private const uint TOKEN_DUPLICATE = 0x0002;
private const uint TOKEN_ASSIGN_PRIMARY = 0x0001;
private const uint GENERIC_ALL_ACCESS = 0x10000000;
private const uint CREATE_NEW_CONSOLE = 0x00000010;
private const uint CREATE_UNICODE_ENVIRONMENT = 0x00000400;
private const int SW_SHOW = 5;
private IntPtr _userToken;
private IntPtr _envBlock;
[StructLayout(LayoutKind.Sequential)]
private struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
[StructLayout(LayoutKind.Sequential)]
private struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)]
private struct STARTUPINFO
{
public int cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
public ServiceDialog()
{
InitializeComponent();
}
private void ServiceDialog_Load(object sender, EventArgs e)
{
// 获取当前用户的令牌
WindowsIdentity currentUser = WindowsIdentity.GetCurrent();
if (currentUser != null)
{
if (!OpenProcessToken(currentUser.Token, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY, out _userToken))
{
MessageBox.Show("无法获取当前用户的令牌!");
}
}
}
private void btnShowDialog_Click(object sender, EventArgs e)
{
MessageBox.Show("Hello World!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void btnStartProcess_Click(object sender, EventArgs e)
{
if (_userToken != IntPtr.Zero)
{
// 构造启动进程的信息结构体
STARTUPINFO startupInfo = new STARTUPINFO();
startupInfo.cb = Marshal.SizeOf(startupInfo);
startupInfo.lpDesktop = "winsta0\\default";
startupInfo.dwFlags = 0x00000100;
// 创建进程的安全属性
SECURITY_ATTRIBUTES processAttributes = new SECURITY_ATTRIBUTES();
processAttributes.nLength = Marshal.SizeOf(processAttributes);
processAttributes.bInheritHandle = true;
// 创建线程的安全属性
SECURITY_ATTRIBUTES threadAttributes = new SECURITY_ATTRIBUTES();
threadAttributes.nLength = Marshal.SizeOf(threadAttributes);
IntPtr environmentPtr = IntPtr.Zero;
if (CreateEnvironmentBlock(out environmentPtr, _userToken, false))
{
_envBlock = environmentPtr;
}
else
{
MessageBox.Show("无法创建环境块!");
}
// 启动进程
PROCESS_INFORMATION processInfo = new PROCESS_INFORMATION();
if (!CreateProcessAsUser(
_userToken,
null,
"notepad.exe",
ref processAttributes,
ref threadAttributes,
false,
CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
_envBlock,
null,
ref startupInfo,
out processInfo))
{
MessageBox.Show("无法启动进程!");
}
DestroyEnvironmentBlock(_envBlock);
}
else
{
MessageBox.Show("未获取到当前用户的令牌!");
}
}
private void ServiceDialog_FormClosing(object sender, FormClosingEventArgs e)
{
if (_userToken != IntPtr.Zero)
{
CloseHandle(_userToken);
}
}
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);
}
}
```
以上代码实现了一个 Windows 窗体程序,其中包含两个按钮,分别用于弹出提示框和启动子进程。在服务中使用时,可以将此程序安装为 Windows 服务,并在需要弹出提示框或启动子进程的时候,调用相应的方法即可。需要注意的是,如果要启动的子进程需要与当前用户交互,需要获取当前用户的令牌,并使用 `CreateProcessAsUser` 函数创建进程。