Win7以“管理员身份运行”的进程,如何启动另一个“标准权限”的进程?

舉杯邀明月 2017-02-05 10:22:15
加精
主要目的,是需要“降权启动另一进程”,并且需要兼容 32位和64位系统。

百度,查看了很多网页,没有一个有效的解决办法。

主要的参考资料:
http://www.cnblogs.com/zhanglinfan/articles/2321807.html
我是用VB写程序的,最初是“87”错误,分析了老半天,终于解决这个。
目前是 “1299”错误, 我已经没法解决了,根本找不出“原因”。
出错的地方是: SetTokenInformation( )  调用,操作失败。


另外还有一个“从explorer.exe进程复制令牌句柄”的代码(现在找不出哪个网页),
开始“以管理员身份运行”后,老是CreateProcessAsUser( ) 失败,而直接运行程序,却可以启动新进程。
也是折腾了很久,终于“不失败”了。可惜没效果,当“以管理员身份运行”启动,新进程也是管理员权限的。

再有一个,就是这个帖子 6楼代码:http://bbs.csdn.net/topics/360158573
这个“效果不明确”:
1. 我用它启动 cmd.exe,CreateProcessAsUser() 的返回值是1,应该是“成功”的,
  但是,没有看到窗口,任务管理器的“进程”中也找不到cmd.exe的进程。
2. 用它启动“记事本”,窗口出来了,再通过它的“打开文件”对话框,
  去启动我的一个“要求管理员权限运行”的程序,启动时没有“UAC”弹窗(程序图标上也没有那个“小盾牌”),
    这说明“记事本”进程似乎是“有管理员权限”的;
    然而,我的程序启动后,却显示的是“没有管理员权限”,这岂不是与“前一现象”相矛盾?

不知道有没有哪位大神能解决“降权限启动”的问题?

再说一下我的需求:
1. 我的是32位程序,启动时是会申请“管理员身份运行”权限的。
2. 这个程序运行后,会启动另一进程。需要新进程是“普通权限”,这个是最关键的问题所在。
3. 最佳的效果是: 能够以当前登录用户的“标准权限”来启动。
   也就是:如果当前登录用户是“标准账户(受限用户)”,那么新进程就是“标准账户权限”;
    如果当前登录用户是“管理员”(不是“系统”的管理员),那么新进程就是“普通管理员权限”,也就是“未提权”状态;
    如果是用“系统内置管理员Admin”登录的,那么新进程就是“已提权的管理员权限”。
4. 需要32位/64位兼容(Windows Vista及更高版本系统),我的是32位程序。
...全文
9957 156 打赏 收藏 转发到动态 举报
写回复
用AI写文章
156 条回复
切换为时间正序
请发表友善的回复…
发表回复
舉杯邀明月 2019-04-04
  • 打赏
  • 举报
回复
引用 157 楼 fencerking 的回复:
149楼的方法好是好。只是这样得到的pid不是真正的pid,我需要等待被调用程序退出……


哦,对了,我忽略了一个问题……
按149楼的方法,你确实得不到“需要的PID”了。 
你这种需求,是无法用上那个方法了。

不过我的还好,在“当时”的需要,只管把“新进程”按要求的权限启动就了事,别的不用管。

你真要用API实现,就好好“按要求”进行操作,调用API。
110楼的方案,完全没问题的。
舉杯邀明月 2019-04-04
  • 打赏
  • 举报
回复
引用 157 楼 fencerking 的回复:
149楼的方法好是好。只是这样得到的pid不是真正的pid,我需要等待被调用程序退出……

哦,你需要新进程的pid的话,用Shell也许有点问题。

但我刚才在立即窗口中试了一下,返回值还是正确的呀。
fencerking 2019-04-04
  • 打赏
  • 举报
回复
149楼的方法好是好。只是这样得到的pid不是真正的pid,我需要等待被调用程序退出……
fencerking 2019-04-04
  • 打赏
  • 举报
