Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows services 如何将DART应用程序作为windows服务运行?_Windows Services_Dart - Fatal编程技术网

Windows services 如何将DART应用程序作为windows服务运行?

Windows services 如何将DART应用程序作为windows服务运行?,windows-services,dart,Windows Services,Dart,我一直在研究在我的下一个项目中使用DART语言的可能性。在这一点上,唯一真正阻碍我的是,我无法找到一种方法将DART应用程序作为windows服务运行。我在谷歌上进行了搜索,并阅读了DART网站上的大部分文档。我发现的大部分信息都与在DART中创建服务器有关,但与windows服务无关 有人能给我指点方向或详细说明这样做的必要步骤吗 谢谢, Jon将Dart用于Windows服务与任何其他可执行文件没有区别;您只需要使用正确的参数调用dart.exe 但是,Windows不支持将任意EXE作为W

我一直在研究在我的下一个项目中使用DART语言的可能性。在这一点上,唯一真正阻碍我的是,我无法找到一种方法将DART应用程序作为windows服务运行。我在谷歌上进行了搜索,并阅读了DART网站上的大部分文档。我发现的大部分信息都与在DART中创建服务器有关,但与windows服务无关

有人能给我指点方向或详细说明这样做的必要步骤吗

谢谢,
Jon

将Dart用于Windows服务与任何其他可执行文件没有区别;您只需要使用正确的参数调用dart.exe

