PSEXEC - "句柄无效" 在以系统用户身份运行命令时的解决方法

15

这是一个命令,在用户生成的命令提示符中运行良好:

PSEXEC \\xxx.xxx.xxx.xxx -u xxxx -p xxxx -accepteula cmd /c "TYPE C:\Pyxislog\PYXIS01.log|Find/i "%ID%"" >nul

然而,如果我尝试从系统调用的命令提示符中运行此命令,会出现以下情况:
Couldn't access 10.219.149.65:
The handle is invalid.
Connecting to 10.219.149.65...

由于将使用一个以系统用户身份运行的远程软件工具部署,因此它必须作为系统用户运行。这是psexec的限制吗?是的,用户名和密码具有管理员权限。

6个回答

12
经过大量研究,这是一项Windows安全功能,用于阻止系统用户的所有网络访问,包括作为其他用户运行任务。我发现规避这个问题最好的方法是创建一个计划任务,从管理员帐户中运行psexec。

2

Psexec强制使用系统用户帐户,通过添加-s参数。

我们使用psexec在远程计算机上启动一些任务,并将其记录在数据库表中。 当我们不使用-s参数时,用户的名称显示为domain\administrator,但是如果使用-s参数,则显示为“System”

有关无效句柄消息,请参阅:

https://superuser.com/questions/200938/psexec-the-handle-is-invalid


感谢您的回复,但是您可能误解了我的意思。如果我运行完整的批处理文件,该行就可以正常工作,因为我正在使用用户帐户运行批处理文件。但是,如果我尝试将软件包部署到与手动运行成功的同一台机器上,则会失败,因为部署会将批处理文件作为SYSTEM用户运行。我不需要PSEXEC访问远程计算机上的系统帐户,我需要它访问管理员帐户。 - bill
你在psexec登录中使用的是同一个用户账号吗?我猜是的。 - Carlos Landeras
是的,例如我复制粘贴了上面展示的PSEXEC命令(填好了xxxx)到一个CMD窗口中,这个窗口是通过开始>运行>CMD打开的。然后我通过执行psexec -i -s cmd.exe命令来作为SYSTEM用户调用另一个CMD窗口,接着在第二个CMD窗口中粘贴和第一个CMD窗口完全相同的命令,就会重新出现这个错误。 - bill

1

此进程正在使用 NT Authority\SYSTEM 帐户运行,而不是作为用户运行。因此它没有可用的提升令牌。 - bill

0

这可能与此无关,但我发现如果连接断开到机器上,即机器进入睡眠状态,我会遇到“句柄无效”的错误。


0
这里是我使用的代码,按照IT工程师的指示安排任务以管理员身份运行并避免“句柄无效”的问题。
        //Schedule a task that will run the script
        using (TaskService ts = new TaskService())
        {
            TaskDefinition td = ts.NewTask();
            td.RegistrationInfo.Description = "Runs script as admin user";
            td.Triggers.Add(new TimeTrigger(DateTime.Now.AddMinutes(2)));
            td.Actions.Add(new ExecAction(@"C:\...\script.exe"));
            try
            {
                ts.RootFolder.RegisterTaskDefinition(@"Script", td, TaskCreation.CreateOrUpdate, "username", "password", logonType: TaskLogonType.Password);
            }
            catch (UnauthorizedAccessException e)
            {
                Console.WriteLine("Could not register task in task scheduler.");
                Console.WriteLine(e.ToString());
                return;
            }
        }

0

我的代码完美运行:

public static void RunTask(string[] task, string username, string password)
{
    System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(task[1] + ".exe");
    psi.RedirectStandardOutput = true;
    psi.RedirectStandardError = true;
    psi.CreateNoWindow = true;
    psi.UseShellExecute = false;
    string args = String.Format(@"-u {1} -p {2} -accepteula \\{0} " + (task[1] == "psexec" ? "-d -s -i 2 {3}" : "{3}"), task[0], username, password, task[1] == "psservice" ? task[2].TrimStart('"').Insert(task[2].IndexOf(' '), "\"") : task[2]);
    psi.Arguments = args;

    System.Diagnostics.Process prc = System.Diagnostics.Process.Start(psi);
    string output = (prc.StandardError.ReadToEnd() + "\r\n" + prc.StandardOutput.ReadToEnd()).Trim();
    output = output.Substring(output.IndexOf(".com\r\n\r\n") + 8);

    prc.WaitForExit();

    if (!(output.Contains("started on") || output.Contains("killed on") || output.Contains("SERVICE_NAME"))) throw new Exception(output);
}

示例调用:

    RunTask(new string[] { "MACHINE", "psexec", @"""C:\Program Files (x86)\Internet Explorer\iexplore.exe""" }, "USERNAME", "PASSWORD");
    RunTask(new string[] { "MACHINE", "pskill", @"""iexplore.exe""" }, "USERNAME", "PASSWORD");
    RunTask(new string[] { "MACHINE", "psservice", @"""start SOMESERVICE""" }, "USERNAME", "PASSWORD");
    RunTask(new string[] { "MACHINE", "psservice", @"""stop SOMESERVICE""" }, "USERNAME", "PASSWORD");

请确保在您的程序旁边有psexec.exepskill.exepsservice.exe文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接