回复
对对,我就是“直接翻译”110的代码,可能没理解,不专业,我也没以为啥,写这个只是平时用到的软件工具调用有这样的需要。不是专业程序员,见笑见笑。
舉杯邀明月 2019-04-03
  • 打赏
  • 举报
回复
引用 154 楼 fencerking 的回复:
[quote=引用 152 楼 舉杯邀明月 的回复:]
[quote=引用 151 楼 fencerking 的回复:]
来挖坟了。也同样遇到了这个问题,用110楼的c++代码改为vb6代码,怎么都通不过。报267错误。


不知道你说的错误代码“267”是10进制值,还是16进制值。
但无论是哪种值,这个“错误代码”似乎跟110楼的代码没关系吧!


我当时改为VB6代码,是正常通过了的,我在118楼有相关说明。
你改的代码会“报错”,也许是你没有“正确翻译”或者传递的参数不正确。

如果你是想“以当前用户的‘标准权限’启动一个新进程”,不妨用149楼的方法吧。
最终效果是一样的,而已也不需要“改变项目架构”。

[/quote]
查了错误代码,是‘目录名无效’,我也怀疑是参数问题,但是基本上各种参数形式都试过了。还是报错。c++代码改为vb6代码,应该改的没问题。 149楼的方法应该是用的c#或者是vb.net。我用的vb6……没装vb.net,汗。
Public Function getTokenbyName(strProcessName As String) As Long

Dim PsSnap As Long
Dim PE32 As PROCESSENTRY32
Dim pHandl As Long
Dim Ltoken As Long
Dim NToken As Long
Dim PsName As String
Dim Sa As SECURITY_ATTRIBUTES
Dim i As Integer
PsSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
If PsSnap = INVALID_HANDLE_VALUE Then getTokenbyName = -1&
PE32.dwSize = Len(PE32)
If Process32First(PsSnap, PE32) Then
Do
i = InStr(1, PE32.szExeFile, Chr(0))
PsName = LCase(Left(PE32.szExeFile, i - 1))
If PsName = LCase(strProcessName) Then
Debug.Print "the input ps name : " & PsName
pHandl = OpenProcess(PROCESS_QUERY_INFORMATION, False, PE32.th32ProcessID)
' pHandl = OpenProcess(PROCESS_ALL_ACCESS, True, PE32.th32ProcessID)
Debug.Print "the explorer id : " & PE32.th32ProcessID
' Debug.Print "the explorer name : " & PE32.szExeFile
If pHandl <> 0 Then
Dim re As Boolean
re = OpenProcessToken(pHandl, TOKEN_DUPLICATE, Ltoken)
' re = OpenProcessToken(pHandl, TOKEN_ALL_ACCESS, Ltoken)
Debug.Print "open processtoken re>>" & re & " return token >>" & Ltoken
Debug.Print "open processtoken errcode: " & Err.LastDllError
If re Then
NToken = vbNull
re = DuplicateTokenEx(Ltoken, TOKEN_ALL_ACCESS, Sa, SecurityImpersonation, TokenPrimary, NToken)

Debug.Print "duplicatetoken re>> " & re & " new token>> " & NToken
Debug.Print "duplicate operation errcode: " & Err.LastDllError
CloseHandle Ltoken
End If
Exit Do
CloseHandle pHandl
End If

End If
Loop While (Process32Next(PsSnap, PE32))
getTokenbyName = IIf(re, NToken, -1&)
Else
getTokenbyName = -1&
CloseHandle PsSnap
End If
End Function



Public Function StartPswithToken(ByVal PsName As String) As Boolean
Dim strUserName As String
Dim UserNameLen As Long
GetUserNameW strUserName, UserNameLen
Dim hToken As Long
hToken = getTokenbyName("Explorer.exe")

Debug.Print "return new token is " & hToken
Dim PsInfo As PROCESS_INFORMATION
ZeroMemory PsInfo, Len(PsInfo)
Dim si As STARTUPINFO
ZeroMemory si, Len(si)
si.cb = Len(si)
si.wShowWindow = SW_SHOW
si.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW
' si.lpDesktop = 0

