【发布时间】:2017-12-14 07:34:19
【问题描述】:
我正在构建 Windows 服务。它需要使用当前用户权限运行命令并删除与子字符串匹配的所有存储凭据 - 例如“神秘”。
我已经在 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;
}
【问题讨论】:
-
你为什么在第二个命令中加倍
%? -
不清楚,你想要什么。提供一些 c# 代码,如果它确实是一个 c# 问题。您可能需要 @ 运算符
string mystring = @"String, which doesnt resolve escapesequences, C:\stuff stays C:\stuff"; -
@PetSerAl 是的,我添加了 %%。命令:cmd.exe /K FOR /F "usebackq tokens=1* delims=:" %%i in (
cmdkey /list^|findstr MYSTRING) do cmdkey /delete:%%j -
@FrankM 当然我可以添加 C# 代码。但我觉得,由于命令本身在运行框中不起作用,因此调试 C# 代码毫无意义。请提出建议。
-
Thx :) 您的 tukans cmdline 副本有更多空格,这可能会导致错误:(yours)
tokens = 1 * delims =:vs (tukans)tokens=1* delims=:visual studio 有时会这样做(在粘贴时添加空格)
标签: c# windows for-loop cmd createprocessasuser