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

    // 其他服务方法...
}
相关推荐
AmosCloud20135 分钟前
3.5 字典树(Trie)与后缀树
开发语言·数据结构·链表·c#
Tiger Z23 分钟前
R 语言科研绘图第 13 期 --- 柱状图-堆叠
开发语言·程序人生·r语言·贴图
我命由我1234531 分钟前
26.Java Lock 接口(synchronized 关键字回顾、可重入锁快速入门、Lock 对比 synchronized)
java·开发语言·后端·java-ee·intellij-idea·intellij idea·后端开发
nixiaoge36 分钟前
组网实训实现
开发语言·php
graceyun43 分钟前
牛客网刷题 ——C语言初阶(5操作符)——BC111 小乐乐与进制转换
c语言·开发语言·算法
JoneMaster1 小时前
[读书日志]从零开始学习Chisel 第二篇:Scala的变量与函数(敏捷硬件开发语言Chisel与数字系统设计)
开发语言·学习·scala
小_太_阳1 小时前
Scala_【5】函数式编程
开发语言·后端·scala·intellij-idea
玉面小君1 小时前
C#设计模式(行为型模式):备忘录模式,时光倒流的魔法
设计模式·c#·备忘录模式
hummhumm2 小时前
第8章 汇编语言--- 循环结构
java·运维·开发语言·汇编·数据结构·算法·汇编语言
奇偶变不变2 小时前
30分钟学会LaTex
开发语言·前端·javascript