Dim sEnv As Variant

If CreateEnvironmentBlock(sEnv, hToken, 0) Then sEnv = vbNullString

Dim Cdir As String * MAX_PATH
GetCurrentDirectoryW Len(Cdir), Cdir

Dim dwCreationFlag As Long
dwCreationFlag = NORMAL_PRIORITY_CLASS Or CREATE_UNICODE_ENVIRONMENT Or CREATE_NEW_CONSOLE
Dim RetV As Long
RetV = CreateProcessWithTokenW(hToken, LOGON_WITH_PROFILE, "", StrPtr(PsName), CREATE_DEFAULT_ERROR_MODE, sEnv, "", si, PsInfo)
' RetV = CreateProcessWithTokenW(hToken, LOGON_WITH_PROFILE, StrPtr(PsName), "", dwCreationFlag, sEnv, Cdir, si, PsInfo)

If RetV = 0 Then MsgBox "lasterror: " & Err.LastDllError

CloseHandle PsInfo.hProcess
CloseHandle PsInfo.hThread
StartPswithToken = RetV
End Function

这是代码,谁给看看?

[/quote]
你这代码…………你理解了110楼的方法吗 ???

先别说你的API声明是否与代码匹配(你没贴出来,不知道是引用的TLB,还是写的Declare),
就说点“明显”的问题:
第54行到第56行,你的不是“做无用功”? (在后面用不到;若是要用,你又无法正确获取信息)
第72行、第80行,用到的sEnv参数,函数原型肯定是“xx指针”,
  而你在第70行的变量声明,竟然是“ Variant”类型…… 
你真以为“void”跟VB6中的 Variant类型 就是匹配的吗???

你的代码,我也确实只是“看看”而已,没进行测试,是否还有其它问题,就不说了。


另外,149楼的方法,你没理解到他的“核心思想”吧!
你说他的“代码可能是C#(或 VB.NET)”,这点倒是没错,
 但这个方法,在VB6中不就是一句 Shell 的事吗……超简单的。
fencerking 2019-04-02
  • 打赏
  • 举报
回复
引用 152 楼 舉杯邀明月 的回复:
[quote=引用 151 楼 fencerking 的回复:]
来挖坟了。也同样遇到了这个问题,用110楼的c++代码改为vb6代码,怎么都通不过。报267错误。


不知道你说的错误代码“267”是10进制值,还是16进制值。
但无论是哪种值,这个“错误代码”似乎跟110楼的代码没关系吧!


我当时改为VB6代码,是正常通过了的,我在118楼有相关说明。
你改的代码会“报错”,也许是你没有“正确翻译”或者传递的参数不正确。

如果你是想“以当前用户的‘标准权限’启动一个新进程”,不妨用149楼的方法吧。
最终效果是一样的,而已也不需要“改变项目架构”。

[/quote]
查了错误代码,是‘目录名无效’,我也怀疑是参数问题,但是基本上各种参数形式都试过了。还是报错。c++代码改为vb6代码,应该改的没问题。 149楼的方法应该是用的c#或者是vb.net。我用的vb6……没装vb.net,汗。
Public Function getTokenbyName(strProcessName As String) As Long

