Windows 编程中用Service开启一个外部进程的两种语言实现方式(C++,C#)。

Windows 编程中用Service开启一个外部进程的两种语言实现方式(C++,C#)。

C++实现

新建一个win32项目,主函数方法:

#pragma region Includes
#include "stdafx.h"
#include <string.h>  
#include <stdio.h>  
#include <Windows.h>  
#include <iostream>
#include<fstream>
#include "start_gui.h"
#pragma endregion

#define SERVICE_NAME TEXT("srv_demo")  
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hServiceStatusHandle;
void WINAPI service_main(int argc, char** argv);
void WINAPI ServiceHandler(DWORD fdwControl);

TCHAR szSvcName[80];
SC_HANDLE schSCManager;
SC_HANDLE schService;

DWORD WINAPI srv_core_thread(LPVOID para)
{
    std::wstring bin_path_=L"D:\\a.exe";    
    StartGUIProc obj(bin_path_);
    obj.Run();

    return NULL;
}


void WINAPI ServiceHandler(DWORD fdwControl)
{
    switch (fdwControl)
    {
    case SERVICE_CONTROL_STOP:
    case SERVICE_CONTROL_SHUTDOWN:
        ServiceStatus.dwWin32ExitCode = 0;
        ServiceStatus.dwCurrentState = SERVICE_STOPPED;
        ServiceStatus.dwCheckPoint = 0;
        ServiceStatus.dwWaitHint = 0;
        uaquit = 1;
        //add you quit code here

        break;
    default:
        return;
    };
    if (!SetServiceStatus(hServiceStatusHandle, &ServiceStatus))
    {
        DWORD nError = GetLastError();
    }
}


void WINAPI service_main(int argc, char** argv)
{
    ServiceStatus.dwServiceType = SERVICE_WIN32;
    ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
    ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
    ServiceStatus.dwWin32ExitCode = 0;
    ServiceStatus.dwServiceSpecificExitCode = 0;
    ServiceStatus.dwCheckPoint = 0;
    ServiceStatus.dwWaitHint = 0;
    hServiceStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceHandler);
    if (hServiceStatusHandle == 0)
    {
        DWORD nError = GetLastError();
    }
    //add your init code here

    //add your service thread here
    HANDLE task_handle = CreateThread(NULL, NULL, srv_core_thread, NULL, NULL, NULL);

    if (task_handle == NULL)
    {
        //fprintf(log,"create srv_core_thread failed\n");
    }   
    // Initialization complete - report running status 
    ServiceStatus.dwCurrentState = SERVICE_RUNNING;
    ServiceStatus.dwCheckPoint = 0;
    ServiceStatus.dwWaitHint = 9000;
    if (!SetServiceStatus(hServiceStatusHandle, &ServiceStatus))
    {
        DWORD nError = GetLastError();
    }

}
//do not change main function
int main(int argc, const char *argv[])
{
    SERVICE_TABLE_ENTRY ServiceTable[2];

    ServiceTable[0].lpServiceName = SERVICE_NAME;
    ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)service_main;

    ServiceTable[1].lpServiceName = NULL;
    ServiceTable[1].lpServiceProc = NULL;
    // 启动服务的控制分派机线程
    StartServiceCtrlDispatcher(ServiceTable);
    return 0;
}

开启进程的类:

#include "stdafx.h"
#include "start_gui.h"
#include <windows.h>
#include "WtsApi32.h"
#include "UserEnv.h"
#include <iostream>
#include <string>
#include <tchar.h>

#pragma comment(lib, "Wtsapi32.Lib")
#pragma comment(lib, "Userenv.Lib")
StartGUIProc::StartGUIProc(const std::wstring& processPath, const std::wstring& arguments)
: processPath_(processPath), arguments_(arguments)
{
}

