Windows VistaWindows 2003.NET 3.0设计/图形架构师高级Windows XP.NET 2.0C# 2.0C# 3.0开发Visual StudioWindows.NETC#
使用 C# 编写的服务辅助应用程序将您的应用程序启动到会话 1






4.39/5 (16投票s)
2007年5月13日
1分钟阅读

94952

2403
在本地系统帐户下,使用会话 0 中的服务(C#)将您的应用程序启动到会话 1。
引言
这篇文章与我之前用原生 C++ 编写的文章相同。(使用 Vista 中的服务辅助应用程序从会话 0 启动到会话 1,请参阅 VistaSessions.asp)
Luzius Kalt 给我发来了一份 C# 版本的服务,对于那些希望在 .NET 平台上使用该代码的人来说,这将非常有效。
由于我收到了很多要求将文章发布在 .NET 上的请求,因此我发布了从 Luzius 处收到的代码。
为了表彰他的努力,我将此作为单独的文章发布。
使用代码
应用程序逻辑的核心是服务。这是将辅助应用程序启动到会话 1 的关键。
因此,只有服务是用 C# 重写的。
用 C# 重写的代码使用 PINVOKE 来执行原生 API。
发送消息到服务的自定义消息发送器应用程序,以及将访问注册表中的 HKCU 的代码(请参阅我的文章 VistaSessions.asp)仍然使用原生代码。
我很快会更新这些内容。
以下结构和 API 来自 Win32,已在 C# 中声明
// Structure for the CreateProcessAsuser API
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int Length;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
//Structure for the DuplicateTokenEx API
enum TOKEN_TYPE : int
{
TokenPrimary = 1,
TokenImpersonation = 2
}
//Structure for the SetTokenInformation API
public enum TOKEN_INFORMATION_CLASS : int
{
TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId,
TokenGroupsAndPrivileges,
TokenSessionReference,
TokenSandBoxInert,
TokenAuditPolicy,
TokenOrigin,
MaxTokenInfoClass
// MaxTokenInfoClass should always be the last enum
}
//Structure for CreateProcess API
[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFO
{
public int cb;
public String lpReserved;
public String lpDesktop;
public String lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
//Structure for CreateProcess API
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
//Structure for LookupPriveleges API
[StructLayout(LayoutKind.Sequential)]
internal struct LUID
{
public int LowPart;
public int HighPart;
}//end struct
//For the TOKEN PRIVILEGES STRUCTURE
[StructLayout(LayoutKind.Sequential)]
internal struct LUID_AND_ATRIBUTES
{
public LUID Luid;
public int Attributes;
}//end struct
//Structure for the AdjustTokenPrivileges API
[StructLayout(LayoutKind.Sequential)]
internal struct TOKEN_PRIVILEGES
{
internal int PrivilegeCount;
//LUID_AND_ATRIBUTES
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
internal int[] Privileges;
}
//Defined for Token rights
public const int READ_CONTROL = 0x00020000;
public const int STANDARD_RIGHTS_REQUIRED = 0x000F0000;
public const int STANDARD_RIGHTS_READ = READ_CONTROL;
public const int STANDARD_RIGHTS_WRITE = READ_CONTROL;
public const int STANDARD_RIGHTS_EXECUTE = READ_CONTROL;
public const int STANDARD_RIGHTS_ALL = 0x001F0000;
public const int SPECIFIC_RIGHTS_ALL = 0x0000FFFF;
public const int TOKEN_ASSIGN_PRIMARY = 0x0001;
public const int TOKEN_DUPLICATE = 0x0002;
public const int TOKEN_IMPERSONATE = 0x0004;
public const int TOKEN_QUERY = 0x0008;
public const int TOKEN_QUERY_SOURCE = 0x0010;
public const int TOKEN_ADJUST_PRIVILEGES = 0x0020;
public const int TOKEN_ADJUST_GROUPS = 0x0040;
public const int TOKEN_ADJUST_DEFAULT = 0x0080;
public const int TOKEN_ADJUST_SESSIONID = 0x0100;
public const int TOKEN_ALL_ACCESS_P = (STANDARD_RIGHTS_REQUIRED |
TOKEN_ASSIGN_PRIMARY |
TOKEN_DUPLICATE |
TOKEN_IMPERSONATE |
TOKEN_QUERY |
TOKEN_QUERY_SOURCE |
TOKEN_ADJUST_PRIVILEGES |
TOKEN_ADJUST_GROUPS |
TOKEN_ADJUST_DEFAULT);
public const int TOKEN_ALL_ACCESS = TOKEN_ALL_ACCESS_P |
TOKEN_ADJUST_SESSIONID;
public const int TOKEN_READ = STANDARD_RIGHTS_READ | TOKEN_QUERY;
public const int TOKEN_WRITE = STANDARD_RIGHTS_WRITE |
TOKEN_ADJUST_PRIVILEGES |
TOKEN_ADJUST_GROUPS |
TOKEN_ADJUST_DEFAULT;
public const int TOKEN_EXECUTE = STANDARD_RIGHTS_EXECUTE;
//Defined for Process Rights
public const uint MAXIMUM_ALLOWED = 0x2000000;
public const int CREATE_NEW_PROCESS_GROUP = 0x00000200;
public const int CREATE_UNICODE_ENVIRONMENT = 0x00000400;
public const int IDLE_PRIORITY_CLASS = 0x40;
public const int NORMAL_PRIORITY_CLASS = 0x20;
public const int HIGH_PRIORITY_CLASS = 0x80;
public const int REALTIME_PRIORITY_CLASS = 0x100;
public const int CREATE_NEW_CONSOLE = 0x00000010;
public const string SE_DEBUG_NAME = "SeDebugPrivilege";
public const string SE_RESTORE_NAME = "SeRestorePrivilege";
public const string SE_BACKUP_NAME = "SeBackupPrivilege";
public const int SE_PRIVILEGE_ENABLED = 0x0002;
public const int ERROR_NOT_ALL_ASSIGNED = 1300;
//structure for the Process32First API
[StructLayout(LayoutKind.Sequential)]
private struct PROCESSENTRY32
{
public uint dwSize;
public uint cntUsage;
public uint th32ProcessID;
public IntPtr th32DefaultHeapID;
public uint th32ModuleID;
public uint cntThreads;
public uint th32ParentProcessID;
public int pcPriClassBase;
public uint dwFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szExeFile;
}
其余代码都很简单。您可以参考我之前的文章来了解核心逻辑。您可以自由使用此代码。如有任何疑问,请通过 jaisvar@gmail.com 与我联系。我正在撰写我的第二篇文章,关于 UAC 调整,很快就会发布。