Dim PsSnap As Long
Dim PE32 As PROCESSENTRY32
Dim pHandl As Long
Dim Ltoken As Long
Dim NToken As Long
Dim PsName As String
Dim Sa As SECURITY_ATTRIBUTES
Dim i As Integer
PsSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
If PsSnap = INVALID_HANDLE_VALUE Then getTokenbyName = -1&
PE32.dwSize = Len(PE32)
If Process32First(PsSnap, PE32) Then
Do
i = InStr(1, PE32.szExeFile, Chr(0))
PsName = LCase(Left(PE32.szExeFile, i - 1))
If PsName = LCase(strProcessName) Then
Debug.Print "the input ps name : " & PsName
pHandl = OpenProcess(PROCESS_QUERY_INFORMATION, False, PE32.th32ProcessID)
' pHandl = OpenProcess(PROCESS_ALL_ACCESS, True, PE32.th32ProcessID)
Debug.Print "the explorer id : " & PE32.th32ProcessID
' Debug.Print "the explorer name : " & PE32.szExeFile
If pHandl <> 0 Then
Dim re As Boolean
re = OpenProcessToken(pHandl, TOKEN_DUPLICATE, Ltoken)
' re = OpenProcessToken(pHandl, TOKEN_ALL_ACCESS, Ltoken)
Debug.Print "open processtoken re>>" & re & " return token >>" & Ltoken
Debug.Print "open processtoken errcode: " & Err.LastDllError
If re Then
NToken = vbNull
re = DuplicateTokenEx(Ltoken, TOKEN_ALL_ACCESS, Sa, SecurityImpersonation, TokenPrimary, NToken)

Debug.Print "duplicatetoken re>> " & re & " new token>> " & NToken
Debug.Print "duplicate operation errcode: " & Err.LastDllError
CloseHandle Ltoken
End If
Exit Do
CloseHandle pHandl
End If

End If
Loop While (Process32Next(PsSnap, PE32))
getTokenbyName = IIf(re, NToken, -1&)
Else
getTokenbyName = -1&
CloseHandle PsSnap
End If
End Function



Public Function StartPswithToken(ByVal PsName As String) As Boolean
Dim strUserName As String
Dim UserNameLen As Long
GetUserNameW strUserName, UserNameLen
Dim hToken As Long
hToken = getTokenbyName("Explorer.exe")

Debug.Print "return new token is " & hToken
Dim PsInfo As PROCESS_INFORMATION
ZeroMemory PsInfo, Len(PsInfo)
Dim si As STARTUPINFO
ZeroMemory si, Len(si)
si.cb = Len(si)
si.wShowWindow = SW_SHOW
si.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW
' si.lpDesktop = 0

Dim sEnv As Variant

If CreateEnvironmentBlock(sEnv, hToken, 0) Then sEnv = vbNullString

Dim Cdir As String * MAX_PATH
GetCurrentDirectoryW Len(Cdir), Cdir

Dim dwCreationFlag As Long
dwCreationFlag = NORMAL_PRIORITY_CLASS Or CREATE_UNICODE_ENVIRONMENT Or CREATE_NEW_CONSOLE
Dim RetV As Long
RetV = CreateProcessWithTokenW(hToken, LOGON_WITH_PROFILE, "", StrPtr(PsName), CREATE_DEFAULT_ERROR_MODE, sEnv, "", si, PsInfo)
' RetV = CreateProcessWithTokenW(hToken, LOGON_WITH_PROFILE, StrPtr(PsName), "", dwCreationFlag, sEnv, Cdir, si, PsInfo)

If RetV = 0 Then MsgBox "lasterror: " & Err.LastDllError

CloseHandle PsInfo.hProcess
CloseHandle PsInfo.hThread
StartPswithToken = RetV
End Function

这是代码,谁给看看?

-小蚊子- 2019-03-27
  • 打赏
  • 举报
回复
引用 150 楼 舉杯邀明月 的回复:
[quote=引用 149 楼 -小蚊子- 的回复:]
System.Diagnostics.Process.Start("Explorer.exe", @"C:\***.exe");
试试这个。。。我发现有用!


你还真够聪明啊!

刚才我简单的测试了一下,确实“最终效果”能够达到。
不过此贴已经结贴很久了,现在也只能对你说声“谢谢”了。[/quote]
我也是遇到同样的问题,你们的帖子我一步步都看了,没完全懂,大概了解了思路,要谢谢你们我才能完工啊,哈哈
舉杯邀明月 2019-03-27
  • 打赏
  • 举报
回复
引用 151 楼 fencerking 的回复:
来挖坟了。也同样遇到了这个问题,用110楼的c++代码改为vb6代码,怎么都通不过。报267错误。


不知道你说的错误代码“267”是10进制值,还是16进制值。
但无论是哪种值,这个“错误代码”似乎跟110楼的代码没关系吧!