HANDLE StartGUIProc::GetCurrentUserToken()
{
    PWTS_SESSION_INFO pSessionInfo = 0;
    DWORD dwCount = 0;
    ::WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &dwCount);
    int session_id = 0;
    for (DWORD i = 0; i < dwCount; ++i)
    {
        WTS_SESSION_INFO si = pSessionInfo[i];
        if (WTSActive == si.State)
        {
            session_id = si.SessionId;
            break;
        }
    }
    ::WTSFreeMemory(pSessionInfo);
    HANDLE current_token = 0;
    BOOL bRet = ::WTSQueryUserToken(session_id, &current_token);
    int errorcode = GetLastError();
    if (bRet == false)
    {
        return 0;
    }
    HANDLE primaryToken = 0;
    bRet = ::DuplicateTokenEx(current_token, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &primaryToken);
    errorcode = GetLastError();
    if (bRet == false)
    {
        return 0;
    }
    return primaryToken;
}

BOOL StartGUIProc::Run()
{
    HANDLE primaryToken = GetCurrentUserToken();
    if (primaryToken == 0)
    {
        return FALSE;
    }
    STARTUPINFO StartupInfo = { 0 };
    PROCESS_INFORMATION processInfo;
    StartupInfo.cb = sizeof(STARTUPINFO);

    std::wstring command = L"\"" + processPath_ + L"\"";
    if (arguments_.length() != 0)
    {
        command += L" " + arguments_;
    }
    void* lpEnvironment = NULL;
    BOOL resultEnv = ::CreateEnvironmentBlock(&lpEnvironment, primaryToken, FALSE);
    if (resultEnv == 0)
    {
        long nError = GetLastError();
    }
    BOOL result = ::CreateProcessAsUser(primaryToken, 0, (LPWSTR)(command.c_str()), NULL, NULL, FALSE, CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT, NULL, 0, &StartupInfo, &processInfo);
    ::DestroyEnvironmentBlock(lpEnvironment);
    ::CloseHandle(primaryToken);
    return result;
}

C#实现:项目需要引用Cjwdev.WindowsApi.dll

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.IO;
using Microsoft.Win32;

namespace ServiceTest
{
    public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {             
            Tools.StartApp(@"C:\Users\Administrator\Desktop\a.exe");
        }

        protected override void OnStop()
        {

        }          
    }
}

开启进程的类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.IO;
using Microsoft.Win32;
using Cjwdev;
using Cjwdev.WindowsApi;
using System.Runtime.InteropServices;

namespace Servicetest
{
    class Tools
    {
        public static void StartApp(string strAppPath)
        {
            try
            {
                string appStartPath = strAppPath;
                IntPtr userTokenHandle = IntPtr.Zero;
                ApiDefinitions.WTSQueryUserToken(ApiDefinitions.WTSGetActiveConsoleSessionId(), ref userTokenHandle);

                ApiDefinitions.PROCESS_INFORMATION procInfo = new ApiDefinitions.PROCESS_INFORMATION();
                ApiDefinitions.STARTUPINFO startInfo = new ApiDefinitions.STARTUPINFO();
                startInfo.cb = (uint)Marshal.SizeOf(startInfo);

                ApiDefinitions.CreateProcessAsUser(
                    userTokenHandle,
                    appStartPath,
                    "",
                    IntPtr.Zero,
                    IntPtr.Zero,
                    false,
                    0,
                    IntPtr.Zero,
                    null,
                    ref startInfo,
                    out procInfo);

                if (userTokenHandle != IntPtr.Zero)
                    ApiDefinitions.CloseHandle(userTokenHandle);

                int _currentAquariusProcessId = (int)procInfo.dwProcessId;
            }
            catch (Exception ex)
            {

            }  
        }   
    }
}

!!!特别注意:如果需要打开的外部程序引用了其他动态库,请将生成的服务.exe放在与需要打开的程序及动态库在同级目录下,然后安装服务,否则Service不能打开外部程序。

