运行 来自 Windows C# 服务的用户进程 cmd.exe
Running user process cmd.exe from Windows C# services
我正在构建 Windows 服务。它需要 运行 使用当前用户权限的命令,并删除所有存储的与子字符串匹配的凭据 - 例如"MYSTRING"。
我在 CreateProcessAsUser 方法中调用了其他模块,该方法确实有效。但是,调用 cmd.exe 模块并传递复杂的命令似乎很棘手。
我可能遗漏了一些转义字符或一些额外的命令行参数,导致复杂命令无法成功 运行。如果我调用我的服务,我可以看到 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 =: " was unexpected at this time.
下面是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;
}
我确实在 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
)都能正确产生两条回声线。
你有什么windows?如果你在 cmd.exe
中执行只是 cmdkey /list^|findstr ADAL
你会得到什么?
我正在构建 Windows 服务。它需要 运行 使用当前用户权限的命令,并删除所有存储的与子字符串匹配的凭据 - 例如"MYSTRING"。
我在 CreateProcessAsUser 方法中调用了其他模块,该方法确实有效。但是,调用 cmd.exe 模块并传递复杂的命令似乎很棘手。
我可能遗漏了一些转义字符或一些额外的命令行参数,导致复杂命令无法成功 运行。如果我调用我的服务,我可以看到 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 =: " was unexpected at this time.
下面是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;
}
我确实在 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
)都能正确产生两条回声线。
你有什么windows?如果你在 cmd.exe
中执行只是 cmdkey /list^|findstr ADAL
你会得到什么?