我当时改为VB6代码,是正常通过了的,我在118楼有相关说明。
你改的代码会“报错”,也许是你没有“正确翻译”或者传递的参数不正确。

如果你是想“以当前用户的‘标准权限’启动一个新进程”,不妨用149楼的方法吧。
最终效果是一样的,而已也不需要“改变项目架构”。

fencerking 2019-03-27
  • 打赏
  • 举报
回复
来挖坟了。也同样遇到了这个问题,用110楼的c++代码改为vb6代码,怎么都通不过。报267错误。
舉杯邀明月 2019-03-27
  • 打赏
  • 举报
回复
引用 149 楼 -小蚊子- 的回复:
System.Diagnostics.Process.Start("Explorer.exe", @"C:\***.exe");
试试这个。。。我发现有用!


你还真够聪明啊!

刚才我简单的测试了一下,确实“最终效果”能够达到。
不过此贴已经结贴很久了,现在也只能对你说声“谢谢”了。
-小蚊子- 2019-03-27
  • 打赏
  • 举报
回复
System.Diagnostics.Process.Start("Explorer.exe", @"C:\***.exe");
试试这个。。。我发现有用!
慧眼识狗熊 2017-11-03
  • 打赏
  • 举报
回复
权限相关,标记下以防以后找不到了。
aogsir 2017-06-17
  • 打赏
  • 举报
回复
引用 20 楼 Chen8013 的回复:
[quote=引用 19 楼 zhao4zhong1 的回复:] 通读MSDN中权限相关章节。
我看你还是纸上谈兵的时候比较多 ………… 你可以歇菜了  [/quote] 那个赵4XX,就是个神棍,天天在CSDN祸害人。他懂不懂的,都要乱贴一大堆。有时贴TM一大堆的英文COPY文章,牛头不对马嘴!!日XX先人
尿性死啦 2017-04-12
  • 打赏
  • 举报
回复
虽然看不懂,帮你顶下
qq_38250166 2017-04-10
  • 打赏
  • 举报
回复
不错不错厉害了,需要百度一下或者去网盘找找参考下
舉杯邀明月 2017-04-10
  • 打赏
  • 举报
回复
引用 143 楼 PctGL 的回复:
正好发现存了这么一个代码,也没楼主有兴趣可以试试,我没试过

Option Explicit

'  . . . . . . . . . .

'
这段代码,我肯定没兴趣试了啊………… 用到了“LogonUser( )”,通用性不太好。 “用户名”倒是好办,可是“用户密码”,你难道让使用程序的人每次去输一下?
PctGL 2017-04-09
  • 打赏
  • 举报
回复
正好发现存了这么一个代码,也没楼主有兴趣可以试试,我没试过


Option Explicit

Private Const CREATE_DEFAULT_ERROR_MODE = &H4000000

Private Const LOGON_WITH_PROFILE = &H1
Private Const LOGON_NETCREDENTIALS_ONLY = &H2

Private Const LOGON32_LOGON_INTERACTIVE = 2
Private Const LOGON32_PROVIDER_DEFAULT = 0
   
Private Type STARTUPINFO
    cb As Long
    lpReserved As Long ' !!! must be Long for Unicode string
    lpDesktop As Long  ' !!! must be Long for Unicode string
    lpTitle As Long    ' !!! must be Long for Unicode string
    dwX As Long
    dwY As Long
    dwXSize As Long
    dwYSize As Long
    dwXCountChars As Long
    dwYCountChars As Long
    dwFillAttribute As Long
    dwFlags As Long
    wShowWindow As Integer
    cbReserved2 As Integer
    lpReserved2 As Long
    hStdInput As Long
    hStdOutput As Long
    hStdError As Long
End Type

Private Type PROCESS_INFORMATION
    hProcess As Long
    hThread As Long
    dwProcessId As Long
    dwThreadId As Long
End Type

