OdysseusYuan/LKY_OfficeTools · error · Exception

创建服务 时,返回值为空!

Error message

创建服务 {serv_name} 时,返回值为空!

What it means

Thrown in Com_ServiceOS.Config.Create when the stdout captured from `sc create ...` via Com_ExeOS.Run.Cmd is null or empty (Com_ServiceOS.cs:303-305). Run.Cmd only returns null inside its own catch (cmd.exe launch or stdio-redirect failure), so an empty result indicates the command never produced output rather than an sc-level failure (access-denied still yields non-empty text). Create catches the throw, logs it, and returns false (Com_ServiceOS.cs:326-330).

Solutions

  1. Run as administrator (Create requires privileges anyway for sc create).
  2. Verify cmd.exe is reachable on PATH and not blocked by policy.
  3. Reproduce by running the exact `sc create ...` string from a real console.
  4. Inspect the application log (Lib_AppLog) for the underlying exception written by Run.Cmd's catch.

Example fix

// before
bool ok = Com_ServiceOS.Config.Create(name, path, display);

// after
if (string.IsNullOrEmpty(Com_ExeOS.Run.Cmd("ver"))) { /* cmd unavailable; fix environment */ return false; }
bool ok = Com_ServiceOS.Config.Create(name, path, display);
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrEmpty(Com_ExeOS.Run.Cmd("ver"))) { /* cmd unavailable; fix env */ return false; }
bool ok = Com_ServiceOS.Config.Create(name, path, display, desc);

Prevention

When it happens

Trigger: Run.Cmd throws because cmd.exe cannot be started, standard-output redirection fails, or the process is killed before emitting output. Extremely unlikely from a plain sc access-denied, which still prints an error string.

Common situations: cmd.exe missing/off-path on a stripped image; an aggressive security product blocking child cmd.exe; stdio handle exhaustion; antivirus interfering with redirected console IO.

Related errors


AI-assisted analysis of OdysseusYuan/LKY_OfficeTools@6f9a1bd471 (2026-08-13). Data as JSON: /api/errors/22c2e8de590d3871. Report an issue: GitHub.

Appendix: source

Thrown at LKY_OfficeTools/Common/Com_ServiceOS.cs:305

            internal static bool Create(string serv_name, string serv_runpath, string serv_displayname, string serv_description = null)
            {
                try
                {
                    if (Query.IsCreated(serv_name))
                    {
                        //已经创建服务,直接返回真
                        return true;
                    }
                    else
                    {
                        //未安装,开始安装
                        string cmd_install = $"sc create \"{serv_name}\" binPath=\"{serv_runpath}\" start=auto DisplayName=\"{serv_displayname}\"";
                        var install_result = Com_ExeOS.Run.Cmd(cmd_install);

                        //非空判断,若返回值为空,则为假
                        if (string.IsNullOrEmpty(install_result))
                        {
                            throw new Exception($"创建服务 {serv_name} 时,返回值为空!");
                        }

                        //判断是否安装成功
                        if (install_result.Contains("成功") || install_result.ToLower().Contains("success"))
                        {
                            //描述信息不为空,配置描述信息
                            if (!string.IsNullOrEmpty(serv_description))
                            {
                                Modify.Description(serv_name, serv_description);
                            }

                            //无论修改描述信息是否成功,均返回成功
                            return true;
                        }
                        else
                        {
                            return false;
                        }

View on GitHub (pinned to 6f9a1bd471)