从Windows C#服务运行用户进程cmd.exe

时间:2017-12-14 07:34:20

标签: c# windows for-loop cmd createprocessasuser

我正在构建一个Windows服务。它需要使用当前用户权限运行命令并删除与子字符串匹配的所有存储凭证 - 例如" myString的&#34 ;.

我在CreateProcessAsUser方法中调用了其他模块。但是,调用cmd.exe模块并传递复杂命令似乎很棘手。

我可能缺少一些转义字符或一些额外的命令行参数,导致复杂命令无法成功运行。如果我调用我的服务,我可以看到cmd提示符启动,但它不执行命令。

我确实尝试对其进行故障排除。我直接在命令cmd提示符下测试了它,这有效。

以下是示例:

直接来自cmd提示符:

FOR /F "usebackq tokens=1* delims=: " %i in (`cmdkey /list^|findstr MYSTRING`) do cmdkey /delete:%j

通过run box执行相同的命令失败:

cmd.exe /K FOR /F "usebackq tokens=1* delims=: " %%i in (`cmdkey /list^|findstr MYSTRING`) do cmdkey /delete:%%j

我尝试添加双引号,转义特殊字符,但不知何故它不起作用。以下是这样的例子。

cmd.exe /K "FOR /F ^"usebackq tokens=1* delims=: ^" %%i in (`cmdkey /list^|findstr ADAL`) do cmdkey /delete %%j"

cmd.exe /K "FOR /F ^"usebackq tokens=1* delims^=: ^" %%i in (^`cmdkey /list^|findstr ADAL^`) do cmdkey /delete %%j"

提前感谢您的帮助。

修改

根据tukan的输入,我能够从运行框运行命令。但是,当我在C#代码中尝试相同时,它会在命令提示符中抛出错误。

命令提示符出错(服务创建的进程):

  

tokens = 1 * delims =:"这时出人意料。

以下是C#方法。

public static bool ClearCredsCache()
        {
            var hUserToken = IntPtr.Zero;
            var startInfo = new STARTUPINFO();
            var procInfo = new PROCESS_INFORMATION();
            var pEnv = IntPtr.Zero;
            int iResultOfCreateProcessAsUser;
            //String cmdLine = "cmd.exe \"FOR / F \"usebackq tokens=1* delims=: \" %%i in (`cmdkey / list ^| findstr MYSTRING`) do cmdkey / list %%j\"& pause";
            String cmdLine = "cmd.exe /K FOR /F \"usebackq tokens = 1 * delims =: \" %i in (`cmdkey /list^|findstr MYSTRING`) do cmdkey /delete:%j";
            //String cmdLine = null;
            String appPath = "cmd.exe";
            String workDir = null;
            bool visible = true;

            startInfo.cb = Marshal.SizeOf(typeof(STARTUPINFO));

            try
            {
                if (!GetSessionUserToken(ref hUserToken))
                {
                    throw new CredMgmtException(CredMgmtException.medium, "StartProcessAsCurrentUser: GetSessionUserToken failed.");
                }

                uint dwCreationFlags = CREATE_UNICODE_ENVIRONMENT | (uint)(visible ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW);
                startInfo.wShowWindow = (short)(visible ? SW.SW_SHOW : SW.SW_HIDE);
                startInfo.lpDesktop = null;

                if (!CreateEnvironmentBlock(ref pEnv, hUserToken, false))
                {
                    throw new CredMgmtException(CredMgmtException.medium, "StartProcessAsCurrentUser: CreateEnvironmentBlock failed.");
                }

                if (!CreateProcessAsUser(hUserToken,
                    appPath, // Application Name
                    cmdLine, // Command Line
                    IntPtr.Zero,
                    IntPtr.Zero,
                    false,
                    dwCreationFlags,
                    pEnv,
                    workDir, // Working directory
                    ref startInfo,
                    out procInfo))
                {
                    iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();
                    throw new CredMgmtException(CredMgmtException.medium, "StartProcessAsCurrentUser: CreateProcessAsUser failed.  Error Code -" + iResultOfCreateProcessAsUser);
                }

                iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();
            }
            finally
            {
                CloseHandle(hUserToken);
                if (pEnv != IntPtr.Zero)
                {
                    DestroyEnvironmentBlock(pEnv);
                }
                CloseHandle(procInfo.hThread);
                CloseHandle(procInfo.hProcess);
            }
           //stdOut.
           // CredMgmtUtil.WriteEvent("Startupinfo=" + startInfo.hStdOutput)
            return true;
        }

1 个答案:

答案 0 :(得分:1)

我确实从run box进行了测试,并且在Windows 7 x64上执行良好而没有错误。

cmd.exe /K FOR /F "usebackq tokens=1* delims=: " %i in (`cmdkey /list^|findstr tukan`) do echo "test"

两种方式(cmd.exe& run box)都能正确生成两条回音线。

你有什么窗户?如果你在cmd.exe cmdkey /list^|findstr ADAL中执行了什么?