Windows services 如何将DART应用程序作为windows服务运行?
我一直在研究在我的下一个项目中使用DART语言的可能性。在这一点上,唯一真正阻碍我的是,我无法找到一种方法将DART应用程序作为windows服务运行。我在谷歌上进行了搜索,并阅读了DART网站上的大部分文档。我发现的大部分信息都与在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
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);
}