该CreateProcessAsUser函数创建一个新的进程及其主线程。新进程然后执行指定的可执行文件。该CreateProcessAsUser功能类似
的CreateProcess
函数,除了新进程运行在由
hToken
参数表示的用户的安全上下文中。默认情况下,新进程是非交互式的,即它运行在不可见且无法接收用户输入的桌面上。此外,默认情况下,新进程继承调用进程的环境,而不是与指定用户关联的环境。
BOOL CreateProcessAsUser(
HANDLE
hToken
,
|
// 处理代表登录用户的令牌
|
LPCTSTR
lpApplicationName
,
|
// 指向可执行模块名称的指针
|
LPTSTR
lpCommandLine
,
|
// 指向命令行字符串的指针
|
LPSECURITY_ATTRIBUTES
lpProcessAttributes
,
|
// 指向进程安全属性的指针
|
LPSECURITY_ATTRIBUTES
lpThreadAttributes
,
|
// 指向线程安全属性的指针
|
BOOL
bInheritHandles
,
|
// 新进程继承句柄
|
DWORD
dwCreationFlags
,
|
// 创建标志
|
LPVOID
lpEnvironment
,
|
// 指向新环境块的指针
|
LPCTSTR
lpCurrentDirectory
,
|
// 指向当前目录名的指针
|
LPSTARTUPINFO
lpStartupInfo
,
|
// 指向 STARTUPINFO 的指针
|
LPPROCESS_INFORMATION
lpProcessInformation
|
// 指向 PROCESS_INFORMATION 的指针
|
);
|
|
hToken
处理代表用户的主要
hToken
。由
hToken
表示的用户必须具有对
lpApplicationName
或
lpCommandLine
参数指定的应用程序的读取和执行访问权限。
如果您的进程具有 SE_TCB_NAME 权限,它可以调用
LogonUser
函数来获取代表指定用户的主要
hToken
。
或者,您可以调用
DuplicateTokenEx
函数将模拟
hToken
转换为主要
hToken
。这允许模拟客户端的服务器应用程序创建具有客户端安全上下文的进程。
的的其它参数
CreateProcessAsUser
函数表现就像的类似参数
的CreateProcess
功能。
指向一个以空字符结尾的字符串,指定要执行的模块的完整路径和文件名。如果指定了部分名称,则默认使用当前驱动器和当前目录。如果此参数为 NULL,则模块名称必须是
lpCommandLine
字符串中的第一个以空格分隔的标记。指定的模块可以是基于 Win32 的应用程序,也可以是其他类型的模块(例如,MS-DOS 或 OS/2),前提是本地计算机上有适当的子系统。
lp命令行
指向一个以空字符结尾的字符串,指定要执行的应用程序的命令行。如果此参数为 NULL,则
lpApplicationName
字符串用作命令行。如果
lpApplicationName
和
lpCommandLine
都不为 NULL,则
lpApplicationName
指定要执行的模块,
lpCommandLine
用作命令行。新进程可以使用
GetCommandLine
检索整个命令行;或 C 运行时进程可以使用
argc
/
argv
机制。
如果
lpApplicationName
为 NULL,则命令行的第一个以空格分隔的标记指定模块名称。如果文件名不包含扩展名,则假定为 .EXE。如果文件名以句点 (.) 结尾且没有扩展名,或者文件名包含路径,则不会附加 .EXE。如果文件名不包含目录路径,Windows 将按以下顺序搜索可执行文件:
-
应用程序加载的目录。
-
当前目录。
-
32 位 Windows 系统目录。使用
GetSystemDirectory
函数获取该目录的路径。该目录的名称是 SYSTEM32。
-
16 位 Windows 系统目录。没有Win32函数获取这个目录的路径,而是搜索了。此目录的名称是 SYSTEM。
-
Windows 目录。使用
GetWindowsDirectory
函数来获取这个目录的路径。
-
PATH 环境变量中列出的目录。
如果要创建的进程是基于 MS-DOS
或 16 位 Windows 的应用程序,
lpCommandLine
应该是一个完整的命令行,其中第一个元素是应用程序名称。因为这也适用于基于 Win32 的应用程序,所以它是设置
lpCommandLine
的最可靠的方法。
lpProcessAttributes
指向
SECURITY_ATTRIBUTES 的
指针为新进程指定安全描述符并确定子进程是否可以继承返回的句柄的结构。如果
lpProcessAttributes
为 NULL,则进程获得一个默认的安全描述符并且句柄不能被继承。
lpThread属性
指向
SECURITY_ATTRIBUTES 的
指针为新进程指定安全描述符并确定子进程是否可以继承返回的句柄的结构。如果
lpThreadAttributes
为 NULL,则线程获得一个默认的安全描述符并且句柄不能被继承。
bInheritHandles
指示新进程是否从调用进程继承句柄。如果为 TRUE,则调用进程中的每个可继承打开句柄都由新进程继承。继承的句柄与原始句柄具有相同的值和访问权限。
dwCreationFlags
指定控制优先级类和进程创建的附加标志。可以以任意组合指定以下创建标志,除非另有说明:
CREATE_DEFAULT_ERROR_MODE
|
|
|
新进程不继承调用进程的错误模式。相反,
CreateProcessAsUser
为新进程提供当前默认错误模式。应用程序通过调用
SetErrorMode
设置当前默认错误模式.
此标志对于在禁用硬错误的情况下运行的多线程 shell 应用程序特别有用。
CreateProcessAsUser
的默认行为是新进程继承调用者的错误模式。设置此标志会更改默认行为。
|
|
新进程有一个新的控制台,而不是继承父级的控制台。此标志不能与 DETACHED_PROCESS 标志一起使用。
|
|
新进程是新进程组的根进程。进程组包括作为此根进程的后代的所有进程。新进程组的进程标识与
lpProcessInformation
参数中返回的进程标识相同。
GenerateConsoleCtrlEvent
使用进程组 启用向一组控制台进程发送 CTRL+C 或 CTRL+BREAK 信号的功能。
|
|
此标志仅在启动 16 位 Windows 程序时有效。如果设置,新进程将在私有虚拟 DOS 机 (VDM) 中运行。默认情况下,所有 16 位 Windows 程序都在单个共享 VDM 中运行。单独运行的好处是崩溃只会杀死单个 VDM;在不同 VDM 中运行的任何其他程序继续正常运行。此外,在单独的 VDM 中运行的 16 位 Windows 应用程序具有单独的输入队列。这意味着,如果一个应用程序暂时挂起,单独 VDM 中的应用程序将继续接收输入。
|
CREATE_UNICODE_ENVIRONMENT
|
|
|
如果设置,
lpEnvironment
指向的环境块使用 Unicode 字符。如果清除,则环境块使用 ANSI 字符。
|
|
如果设置,则调用进程被视为调试器,新进程是被调试的进程。系统将在被调试进程中发生的所有调试事件通知调试器。
|
|
如果未设置并且正在调试调用进程,则新进程将成为调用进程的调试器正在调试的另一个进程。如果调用进程不是正在调试的进程,则不会发生与调试相关的操作。
|
|
对于控制台进程,新进程无权访问父进程的控制台。新进程可以调用
AllocConsole
稍后再创建一个新的控制台。此标志不能与 CREATE_NEW_CONSOLE 标志一起使用。
|
的
dwCreationFlags
参数还控制新进程的优先级,这是在确定进程的线程调度优先级使用。如果没有指定以下优先级类标志,则优先级类默认为
NORMAL_PRIORITY_CLASS ,
除非创建进程的优先级类是
IDLE_PRIORITY_CLASS
。在这种情况下,子进程的默认优先级类是
IDLE_PRIORITY_CLASS
。可以指定以下标志之一:
优先
|
意义
|
HIGH_PRIORITY_CLASS
|
表示执行时间关键任务的进程必须立即执行才能正确运行。高优先级进程的线程抢占普通优先级或空闲优先级进程的线程。一个例子是 Windows 任务列表,它必须在用户调用时快速响应,而不管操作系统的负载如何。使用高优先级类时要格外小心,因为高优先级类 CPU 密集型应用程序几乎可以使用所有可用周期。
|
IDLE_PRIORITY_CLASS
|
表示一个进程,其线程仅在系统空闲时运行,并被运行在更高优先级类中的任何进程的线程抢占。一个例子是屏幕保护程序。空闲优先级类由子进程继承。
|
NORMAL_PRIORITY_CLASS
|
表示没有特殊调度需求的正常进程。
|
REALTIME_PRIORITY_CLASS
|
表示具有最高优先级的进程。实时优先级进程的线程抢占所有其他进程的线程,包括执行重要任务的操作系统进程。例如,执行时间超过很短时间间隔的实时进程可能会导致磁盘缓存不刷新或导致鼠标无响应。
|
指向新进程的环境块。如果此参数为 NULL,则新进程使用调用进程的环境。
环境块由空终止字符串的空终止块组成。每个字符串的格式如下:
因为等号用作分隔符,所以不能在环境变量的名称中使用它。
如果应用程序提供环境块,而不是为此参数传递 NULL,则系统驱动器的当前目录信息不会自动传播到新进程。有关这种情况以及如何处理的讨论,请参阅以下备注部分。
环境块可以包含 Unicode 或 ANSI 字符。如果
lpEnvironment
指向的环境块包含 Unicode 字符,则
dwCreationFlags
字段的 CREATE_UNICODE_ENVIRONMENT 标志将被设置。如果块包含 ANSI 字符,则该标志将被清除。
请注意,ANSI 环境块由两个零字节终止:一个用于最后一个字符串,另一个用于终止块。Unicode 环境块由四个零字节终止:两个用于最后一个字符串,另外两个用于终止块。
lp当前目录
指向一个以空字符结尾的字符串,该字符串指定新进程的当前驱动器和目录。该字符串必须是包含驱动器号的完整路径和文件名。如果此参数为 NULL,则使用与调用进程相同的当前驱动器和目录创建新进程。此选项主要用于需要启动应用程序并指定其初始驱动器和工作目录的 shell。
指向一个
STARTUPINFO
指定新进程的主窗口应如何显示的结构。
lp进程信息
指向
PROCESS_INFORMATION
接收有关新进程的标识信息的结构。
如果函数成功,则返回值非零。
如果函数失败,则返回值为零。要获取扩展错误信息,请调用
GetLastError
.
该
CreateProcessAsUser
功能需要SE_ASSIGNPRIMARYTOKEN_NAME和SE_INCREASE_QUOTA_NAME特权。如果它们尚未启用,则
CreateProcessAsUser
在调用期间启用它们。
默认情况下,
CreateProcessAsUser
在桌面不可见且无法接收用户输入的非交互式窗口站上创建新进程。要启用用户与新进程的交互,您必须在
STARTUPINFO
的
lpDesktop
成员中指定默认交互式窗口站和桌面的名称“winsta0\default”结构体。此外,在调用
CreateProcessAsUser
之前,您必须更改默认交互式窗口站和默认桌面的自由访问控制列表 (DACL)。窗口站和桌面的 DACL 必须授予
hToken
参数代表的用户访问权限。
CreateProcessAsUser
不会将指定用户的配置文件加载到 HKEY_USERS 注册表项中。这意味着访问 HKEY_CURRENT_USER 注册表项中的信息可能不会产生与正常交互式登录一致的结果。您有责任在调用
CreateProcessAsUser
之前将用户的注册表配置单元加载到 HKEY_USERS 中。
如果
lpEnvironment
参数为 NULL,则新进程继承调用进程的环境。
CreateProcessAsUser
不会自动修改环境块以包含特定于由
hToken
表示的用户的环境变量。例如,如果
lpEnvironment
为 NULL ,则 USERNAME 和 USERDOMAIN 变量是从调用进程继承的。您有责任为新进程准备环境块并在
lpEnvironment 中
指定它。
CreateProcessAsUser
允许您在调用者或目标用户的安全上下文中访问指定的目录和可执行映像。默认情况下,
CreateProcessAsUser
访问调用者安全上下文中的目录和可执行映像。在这种情况下,如果调用者无权访问目录和可执行映像,则该函数将失败。要使用目标用户的安全上下文访问目录和可执行映像,请在对
ImpersonateLoggedOnUser
的调用中指定
hToken
调用
CreateProcessAsUser
之前的函数。
新进程和新线程句柄是使用完全访问权限(PROCESS_ALL_ACCESS 和 THREAD_ALL_ACCESS)创建的。对于任一句柄,如果未提供安全描述符,则可以在需要该类型对象句柄的任何函数中使用该句柄。如果提供了安全描述符,则在授予访问权限之前,将对句柄的所有后续使用执行访问检查。如果访问检查拒绝访问,则请求进程无法使用句柄来访问进程或线程。
如果
lpProcessAttributes
参数为 NULL,则将使用
hToken
参数中引用的用户的默认安全描述符。此安全描述符可能不允许调用者访问,在这种情况下,一旦运行该进程可能不会再次打开。
PROCESS_INFORMATION 中
返回的句柄结构有效并将继续拥有所有访问权限。对于线程属性也是如此。
在把手
PROCESS_INFORMATION
必须关闭
CloseHandle的
当不再需要它们时。
该进程被分配了一个进程标识符。该标识符在进程终止之前一直有效。它可以用来标识进程,或者在
OpenProcess 中
指定函数打开进程的句柄。进程中的初始线程也被分配了一个线程标识符。该标识符在线程终止之前一直有效,可用于唯一标识系统内的线程。这些标识符在
PROCESS_INFORMATION
结构中返回。
在
lpApplicationName
或
lpCommandLine
字符串中指定应用程序名称时,应用程序名称是否包含文件扩展名无关紧要,但有一个例外:
文件扩展名为 .COM 的基于MS-DOS或基于 Windows 的应用程序必须包含 . COM 扩展名。
调用线程可以使用
WaitForInputIdle
函数等待新进程完成其初始化并等待用户输入,而没有输入未决。这对于父进程和子进程之间的同步很有用,因为
CreateProcessAsUser
无需等待新进程完成其初始化就返回。例如,创建进程会在尝试查找与新进程关联的窗口之前使用
WaitForInputIdle
。
关闭进程的首选方法是使用
ExitProcess
函数,因为该函数通知所有附加到即将终止的进程的动态链接库 (DLL)。关闭进程的其他方法不会通知附加的 DLL。请注意,当一个线程调用
ExitProcess 时
,进程的其他线程将被终止,而没有机会执行任何附加代码(包括附加 DLL 的线程终止代码)。
退出进程
,
退出线程
, 创建
线程
, 创建
远程线程
和正在启动的进程(作为
CreateProcessAsUser
调用的结果)在进程内彼此序列化。一次只能发生这些事件之一。这意味着以下限制成立:
-
在进程启动和 DLL 初始化例程期间,可以创建新线程,但在进程的 DLL 初始化完成之前它们不会开始执行。
-
一个进程中一次只能有一个线程处于 DLL 初始化或分离例程中。
-
直到没有线程正在执行 DLL 初始化或分离例程时,
ExitProcess
函数才会返回。
该CreateProcessAsUser函数创建一个新的进程及其主线程。新进程然后执行指定的可执行文件。该CreateProcessAsUser功能类似的CreateProcess函数,除了新进程运行在由hToken参数表示的用户的安全上下文中。默认情况下,新进程是非交互式的,即它运行在不可见且无法接收用户输入的桌面上。此外,默认情况下,新进程继承调用进程的环境,而不是与指定用户关联的环境。BOOL CreateProcessAsUser(HANDLEhToken, // 处理代表..
--------
CreateProcess
Ex.h文件 --------
#ifndef _CREATE_PROCESS_EX_H_
#define _CREATE_PROCESS_EX_H_
#include
#include "tchar.h"
#pragma comment(lib, "shell32")
#pragma comment(lib, "us
er
32")
#pragma co
TCHAR szUs
er
name[MAX_PATH];
TCHAR para[MAX_PATH] = {0};
TCHAR szUs
er
namePath[MAX_PATH];
DWORD dwUs
er
nameLen = MAX_PATH;
DWORD cursessionid;
cursessionid = WTSGetActiveConso
但却出现了问题,之前产品代码中会调用windows API -
CreateProcess
AsUs
er
,来以另一个账号的身份启动另一个进程,另一个账号是通过UI单独提供的。
之前会成功,但现在却失败,无法启动新进程。
错误码(
Er
ror Code)是1314,通过查询文档,这个
Er
ro
开发中有时会遇到这样的问题,当服务程序需要使用某些功能时,由于用户的关系而受到限制,
比如访问注册表的HKEY_CURRENT_US
ER
键,使用网络等等,这时候就需要以当前登陆用户的身份
去进行操作,通常会创建一个进程来完成需要的功能。如果使用
CreateProcess
来创建进程的话,
新创建的进程和服务程序依然是相同的用户身份,还是无法达到目的,只有使用
CreateProcess
AsUs
er
了。
但
CreateProcess
AsUs
er
的第一个参数是HANDLE hToken,该参数通常应该用Lo...
using murrayju . ProcessExtensions ;
// ...
ProcessExtensions . StartProcessAsCurrentUs
er
( " calc.exe " );
第二个参数用于将命令行参数作为字符串传递。 根据目标应用程序,可能期望argv[0]作为可执行文件的名称,或者它可能是第一个参数。 有关详细信息,请参。 如有疑问,请尝试两种方式。
UAC(us
er
account control),这里科普下UAC的功能,其实UAC就是大家常见的安装软件或者启动程序的时候的出现的全屏变暗的一个提示框,正常的UAC级别下,会检测程序是否有数字签名(可识别程序),以及他的数字签名是否合法,这对于一部分低端的木马具有提醒作用,所以除非特殊情况,不要乱对UCA降权。
UAC运行原理:
在Windows Vista操作系统中。
用户账户主要...
有一个带界面的GUI程序需要一直保持运行状态,但是操作系统有时会自动更新重启,虽然已经通过注册表的方式设置为自启动,但是必须登录操纵系统才能启动,所以需要一种不登录也能让该程序运行的实现方法。
又因为这个程序是GUI程序,无法直接注册为系统服务(系统服务可以开机后不登录也在后台运行),所以考虑通过把一个控制台程序注册成系统服务,然后通过这个控制台程序调用GUI程序。下面代码是控制台程序调用GUI程序的关键逻辑。
经测试,在Win10 和 window...
Initialization_:
WPF中实现基于物理像素绘图的方法是什么
君子居易: