c# 服务中启动exe窗体程序

Windows服务默认在会话0(Session 0)中运行,这是一个隔离的环境,旨在防止服务与应用程序和用户会话交互,从而提高系统的稳定性和安全性。由于这个原因,直接从服务启动的GUI应用程序将不会显示,因为它们没有与用户桌面交互的能力。

为了在用户会话中启动一个GUI应用程序,你可以使用CreateProcessAsUser函数。这个函数允许你在指定用户的安全上下文中创建一个新进程。以下是使用CreateProcessAsUser函数在特定用户会话中启动进程的步骤和示例代码:

步骤:

  1. 获取目标用户的安全令牌。
  2. 使用CreateProcessAsUser函数在新用户的会话中创建进程。

以下是一个C#示例,演示如何使用CreateProcessAsUser

复制代码
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Principal;

public partial class YourService : ServiceBase
{
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);

    [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 lpProcessInfo);

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool CloseHandle(IntPtr hObject);

    // 定义其他需要的结构体和常量...

    protected override void OnStart(string[] args)
    {
        string applicationName = "PathToYourExe.exe";
        string username = "YourUsername";
        string domain = "YourDomain";
        string password = "YourPassword";

        IntPtr tokenHandle = IntPtr.Zero;
        IntPtr dupTokenHandle = IntPtr.Zero;
        PROCESS_INFORMATION procInfo = new PROCESS_INFORMATION();
        STARTUPINFO startupInfo = new STARTUPINFO();

        // LogonUser获取用户令牌
        bool loggedOn = LogonUser(username, domain, password, 2, 0, out tokenHandle);

        if (loggedOn)
        {
            // 准备启动信息
            startupInfo.cb = Marshal.SizeOf(typeof(STARTUPINFO));

            // 复制令牌以获取必要的权限
            if (!DuplicateToken(tokenHandle, 2, ref dupTokenHandle))
            {
                // 处理错误
            }

            // 创建进程
            bool result = CreateProcessAsUser(dupTokenHandle, null, applicationName, ref SECURITY_ATTRIBUTES.Null, ref SECURITY_ATTRIBUTES.Null, false, 0, IntPtr.Zero, null, ref startupInfo, out procInfo);

            if (!result)
            {
                // 处理错误
            }

            // 释放句柄
            CloseHandle(tokenHandle);
            CloseHandle(dupTokenHandle);
            CloseHandle(procInfo.hThread);
            CloseHandle(procInfo.hProcess);
        }
        else
        {
            // 处理LogonUser失败
        }
    }

    // 其他服务方法...
}
相关推荐
Pocker_Spades_A12 分钟前
从 0 到 1 开发图书管理系统:飞算 JavaAI 让技术落地更简单
java·开发语言·java开发·飞算javaai炫技赛
郝学胜-神的一滴19 分钟前
对于类似std::shared_ptr但有可能空悬的指针使用std::weak_ptr: Effective Modern C++ 条款20
开发语言·c++·程序人生·系统架构
linux修理工40 分钟前
使用 SecureCRT 连接华为 eNSP 模拟器的方法
服务器·开发语言·php
若水晴空初如梦1 小时前
QT聊天项目DAY17
开发语言·qt
Murphy_lx1 小时前
C++ stdset 与 stdmultiset 深度比较
开发语言·c++
LZQqqqqo1 小时前
C# 事件Event
开发语言·c#
样子20182 小时前
PHP 之使用HTMLPurifier过滤XSS
开发语言·前端·php·xss
时光追逐者2 小时前
C#/.NET/.NET Core优秀项目和框架2025年7月简报
c#·.net·.netcore
枫叶梨花2 小时前
使用Go语言获取Windows系统信息:从CPU到电池的全维度监控
开发语言·windows·golang
C_Liu_3 小时前
从C语言到C++:拥抱面向对象编程的全新世界
c语言·开发语言·c++