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

    // 其他服务方法...
}
相关推荐
明如正午12 分钟前
【C#】跨线程更新进度条_UpdateProgress 方法解析
c#
bu_shuo1 小时前
MATLAB中的meshgrid和ndgrid
开发语言·matlab
我命由我123452 小时前
Jetpack Compose - MaterialExpressiveTheme 与 MaterialTheme、ColorScheme
android·java·开发语言·java-ee·kotlin·android jetpack·android runtime
曹牧2 小时前
C#:`JsonConvert.DeserializeObject`
windows·c#
深海呐2 小时前
仓颉语言是ArkTs的上层语言吗?就像kotlin和Java
java·开发语言·kotlin·仓颉
白露与泡影2 小时前
聊聊物联网Java后端的核心技术难点(水表/电表/充电桩实战)
java·开发语言·物联网
gumichef2 小时前
第一章:面向对象核心——类和对象深度讲解
开发语言·c++
冷咖啡离 我的笨笨2 小时前
数据去重:通过 C# 删除 Excel 中的重复行
开发语言·c#·excel
ao-weilai2 小时前
C++基础:类和对象
开发语言·c++
夜雪一千3 小时前
Python从HTML提取纯文本、去空格、比对内容是否变化:方案+合理性分析
开发语言·python·html