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失败
        }
    }

    // 其他服务方法...
}
相关推荐
SRC_BLUE_172 分钟前
Python GUI 编程 | QObject 控件基类详解 — 定时器
开发语言·数据库·python
啊阿狸不会拉杆10 分钟前
第二十一章:Python-Plotly库实现数据动态可视化
开发语言·python·plotly
滴答滴答嗒嗒滴20 分钟前
Python小练习系列 Vol.12:学生信息排序(sorted + key函数)
开发语言·python
愚润求学1 小时前
【C++】vector常用方法总结
开发语言·c++·vector
厦门德仔1 小时前
【C#】C#字符串拼接的6种方式及其性能分析对比
服务器·windows·c#
天天进步20151 小时前
Python项目-基于Flask的个人博客系统设计与实现(1)
开发语言·python·flask
安然无虞1 小时前
31天Python入门——第20天:魔法方法详解
开发语言·后端·爬虫·python
QQ__17646198241 小时前
Matlab安装tdms插件
开发语言·matlab·tdms插件
画个逗号给明天"1 小时前
C#从入门到精通(5)
开发语言·笔记·c#
赤秀2 小时前
C++模板初阶
开发语言·c++