我需要编写一个小的服务来在登录屏幕上运行应用程序(带有gui,例如calc.exe).我已经找到了这个问题(和答案):Running a process at the Windows 7 Welcome Screen如果您不了解其工作原理,请阅读代码注释:// grab t...
我需要编写一个小的服务来在登录屏幕上运行应用程序(带有gui,例如calc.exe).
我已经找到了这个问题(和答案):
Running a process at the Windows 7 Welcome Screen
如果您不了解其工作原理,请阅读代码注释:
// grab the winlogon process
Process winLogon = null;
foreach (Process p in Process.GetProcesses())
{
if (p.ProcessName.Contains("winlogon"))
{
winLogon = p;
break;
}
}
// grab the winlogon's token
IntPtr userToken = IntPtr.Zero;
if (!OpenProcessToken(winLogon.Handle, TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE, out userToken))
{
log("ERROR: OpenProcessToken returned false - " + Marshal.GetLastWin32Error());
}
// create a new token
IntPtr newToken = IntPtr.Zero;
SECURITY_ATTRIBUTES tokenAttributes = new SECURITY_ATTRIBUTES();
tokenAttributes.nLength = Marshal.SizeOf(tokenAttributes);
SECURITY_ATTRIBUTES threadAttributes = new SECURITY_ATTRIBUTES();
threadAttributes.nLength = Marshal.SizeOf(threadAttributes);
// duplicate the winlogon token to the new token
if (!DuplicateTokenEx(userToken, 0x10000000, ref tokenAttributes, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
TOKEN_TYPE.TokenImpersonation, out newToken))
{
log("ERROR: DuplicateTokenEx returned false - " + Marshal.GetLastWin32Error());
}
TOKEN_PRIVILEGES tokPrivs = new TOKEN_PRIVILEGES();
tokPrivs.PrivilegeCount = 1;
LUID seDebugNameValue = new LUID();
if (!LookupPrivilegeValue(null, SE_DEBUG_NAME, out seDebugNameValue))
{
log("ERROR: LookupPrivilegeValue returned false - " + Marshal.GetLastWin32Error());
}
tokPrivs.Privileges = new LUID_AND_ATTRIBUTES[1];
tokPrivs.Privileges[0].Luid = seDebugNameValue;
tokPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// escalate the new token's privileges
if (!AdjustTokenPrivileges(newToken, false, ref tokPrivs, 0, IntPtr.Zero, IntPtr.Zero))
{
log("ERROR: AdjustTokenPrivileges returned false - " + Marshal.GetLastWin32Error());
}
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
STARTUPINFO si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = "Winsta0\\Winlogon";
// start the process using the new token
if (!CreateProcessAsUser(newToken, "calc.exe", null, ref tokenAttributes, ref threadAttributes,
true, (uint)CreateProcessFlags.CREATE_NEW_CONSOLE | (uint)CreateProcessFlags.INHERIT_CALLER_PRIORITY, IntPtr.Zero,
"C:\\Windows\\System32", ref si, out pi))
{
log("ERROR: CreateProcessAsUser returned false - " + Marshal.GetLastWin32Error());
}
Process _p = Process.GetProcessById(pi.dwProcessId);
if (_p != null)
{
log("Process " + _p.Id + " Name " + _p.ProcessName);
}
else
{
log("Process not found");
}
它适用于Windows7.在XP中,我在调用CreateProcessAsUser时收到错误1349 ERROR_BAD_TOKEN_TYPE(MSDN:令牌的类型不适合尝试使用.).
如何在Windows XP中实现这一点?它不一定是上面的代码,但应作为服务使用(具有系统帐户?).
谢谢你的支持
助焊剂
解决方法:
这绝对与特权问题有关(Windows Vista和7在安全性方面有显着变化).与其尝试获取winlogon.exe的令牌并模拟它,不如尝试通过WTSQueryUserToken获取用户令牌:
WTSQueryUserToken (WTSGetActiveConsoleSessionId(), out userToken);
用上面的语句替换用于获取令牌的OpenProcessToken行.
您的新代码应如下所示:
// if (!OpenProcessToken(winLogon.Handle, TOKEN_QUERY | TOKEN_IMPERSONATE | //TOKEN_DUPLICATE, out userToken))
// {
// log("ERROR: OpenProcessToken returned false - " + //Marshal.GetLastWin32Error());
// }
WTSQueryUserToken (WTSGetActiveConsoleSessionId(), out userToken);
做你的DLL导入是这样的:
[DllImport("Kernel32.dll", SetLastError = true)]
[return:MarshalAs(UnmanagedType.U4)]
public static extern int WTSGetActiveConsoleSessionId ( );
您只需要用此代码替换我注释掉的部分.
本文标题为:c#-在Windows XP登录屏幕(.NET / Pinvoke)上运行进程(WITH GUI)
基础教程推荐
- C# 反射与dynamic最佳组合示例代码 2022-11-10
- C#中Timer实现Tick使用精度的问题 2023-06-28
- C#中单问号(?)和双问号(??)的用法整理 2023-06-09
- unity实现物体延时出现 2023-04-10
- Unity平台模拟自动挡驾驶汽车 2023-03-09
- 浅谈C#六大设计原则 2023-03-03
- c# – SQLBulkCopy不复制主键 2023-11-24
- 基于C#模拟实现回合制游戏 2023-05-12
- C#程序终极调试实现windbg的时间旅行 2023-06-09
- 浅谈C#在网络波动时防重复提交的方法 2023-01-22