但是,Windows不支持将任意EXE作为Windows服务运行,因为它们需要少量元数据/引导。我在这方面有很好的经验。在评论中,建议使用SC.exe;但我无法在最新版本的Windows Server上运行它:(

==最新更新===

我最初的答案是使用C和Dart FFI来提升Windows服务。然而,这些都不是真正需要的,因为通过使用Docker和Windows容器可以获得一个非常简单的解决方案

替代方法是将应用程序编译为可执行的Windows控制台应用程序,创建Docker文件和包含该应用程序的Windows Docker映像,而不是将其作为Windows服务实际运行。在服务器上,您需要Docker,只需使用--restart选项运行映像即可。要测试此操作,请退出WindowsS10支持带有Windows容器的Docker

因此,简单的解决方案是,我们实际上不需要将Dart代码作为Windows服务运行,因为我们可以将其作为服务器上的docker容器运行

==原始答案===

我在游戏中迟到了,但我找到了一种不用使用第三方应用程序就能解决这个问题的方法

我的解决方案有点像黑客,但它确实有效。我正在将dart应用程序编译为可执行文件,然后使用sc.exe create将其注册为Windows服务。sc.exe create的问题是,应用程序的主要功能需要执行一些额外的步骤来通知Windows它正在运行。如果不这样做,Windows将服务陷于“启动状态”

< P>我不认为有一个PUB包可以执行这个任务。但是,我们可以使用2件事情:DART:FFI,以及下面的Mohit Arora文章,它解释了如何在C++中创建Windows服务。 我抓取了Mohit的代码并做了大量的更改(包括将其向后移植到C,因为…C++)

C 下面是Service.c文件的完整代码:


// Provides an API for Dart console applications to
// integrate themselves as Windows Services
// The entry point to this API is the Init(...)
// function at the bottom of this file.

// The Init(...) function registers the ServiceMain(...)
// function as the actual windows service function.
// the ServiceMain function does the following:
//
// 1. Registers the ServiceCtrlHandler(...) function 
// as the service control handler, which is essentially
// tasked to handle control requests (in this case we 
// are only handling the request to stop the service).
//
// 2. Creates an event object that and then waits indefinitely 
// for the event to be set.
//
// The ServiceCtrlHandler(...) function responds to a
// close request by setting the event created by the 
// ServiceMain(...) function, essentially freeing 
// the latter from the indefinite wait and terminating
// it.

// The functions in this file don't actually 
// do any work, but keep the Windows Service
// alive. The work be initiated by the calling 
// application either before or after the call to Init(...).

// Because this was developed for the purpose
// of enabling Dart applications to run as 
// Windows Services, it it the Dart Application 
// that needs to call Init(...) using Dart FFI.
// It must also be the Dart Application to 
// spawn an isolate that does the actual work
// before the call to Init(...)

#include <Windows.h>
#include <tchar.h>

#include "service.h"


SERVICE_STATUS        g_ServiceStatus = { 0 };
SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
HANDLE                g_ServiceStopEvent = INVALID_HANDLE_VALUE;


LPWSTR w_service_name;


void UpdateStatus(
    DWORD newState,
    DWORD checkPoint,
    DWORD exitCode,
    DWORD controlsAccepted)
{
    g_ServiceStatus.dwControlsAccepted = controlsAccepted;
    g_ServiceStatus.dwCurrentState = newState;
    g_ServiceStatus.dwWin32ExitCode = exitCode;
    g_ServiceStatus.dwCheckPoint = checkPoint;

    SetServiceStatus(g_StatusHandle, &g_ServiceStatus);
}


// Responds to control events. This implementation is
// only responding to the SERVICE_CONTROL_STOP event
// This method signals the ServiceMain function
// that it can stop waiting before terminating.
void WINAPI ServiceCtrlHandler(DWORD CtrlCode)
{
    if (CtrlCode != SERVICE_CONTROL_STOP || g_ServiceStatus.dwCurrentState != SERVICE_RUNNING)
        return;

    UpdateStatus(SERVICE_STOP_PENDING, 4, 0, 0);

    SetEvent(g_ServiceStopEvent);

}


void InitServiceStatus()
{
    ZeroMemory(&g_ServiceStatus, sizeof(g_ServiceStatus));
    g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    g_ServiceStatus.dwServiceSpecificExitCode = 0;
    UpdateStatus(SERVICE_START_PENDING, 0, 0, 0);
}


// This function essentially creates an event object 
// and enters a holding pattern until that event object 
// is set by the ServiceCtrlHandler(...) in response
// to a close request.

// The function doesn't actually do any work,
// except to keep the Windows Service alive.
void WINAPI ServiceMain(DWORD argc, LPTSTR* argv)
{
    g_StatusHandle = RegisterServiceCtrlHandler(w_service_name, ServiceCtrlHandler);

    if (g_StatusHandle == NULL)
        return;

    InitServiceStatus();

    g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    if (g_ServiceStopEvent == NULL)
    {
        UpdateStatus(SERVICE_STOPPED, 1, GetLastError(), 0);
        return;
    }

    UpdateStatus(SERVICE_RUNNING, 0, 0, SERVICE_ACCEPT_STOP);

    while (WaitForSingleObject(g_ServiceStopEvent, INFINITE) != WAIT_OBJECT_0)
        ;

    CloseHandle(g_ServiceStopEvent);
    UpdateStatus(SERVICE_STOPPED, 3, 0, 0);
}



LPWSTR get_service_name(const char* service_name)
{
    int max_count = strlen(service_name);
    int size = max_count + 1;
    LPWSTR ret = malloc(sizeof(wchar_t) * size);
    size_t outSize;
    mbstowcs_s(&outSize, ret, size, service_name, max_count);
    return ret;
}



/// This is the entry point that should be called
/// by the Dart application (or any application 
/// of a similar kind of platform) in order to 
/// integrate itself as a Windows Service.
/// It registers the ServiceMain(...) function
/// as the service main function. Please consult
/// the comments at that function to understand
/// what it does.
int init(const char* service_name)
{
    w_service_name = get_service_name(service_name);

    SERVICE_TABLE_ENTRY ServiceTable[] =
    {
        {w_service_name, (LPSERVICE_MAIN_FUNCTION)ServiceMain},
        {NULL, NULL}
    };

    if (StartServiceCtrlDispatcher(ServiceTable) == FALSE)
        return GetLastError();
}


只需确保将WINSERVICE_导出添加到其中一个定义中,或者用项目中相应的定义替换它

飞奔 我还需要从Dart方面进行一些更改。以下是我的原型:


import 'dart:ffi' as ffi;
import 'dart:io';
import 'dart:isolate';
import 'package:ffi/ffi.dart';
import 'package:grpc/grpc.dart' as grpc;

// These two types represent the
// Init(...) function of the C API
typedef init_func = ffi.Int32 Function(ffi.Pointer<Utf8>);
typedef Init = int Function(ffi.Pointer<Utf8>);

// Entry point to the Dart application.
// When run as a Windows Service,
// this is still the entry point.
// This code is not embeded but is started
// as a regular console application.
void main() async {
  final init = createInit();

  // Starts the actual work in a separate Isolate
  await Isolate.spawn(run, 'message');

  final serviceName = Utf8.toUtf8('MProto_Server_from_Dart');
  // calls the Init(...) function
  var result = init(serviceName);
  if (result != 0) return;

  // blocks this Isolate indefinitely from continuing
  while (true) {
    sleep(Duration(days: 365));
  }
}

// Creates the instance of the proxy to the Init(...)
// function.
Init createInit() {
  final path =
      r'[PATH to the C compiled DLL]';
  final dylib = ffi.DynamicLibrary.open(path);

  // ignore: omit_local_variable_types
  final Init init =
      dylib.lookup<ffi.NativeFunction<init_func>>('init').asFunction();
  return init;
}


// Performs the actual work that needs to
// be done, in this case, we are hosting
// a gRPC service, but this should 
// work with any other kind of 
// payload, namely other types of
// http services.
void run(String message) async {
  print('inside isolate');
  var server = grpc.Server(
    [
// my service classes
    ],
  );
  await server.serve(port: 5001);
}



输入“dart:ffi”作为ffi;
导入“dart:io”;
导入“dart:隔离”;
进口“包装:ffi/ffi.dart”;
将“包装:grpc/grpc.dart”作为grpc导入;
//这两种类型代表
//C API的Init(…)函数
typedef init_func=ffi.Int32函数(ffi.Pointer);
typedef Init=int函数(ffi.Pointer);
//Dart应用程序的入口点。
//作为Windows服务运行时,
//这仍然是切入点。
//此代码未嵌入,但已启动
//作为常规的控制台应用程序。
void main()异步{
final init=createInit();
//在单独的隔离中开始实际工作
等待隔离.spawn(运行'message');
final serviceName=Utf8.toUtf8('MProto_Server_from_Dart');
//调用Init(…)函数
var result=init(serviceName);
如果(结果!=0)返回;
//无限期阻止此隔离继续
while(true){
睡眠(持续时间:365天);
}
}
//创建Init(…)的代理实例
//功能。
Init createInit(){
最终路径=
r'[C编译DLL的路径];
final dylib=ffi.DynamicLibrary.open(路径);
//忽略:忽略\本地\变量\类型
最终初始化初始化=
dylib.lookup('init').asFunction();
返回init;
}
//执行需要执行的实际工作
//完成,在这种情况下,我们是主机
//gRPC服务,但这应该
//与任何其他类型的
//有效载荷,即其他类型的
//http服务。
无效运行(字符串消息)异步{
打印(“内部隔离”);
var server=grpc.server(
[
//我的服务课
],
);
等待服务器服务(端口:5001);
}

也许我遗漏了一些东西,但问题是什么?你可以为你的dart脚本创建一个服务,就像为其他所有可执行文件创建服务一样,不是吗?事实上,除了使用Visual Studio在C#.Net中的一些东西外,我从来没有在Windows上为其他任何东西创建过服务。你可能对任何通用脚本都有这样做的指导吗?应该这样做吗e技巧。可执行文件是dart.exe,dart文件的路径是参数-您可能需要在创建参数后在services.msc中手动添加该参数。非常感谢…我将尝试一下。@user1125786您成功了吗?如果成功了,您能告诉我怎么做吗?因为当我尝试启动它时,它会出现一个错误
,服务没有响应及时启动或控制请求

import 'dart:ffi' as ffi;
import 'dart:io';
import 'dart:isolate';
import 'package:ffi/ffi.dart';
import 'package:grpc/grpc.dart' as grpc;

// These two types represent the
// Init(...) function of the C API
typedef init_func = ffi.Int32 Function(ffi.Pointer<Utf8>);
typedef Init = int Function(ffi.Pointer<Utf8>);

// Entry point to the Dart application.
// When run as a Windows Service,
// this is still the entry point.
// This code is not embeded but is started
// as a regular console application.
void main() async {
  final init = createInit();

  // Starts the actual work in a separate Isolate
  await Isolate.spawn(run, 'message');

  final serviceName = Utf8.toUtf8('MProto_Server_from_Dart');
  // calls the Init(...) function
  var result = init(serviceName);
  if (result != 0) return;

  // blocks this Isolate indefinitely from continuing
  while (true) {
    sleep(Duration(days: 365));
  }
}

// Creates the instance of the proxy to the Init(...)
// function.
Init createInit() {
  final path =
      r'[PATH to the C compiled DLL]';
  final dylib = ffi.DynamicLibrary.open(path);

  // ignore: omit_local_variable_types
  final Init init =
      dylib.lookup<ffi.NativeFunction<init_func>>('init').asFunction();
  return init;
}


// Performs the actual work that needs to
// be done, in this case, we are hosting
// a gRPC service, but this should 
// work with any other kind of 
// payload, namely other types of
// http services.
void run(String message) async {
  print('inside isolate');
  var server = grpc.Server(
    [
// my service classes
    ],
  );
  await server.serve(port: 5001);
}