0

我正在构建一个 Windows 服务。它需要使用当前用户权限运行命令并删除所有存储的与子字符串匹配的凭据 - 例如“MYSTRING”。

我已经在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;
        }
4

1 回答 1

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

于 2017-12-14T07:54:13.357 回答