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

    // 其他服务方法...
}
相关推荐
t***5447 小时前
Clang 编译器在 Orwell Dev-C++ 中的局限性
开发语言·c++
oy_mail7 小时前
QoS质量配置
开发语言·智能路由器·php
oyzz1208 小时前
PHP操作redis
开发语言·redis·php
nashane8 小时前
HarmonyOS 6学习:网络能力变化监听与智能提示——告别流量偷跑,打造贴心网络感知应用
开发语言·php·harmony app
凌波粒8 小时前
Java 8 “新”特性详解:Lambda、函数式接口、Stream、Optional 与方法引用
java·开发语言·idea
拾贰_C9 小时前
【Google | Gemini | API | POST】怎么使用Google 的Gemini API (原生版)
开发语言·lua
t***54410 小时前
如何在Dev-C++中选择Clang编译器
开发语言·c++
橙子1991101610 小时前
Java 基础相关
java·开发语言
星越华夏11 小时前
python——三角函数用法
开发语言·python