'  LogonUser() requires that the caller has the following permission
'  Permission                        Display Name
'  --------------------------------------------------------------------
'  SE_TCB_NAME                      Act as part of the operating system

'  CreateProcessAsUser() requires that the caller has the following permissions
'  Permission                        Display Name
'  ---------------------------------------------------------------
'  SE_ASSIGNPRIMARYTOKEN_NAME       Replace a process level token
'  SE_INCREASE_QUOTA_NAME           Increase quotas
  
Private Declare Function LogonUser Lib "advapi32.dll" Alias _
        "LogonUserA" _
        (ByVal lpszUsername As String, _
        ByVal lpszDomain As String, _
        ByVal lpszPassword As String, _
        ByVal dwLogonType As Long, _
        ByVal dwLogonProvider As Long, _
        phToken As Long) As Long

Private Declare Function CreateProcessAsUser Lib "advapi32.dll" _
        Alias "CreateProcessAsUserA" _
        (ByVal hToken As Long, _
        ByVal lpApplicationName As Long, _
        ByVal lpCommandLine As String, _
        ByVal lpProcessAttributes As Long, _
        ByVal lpThreadAttributes As Long, _
        ByVal bInheritHandles As Long, _
        ByVal dwCreationFlags As Long, _
        ByVal lpEnvironment As Long, _
        ByVal lpCurrentDirectory As String, _
        lpStartupInfo As STARTUPINFO, _
        lpProcessInformation As PROCESS_INFORMATION) As Long

' CreateProcessWithLogonW API is available only on Windows 2000 and later.
Private Declare Function CreateProcessWithLogonW Lib "advapi32.dll" _
        (ByVal lpUsername As String, _
        ByVal lpDomain As String, _
        ByVal lpPassword As String, _
        ByVal dwLogonFlags As Long, _
        ByVal lpApplicationName As Long, _
        ByVal lpCommandLine As String, _
        ByVal dwCreationFlags As Long, _
        ByVal lpEnvironment As Long, _
        ByVal lpCurrentDirectory As String, _
        ByRef lpStartupInfo As STARTUPINFO, _
        ByRef lpProcessInformation As PROCESS_INFORMATION) As Long
      
Private Declare Function CloseHandle Lib "kernel32.dll" _
        (ByVal hObject As Long) As Long
                             
Private Declare Function SetErrorMode Lib "kernel32.dll" _
        (ByVal uMode As Long) As Long
        
Private Type OSVERSIONINFO
    dwOSVersionInfoSize As Long
    dwMajorVersion As Long
    dwMinorVersion As Long
    dwBuildNumber As Long
    dwPlatformId As Long
    szCSDVersion As String * 128
End Type
                             
' Version Checking APIs
Private Declare Function GetVersionExA Lib "kernel32.dll" _
    (lpVersionInformation As OSVERSIONINFO) As Integer

Private Const VER_PLATFORM_WIN32_NT = &H2

'********************************************************************

'                   RunAsUser for Windows 2000 and Later
'********************************************************************
Public Function W2KRunAsUser(ByVal UserName As String, _
        ByVal Password As String, _
        ByVal DomainName As String, _
        ByVal CommandLine As String, _
        ByVal CurrentDirectory As String) As Long

    Dim si As STARTUPINFO
    Dim pi As PROCESS_INFORMATION
    
    Dim wUser As String
    Dim wDomain As String
    Dim wPassword As String
    Dim wCommandLine As String
    Dim wCurrentDir As String
    
    Dim Result As Long
    
    si.cb = Len(si)
        
    wUser = StrConv(UserName + Chr$(0), vbUnicode)
    wDomain = StrConv(DomainName + Chr$(0), vbUnicode)
    wPassword = StrConv(Password + Chr$(0), vbUnicode)
    wCommandLine = StrConv(CommandLine + Chr$(0), vbUnicode)
    wCurrentDir = StrConv(CurrentDirectory + Chr$(0), vbUnicode)
    
    Result = CreateProcessWithLogonW(wUser, wDomain, wPassword, _
          LOGON_WITH_PROFILE, 0&, wCommandLine, _
          CREATE_DEFAULT_ERROR_MODE, 0&, wCurrentDir, si, pi)
    ' CreateProcessWithLogonW() does not
    If Result <> 0 Then
        CloseHandle pi.hThread
        CloseHandle pi.hProcess
        W2KRunAsUser = 0
    Else
        W2KRunAsUser = Err.LastDllError
        MsgBox "CreateProcessWithLogonW() failed with error " & Err.LastDllError, vbExclamation
    End If