至于Windows如何创建一个Service,安装卸载服务以及打开外部程序的其他实现请参考以下链接,同时感谢以下文章的作者:
1. 【转】用C/C++创建windows服务程序
2. 【转】 解决vista和win7在windows服务中交互桌面权限问题:穿透Session 0 隔离
3. CreateProcessAsUser,C#写的windows服务弹框提示消息或者启动子进程
4. C#创建Windows服务与安装

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
实现 C++ 代码自动提示的方式实现 C# 代码自动提示的方式类似。以下是一个简单的示例代码,可以实现在 RichTextBox 中输入 C++ 代码时,根据当前光标所在行的文本自动提示相关的 C++ 关键字和标识符: ``` private void richTextBox1_TextChanged(object sender, EventArgs e) { // 获取当前光标所在行的文本 int index = richTextBox1.SelectionStart; int line = richTextBox1.GetLineFromCharIndex(index); string text = richTextBox1.Lines[line]; // 根据文本获取匹配的代码提示列表 List<string> suggestions = GetSuggestions(text); // 清空 ListBox,并添加提示项 listBox1.Items.Clear(); listBox1.Items.AddRange(suggestions.ToArray()); // 显示 ListBox if (suggestions.Count > 0) { listBox1.Visible = true; listBox1.Width = richTextBox1.Width; listBox1.Top = richTextBox1.Top + (line + 1) * richTextBox1.Font.Height; listBox1.Left = richTextBox1.Left; } else { listBox1.Visible = false; } } private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { // 将选中的提示项插入到 RichTextBox 中 int index = richTextBox1.SelectionStart; int line = richTextBox1.GetLineFromCharIndex(index); int start = richTextBox1.GetFirstCharIndexFromLine(line); int length = index - start; string suggestion = listBox1.SelectedItem.ToString(); richTextBox1.SelectionStart = start; richTextBox1.SelectionLength = length; richTextBox1.SelectedText = suggestion; listBox1.Visible = false; } private List<string> GetSuggestions(string text) { // 根据文本获取匹配的代码提示列表 List<string> suggestions = new List<string>(); if (text.StartsWith("#")) { // C++ 预处理指令 suggestions.Add("#define"); suggestions.Add("#include"); suggestions.Add("#ifdef"); suggestions.Add("#ifndef"); suggestions.Add("#endif"); } else if (text.EndsWith(".")) { // C++ 命名空间 suggestions.Add("std"); } else { // C++ 关键字和标识符 suggestions.Add("auto"); suggestions.Add("break"); suggestions.Add("case"); suggestions.Add("char"); suggestions.Add("class"); suggestions.Add("const"); suggestions.Add("continue"); suggestions.Add("default"); suggestions.Add("delete"); suggestions.Add("do"); suggestions.Add("double"); suggestions.Add("else"); suggestions.Add("enum"); suggestions.Add("extern"); suggestions.Add("float"); suggestions.Add("for"); suggestions.Add("friend"); suggestions.Add("goto"); suggestions.Add("if"); suggestions.Add("inline"); suggestions.Add("int"); suggestions.Add("long"); suggestions.Add("mutable"); suggestions.Add("namespace"); suggestions.Add("new"); suggestions.Add("operator"); suggestions.Add("private"); suggestions.Add("protected"); suggestions.Add("public"); suggestions.Add("register"); suggestions.Add("return"); suggestions.Add("short"); suggestions.Add("signed"); suggestions.Add("sizeof"); suggestions.Add("static"); suggestions.Add("struct"); suggestions.Add("switch"); suggestions.Add("template"); suggestions.Add("this"); suggestions.Add("throw"); suggestions.Add("try"); suggestions.Add("typedef"); suggestions.Add("typeid"); suggestions.Add("typename"); suggestions.Add("union"); suggestions.Add("unsigned"); suggestions.Add("using"); suggestions.Add("virtual"); suggestions.Add("void"); suggestions.Add("volatile"); suggestions.Add("wchar_t"); suggestions.Add("while"); } return suggestions; } ``` 需要注意的是,上述示例只是为了演示实现 C++ 代码自动提示的思路,实际应用中需要根据 C++ 语法规则和标准库的使用情况来生成代码提示列表。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sun-Eve

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值