在windows系统中,有时需要在程序中以其他用户身份运行另外的exe程序,需要用
到advapi32.dll中的CreateProcessAsUser函数,在msdn中该函数原型为:
BOOL CreateProcessAsUser(
HANDLE hToken,
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation);关于个参数的具体说明msdn上有详细说明
就不在这里重复了。
需要提出说明的是hToken参数,在使用这个函数的时候,token 需要采用DuplicateTokenEx
函数来复制当前的token否则会出现1349的错误。关于DuplicateTokenEx的具体说明请参阅msdn.
示列代码:
1
using
System;
2
using
System.Collections;
3
using
System.Diagnostics;
4
using
System.Threading;
5
using
Microsoft.Win32;
6
using
System.Text;
7
using
System.Security.Principal;
8
using
ReportManagerControlLibrary;
9
using
System.IO;
10
using
System.Security;
11
using
System.Security.Permissions;
12
using
System.Runtime.InteropServices;
13
namespace
test{
14
15
16
///
<summary>
17
///
Add Windows authorization by Junyi ,Oct.18.2006
18
///
</summary>
19
[SecurityPermission(SecurityAction.Demand,ControlPrincipal
=
true
)]
20
public
class
SchematicGenerator {
21
#region
API calling
22
[DllImport(
"
kernel32.dll
"
)]
23
private
static
extern
bool
GetExitCodeProcess(IntPtr hProcess,
out
uint
24
lpExitCode);
25
26
[DllImport(
"
kernel32
"
, SetLastError
=
true
, ExactSpelling
=
true
)]
27
private
static
extern
Int32 WaitForSingleObject(IntPtr handle, Int32
28
milliseconds);
29
30
[DllImport(
"
kernel32.dll
"
, EntryPoint
=
"
CloseHandle
"
, SetLastError
=
true
,
31
CharSet
=
CharSet.Auto, CallingConvention
=
CallingConvention.StdCall)]
32
private
extern
static
bool
CloseHandle(IntPtr handle);
33
[DllImport(
"
kernel32.dll
"
, SetLastError
=
true
)]
34
private
extern
static
void
ExitProcess(
uint
uExitCode);
35
[DllImport(
"
advapi32.dll
"
, CharSet
=
CharSet.Auto, SetLastError
=
true
)]
36
static
extern
Boolean CreateProcessAsUser(
37
IntPtr hToken,
38
String lpApplicationName,
39
String lpCommandLine,
40
IntPtr lpProcessAttributes,
41
IntPtr lpThreadAttributes,
42
Boolean bInheritHandles,
43
UInt32 dwCreationFlags,
44
IntPtr lpEnvironment,
45
String lpCurrentDirectory,
46
ref
STARTUPINFO lpStartupInfo,
47
out
PROCESS_INFORMATION lpProcessInformation);
48
[DllImport(
"
advapi32.dll
"
, CharSet
=
CharSet.Auto, SetLastError
=
true
)]
49
internal
static
extern
bool
DuplicateTokenEx(IntPtr tokenHandle,
int
50
dwDesiredAccess,
51
ref
SECURITY_ATTRIBUTES lpTokenAttributes,
int
52
SECURITY_IMPERSONATION_LEVEL ,
53
int
TOKEN_TYPE,
ref
IntPtr dupeTokenHandle);
54
[DllImport(
"
kernel32.dll
"
, SetLastError
=
true
)]
//
copy user token
55
public
static
extern
bool
DuplicateHandle(IntPtr hSourceProcessHandle,
56
IntPtr hSourceHandle, IntPtr hTargetProcessHandle,
out
IntPtr
57
58
lpTargetHandle,
59
uint
dwDesiredAccess,
bool
bInheritHandle,
uint
dwOptions);
60
61
[StructLayout(LayoutKind.Sequential)]
62
internal
struct
SECURITY_ATTRIBUTES
63
{
64
internal
int
nLength;
65
internal
int
lpSecurityDescriptor;
66
internal
bool
bInheritHandle;
67
68
}
69
70
[StructLayout(LayoutKind.Sequential)]
71
internal
struct
STARTUPINFO
72
{
73
internal
int
cb;
74
[MarshalAs(UnmanagedType.LPTStr)]
75
internal
string
lpReserved;
76
[MarshalAs(UnmanagedType.LPTStr)]
77
internal
string
lpDesktop;
78
[MarshalAs(UnmanagedType.LPTStr)]
79
internal
string
lpTitle;
80
internal
int
dwX;
81
internal
int
dwY;
82
internal
int
dwXSize;
83
internal
int
dwYSize;
84
internal
int
dwXCountChars;
85
internal
int
dwYCountChars;
86
internal
int
dwFillAttribute;
87
internal
int
dwFlags;
88
internal
short
wShowWindow;
89
internal
short
cbReserved2;
90
internal
IntPtr lpReserved2;
91
internal
IntPtr hStdInput;
92
internal
IntPtr hStdOutput;
93
internal
IntPtr hStdError;
94
}
95
96
[StructLayout(LayoutKind.Sequential)]
97
internal
struct
PROCESS_INFORMATION
98
{
99
internal
IntPtr hProcess;
100
internal
IntPtr hThread;
101
internal
int
dwProcessId;
102
internal
int
dwThreadId;
103
}
104
105
//
SECURITY_IMPERSONATION_LEVEL
106
const
int
SecurityAnonymous
=
0
;
107
const
int
SecurityIdentification
=
1
;
108
const
int
SecurityImpersonation
=
2
;
109
const
int
SecurityDelegation
=
3
;
110
111
//
TOKEN_TYPE
112
const
int
TokenPrimary
=
1
;
113
const
int
TokenImpersonation
=
2
;
114
115
//
dwLogonFlags Specifies the logon option
116
const
int
LOGON_WITH_PROFILE
=
1
;
117
const
int
LOGON_NETCREDENTIALS_ONLY
=
2
;
118
119
//
Access Token constants
120
const
int
TOKEN_ALL_ACCESS
=
0x10000000
;
121
122
//
dwCreationFlags - Specifies how the process is created
123
const
int
DETACHED_PROCESS
=
0x00000008
;
124
const
int
CREATE_NO_WINDOW
=
0x08000000
;
125
const
int
CREATE_SUSPENDED
=
0x00000004
;
126
const
int
CREATE_NEW_CONSOLE
=
0x00000010
;
127
const
int
CREATE_NEW_PROCESS_GROUP
=
0x00000200
;
128
const
int
CREATE_SEPARATE_WOW_VDM
=
0x00000800
;
129
const
int
CREATE_UNICODE_ENVIRONMENT
=
0x00000400
;
130
const
int
CREATE_DEFAULT_ERROR_MODE
=
0x04000000
;
131
132
//
dwCreationFlags parameter controls the new process's priority class
133
const
int
NORMAL_PRIORITY_CLASS
=
0x00000020
;
134
const
int
IDLE_PRIORITY_CLASS
=
0x00000040
;
135
const
int
HIGH_PRIORITY_CLASS
=
0x00000080
;
136
const
int
REALTIME_PRIORITY_CLASS
=
0x00000100
;
137
const
int
BELOW_NORMAL_PRIORITY_CLASS
=
0x00004000
;
138
const
int
ABOVE_NORMAL_PRIORITY_CLASS
=
0x00008000
;
139
//
dwFlags
140
//
This is a bit field that determines whether certain STARTUPINFO
141
//
members are used when the process creates a window.
142
//
Any combination of the following values can be specified:
143
const
int
STARTF_USESHOWWINDOW
=
0x0000000
;
144
const
int
STARTF_USESIZE
=
0x00000002
;
145
const
int
STARTF_USEPOSITION
=
0x00000004
;
146
const
int
STARTF_USECOUNTCHARS
=
0x00000008
;
147
const
int
STARTF_USEFILLATTRIBUTE
=
0x00000010
;
148
const
int
STARTF_FORCEONFEEDBACK
=
0x00000040
;
149
const
int
STARTF_FORCEOFFFEEDBACK
=
0x00000080
;
150
const
int
STARTF_USESTDHANDLES
=
0x00000100
;
151
const
int
STARTF_USEHOTKEY
=
0x00000200
;
152
153
#endregion
154
public
void
Test()
155
{
156
157
{
158
159
try
160
{
161
IntPtr dupeTokenHandle
=
;
162
IntPtr hProcess
=
Process.GetCurrentProcess().Handle;
163
IntPtr _hTargetToken
=
IntPtr.Zero;
164
//
Setting security attributes
165
SECURITY_ATTRIBUTES sa
=
new
SECURITY_ATTRIBUTES();
166
sa.bInheritHandle
=
false
;
167
sa.nLength
=
Marshal.SizeOf(sa);
168
sa.lpSecurityDescriptor
=
0
;
169
170
PROCESS_INFORMATION processInfo
=
new
PROCESS_INFORMATION();
173
//
Setting startupinfo
174
STARTUPINFO startInfo
=
new
STARTUPINFO();
175
startInfo.cb
=
Marshal.SizeOf(startInfo);
176
startInfo.lpDesktop
=
""
;
177
//
Copy Token
178
bool
status
=
DuplicateTokenEx(dupeTokenHandle,
TOKEN_ALL_ACCESS,
ref
sa, SecurityImpersonation, TokenPrimary,
ref
_hTargetToken);
183
if
(
!
status)
184
{
185
int
err1
=
Marshal.GetLastWin32Error();
186
StreamWriter sw
=
new
StreamWriter(
@"
C:\log.log
"
,
true
);
187
sw.WriteLine(
"
TokenHandle:
"
+
err1);
188
}
189
190
//
Create ProcessAsUser
191
bool
ret
=
CreateProcessAsUser(
192
_hTargetToken,
193
exePath,
//
file to execute
194
arguments,
//
command line
195
IntPtr.Zero,
//
pointer to process
196
197
SECURITY_ATTRIBUTES
198
IntPtr.Zero,
//
pointer to thread SECURITY_ATTRIBUTES
199
false
,
//
handles are not inheritable
200
CREATE_NEW_CONSOLE,
//
creation flags
201
IntPtr.Zero,
//
pointer to new environment block
202
folder,
//
name of current directory
203
ref
startInfo,
//
pointer to STARTUPINFO structure
204
out
processInfo
//
receives information about new
205
206
process
207
);
208
if
(
!
ret)
209
{
210
int
err
=
Marshal.GetLastWin32Error();
211
StreamWriter sw
=
new
212
213
StreamWriter(
@"
C:\log.log
"
,
true
);
214
sw.WriteLine(
"
TokenHandle:
"
+
err1);
215
}
216
//
Wait process
217
WaitForSingleObject( processInfo.hProcess,
5
*
60
*
1000
)
218
uint
ec;
219
GetExitCodeProcess(processInfo.hProcess,
out
ec);
220
if
((
int
)ec
!=
0
)
221
{
222
ExitProcess(ec);
223
224
}
225
CloseHandle(processInfo.hProcess);
226
CloseHandle(processInfo.hThread);
227
CloseHandle(dupeTokenHandle);
228
229
230
231
232
}
233
catch
(Exception ex)
234
{
235
236
237
}
238
239
240
241
}
242
}
243
244
}
245
246
247
248
249
250