End Function

'********************************************************************
'                   RunAsUser for Windows NT 4.0
'********************************************************************
Public Function NT4RunAsUser(ByVal UserName As String, _
                ByVal Password As String, _
                ByVal DomainName As String, _
                ByVal CommandLine As String, _
                ByVal CurrentDirectory As String) As Long
Dim Result As Long
Dim hToken As Long
Dim si As STARTUPINFO
Dim pi As PROCESS_INFORMATION

    Result = LogonUser(UserName, DomainName, Password, LOGON32_LOGON_INTERACTIVE, _
                       LOGON32_PROVIDER_DEFAULT, hToken)
    If Result = 0 Then
        NT4RunAsUser = Err.LastDllError
        ' LogonUser will fail with 1314 error code, if the user account associated
        ' with the calling security context does not have
        ' "Act as part of the operating system" permission
        MsgBox "LogonUser() failed with error " & Err.LastDllError, vbExclamation
        Exit Function
    End If
    
    si.cb = Len(si)
    Result = CreateProcessAsUser(hToken, 0&, CommandLine, 0&, 0&, False, _
                CREATE_DEFAULT_ERROR_MODE, _
                0&, CurrentDirectory, si, pi)
    If Result = 0 Then
        NT4RunAsUser = Err.LastDllError
        ' CreateProcessAsUser will fail with 1314 error code, if the user
        ' account associated with the calling security context does not have
        ' the following two permissions
        ' "Replace a process level token"
        ' "Increase Quotoas"
        MsgBox "CreateProcessAsUser() failed with error " & Err.LastDllError, vbExclamation
        CloseHandle hToken
        Exit Function
    End If
    
    CloseHandle hToken
    CloseHandle pi.hThread
    CloseHandle pi.hProcess
    NT4RunAsUser = 0

End Function

Public Function RunAsUser(ByVal UserName As String, _
                ByVal Password As String, _
                ByVal DomainName As String, _
                ByVal CommandLine As String, _
                ByVal CurrentDirectory As String) As Long

    Dim w2kOrAbove As Boolean
    Dim osinfo As OSVERSIONINFO
    Dim Result As Long
    Dim uErrorMode As Long
    
    ' Determine if system is Windows 2000 or later
    osinfo.dwOSVersionInfoSize = Len(osinfo)
    osinfo.szCSDVersion = Space$(128)
    GetVersionExA osinfo
    w2kOrAbove = _
        (osinfo.dwPlatformId = VER_PLATFORM_WIN32_NT And _
         osinfo.dwMajorVersion >= 5)
    If (w2kOrAbove) Then
        Result = W2KRunAsUser(UserName, Password, DomainName, _
                    CommandLine, CurrentDirectory)
    Else
        Result = NT4RunAsUser(UserName, Password, DomainName, _
                    CommandLine, CurrentDirectory)
    End If
    RunAsUser = Result
End Function
            



舉杯邀明月 2017-03-31
  • 打赏
  • 举报
回复
这个帖子还有人来灌水…………
引用 123 楼 horris 的回复:
知道为什么说“上善若水”吗?因为水遇到阻挡能绕过去而不是硬顶。保持简单总是有好处的。一家之谈。。。
逃避问题,谁不会??? 相同的话,反复说没有意义。 请看上面,我在109楼的回复。
cdcjk 2017-03-30
  • 打赏
  • 举报
回复
666666666666666
m0_38074585 2017-03-26
  • 打赏
  • 举报
回复
学习了,感谢分销
加载更多回复(136)

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