// 创建交互式服务安装完成以后,启动UI的程序
BOOL LaunchApplication(LPCTSTR lpszExecute, LPCTSTR lpszCmdLine)
{
BOOL bRet = FALSE;
HANDLE hUserTokenDup = NULL;
LPVOID pEnv = NULL;
do
{
DWORD dwSessionId = 0;
if (0xFFFFFFFF == (dwSessionId = WTSGetActiveConsoleSessionId())) { PRINT(ERR, GetLastError(), TEXT("WTSGetActiveConsoleSessionId")); break; }
#define DEFAULT_WINLOGON_APPLICATION (TEXT("winlogon.exe"))
#define DEFAULT_DEFAULT_APPLICATION (TEXT("explorer.exe")) // 需要以explorer.exe进程的Token来创建Env环境块,否则以服务启动的App在打开文件路径的方面可能会遇到一些问题,比如最常见的是会访问C:\Windows\System32\config\systemprofile导致访问了错误的位置。
DWORD dwWinlogonPid = 0;
if (0xFFFFFFFF == (dwWinlogonPid = GetProcessID(DEFAULT_WINLOGON_APPLICATION, dwSessionId))) { PRINT(ERR, TEXT("Get Process ID Failed!")); break; }
if (NULL == (hUserTokenDup = GetProcessTokenDup(dwWinlogonPid))) { PRINT(ERR, TEXT("Get Process Duplicate Token Failed!")); break; }
if (!AdjustProcessTokenDup(hUserTokenDup, dwSessionId)) { PRINT(ERR, TEXT("Adjust Process Token Failed!")); break; }
HANDLE hDefaultTokenDup2 = NULL;
DWORD dwDefaultPid = 0;
if (0xFFFFFFFF == (dwDefaultPid = GetProcessID(DEFAULT_DEFAULT_APPLICATION, dwSessionId))) { PRINT(ERR, TEXT("Get Process ID Failed!")); break; }
if (NULL == (hDefaultTokenDup2 = GetProcessTokenDup(dwDefaultPid))) { PRINT(ERR, TEXT("Get Process Duplicate Token Failed!")); break; }
// Create Environment Block
DWORD dwCreateFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
if (CreateEnvironmentBlock(&pEnv, hDefaultTokenDup2, TRUE)) { dwCreateFlags |= CREATE_UNICODE_ENVIRONMENT; }
// Launch Process In The Client's Logon Session
TCHAR szExecute[MAX_PATH] = { 0 };
GetModuleFileName(NULL, szExecute, _countof(szExecute));
_tcsrchr(szExecute, TEXT('\\'))[1] = TEXT('\0');
StringCbCat(szExecute, _countof(szExecute) - _tcslen(szExecute), lpszExecute);
TCHAR szCmdLine[MAX_PATH] = { 0 };
if (NULL != lpszCmdLine) { StringCchPrintf(szCmdLine, _countof(szCmdLine), TEXT("%s"), lpszCmdLine); }
#define DEFAULT_DESKTOP_WINSTA0 (TEXT("winsta0\\default"))
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { sizeof(STARTUPINFO) };
si.lpDesktop = DEFAULT_DESKTOP_WINSTA0;
if (!CreateProcessAsUser(hUserTokenDup,
szExecute,
szCmdLine,
NULL,
NULL,
FALSE,
dwCreateFlags,
pEnv,
NULL,
&si,
&pi))
{
PRINT(ERR, GetLastError(), TEXT("CreateProcessAsUser"));
break;
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
// Completed
bRet = TRUE;
} while (FALSE);
if (NULL != pEnv) { DestroyEnvironmentBlock(pEnv); pEnv = NULL; }
if (NULL != hUserTokenDup) { CloseHandle(hUserTokenDup); hUserTokenDup = NULL; }
return bRet;
}
DWORD GetProcessID(LPCTSTR lpszProcessName, DWORD dwSessionId)
{
DWORD dwProcessId = 0xFFFFFFFF;
HANDLE hSnapshot = INVALID_HANDLE_VALUE;
do
{
_ASSERT(NULL != lpszProcessName);
if (NULL == lpszProcessName) { break; }
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hSnapshot) { PRINT(ERR, GetLastError(), TEXT("CreateToolhelp32Snapshot")); break; }
PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };
if (!Process32First(hSnapshot, &pe32)) { PRINT(ERR, GetLastError(), TEXT("Process32First")); break; }
do
{
if (0 == _tcsicmp(pe32.szExeFile, lpszProcessName))
{
DWORD dwProcessSessionId = 0;
if (ProcessIdToSessionId(pe32.th32ProcessID, &dwProcessSessionId)
&& (dwSessionId == dwProcessSessionId))
{
dwProcessId = pe32.th32ProcessID;
break;
}
}
} while (Process32Next(hSnapshot, &pe32));
// Completed
} while (FALSE);
if (INVALID_HANDLE_VALUE != hSnapshot) { CloseHandle(hSnapshot); hSnapshot = INVALID_HANDLE_VALUE; }
return dwProcessId;
}
HANDLE GetProcessTokenDup(DWORD dwProcessId)
{
HANDLE hProcess = NULL;
HANDLE hToken = NULL;
HANDLE hTokenDup = NULL;
do
{
if (NULL == (hProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, dwProcessId))) { PRINT(ERR, GetLastError(), TEXT("OpenProcess")); break; }
if (!OpenProcessToken(hProcess,
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE,
&hToken))
{
PRINT(ERR, GetLastError(), TEXT("OpenProcessToken"));
break;
}
if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hTokenDup)) { PRINT(ERR, GetLastError(), TEXT("DuplicateTokenEx")); break; }
// Completed
} while (FALSE);
if (NULL != hToken) { CloseHandle(hToken); hToken = NULL; }
if (NULL != hProcess) { CloseHandle(hProcess); hProcess = NULL; }
return hTokenDup;
}
BOOL AdjustProcessTokenDup(HANDLE hTokenDup, DWORD dwSessionId)
{
BOOL bRet = FALSE;
do
{
if (NULL == hTokenDup) { break; }
// Adjust Token Privileges
if(!SetTokenInformation(hTokenDup, TokenSessionId, (LPVOID)&dwSessionId, sizeof(dwSessionId))) { PRINT(ERR, GetLastError(), TEXT("SetTokenInformation")); break; }
if (!AdjustTokenDupPrivileges(hTokenDup, SE_DEBUG_NAME)) { PRINT(ERR, TEXT("Enable SE_DEBUG_NAME Privilege Failed!")); }
if (!AdjustTokenDupPrivileges(hTokenDup, SE_TCB_NAME)) { PRINT(ERR, TEXT("Enable SE_TCB_NAME Privilege Failed!")); }
if (!AdjustTokenDupPrivileges(hTokenDup, SE_CHANGE_NOTIFY_NAME)) { PRINT(ERR, TEXT("Enable SE_CHANGE_NOTIFY_NAME Privilege Failed!")); }
if (!AdjustTokenDupPrivileges(hTokenDup, SE_INCREASE_QUOTA_NAME)) { PRINT(ERR, TEXT("Enable SE_INCREASE_QUOTA_NAME Privilege Failed!")); }
if (!AdjustTokenDupPrivileges(hTokenDup, SE_ASSIGNPRIMARYTOKEN_NAME)) { PRINT(ERR, TEXT("Enable SE_ASSIGNPRIMARYTOKEN_NAME Privilege Failed!")); }
// Completed
bRet = TRUE;
} while (FALSE);
return bRet;
}
BOOL AdjustTokenDupPrivileges(HANDLE hTokenDup, LPCTSTR lpszPrivileges)
{
BOOL bRet = FALSE;
do
{
LUID luid = { 0 };
if (!LookupPrivilegeValue(NULL, lpszPrivileges, &luid))
{
PRINT(ERR, GetLastError(), TEXT("LookupPrivilegeValue"));
break;
}
TOKEN_PRIVILEGES tp = { 0 };
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Adjust token privileges
if (!AdjustTokenPrivileges(hTokenDup, FALSE, &tp, sizeof(tp), NULL, NULL))
{
PRINT(ERR, GetLastError(), TEXT("AdjustTokenPrivileges"));
break;
}
// Completed
bRet = TRUE;
} while (FALSE);
return bRet;
}
void PRINT(DWORD dwLevel, LPCTSTR lpszFormat, ...)
{
do
{
if (!m_bDbgValid) { break; }
TCHAR szText[DEFAULT_PRINTF_BUFFER_LENGTH] = { 0 };
TCHAR szBuffer[DEFAULT_PRINTF_BUFFER_LENGTH] = { 0 };
// Parse Parameter
va_list args;
va_start(args, lpszFormat);
StringCchVPrintf(szBuffer, _countof(szBuffer), lpszFormat, args);
va_end(args);
// Format
FORMAT(szText, _countof(szText), szBuffer);
// Dump
DUMP(dwLevel, szText);
} while (FALSE);
}
void PRINT(DWORD dwLevel, DWORD dwErrorId, LPCTSTR lpszDescription)
{
do
{
if (!m_bDbgValid) { break; }
TCHAR szText[DEFAULT_PRINTF_BUFFER_LENGTH] = { 0 };
// Format
FORMAT(szText, _countof(szText), dwErrorId, lpszDescription);
// Dump
DUMP(dwLevel, szText);
} while (FALSE);
}
void CCommon::FORMAT(LPTSTR lpszText, size_t nLength, LPCTSTR lpszInfo)
{
_ASSERT(NULL != lpszText);
_ASSERT(nLength > 0);
_ASSERT(NULL != lpszInfo);
SYSTEMTIME st = { 0 };
GetLocalTime(&st);
StringCchPrintf(lpszText,
nLength,
TEXT("[%04d-%02d-%02d %02d:%02d:%02d.%03d] - %s\r\n"),
st.wYear,
st.wMonth,
st.wDay,
st.wHour,
st.wMinute,
st.wSecond,
st.wMilliseconds,
lpszInfo);
}
void FORMAT(LPTSTR lpszText, size_t nLength, DWORD dwErrorId, LPCTSTR lpszDescription)
{
_ASSERT(NULL != lpszText);
_ASSERT(nLength > 0);
_ASSERT(NULL != lpszDescription);
SYSTEMTIME st = { 0 };
GetLocalTime(&st);
TCHAR szBuffer[DEFAULT_PRINTF_BUFFER_LENGTH] = { 0 };
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErrorId, LANG_NEUTRAL, (LPTSTR)szBuffer, _countof(szBuffer), NULL);
StringCchPrintf(lpszText,
nLength,
TEXT("[%04d-%02d-%02d %02d:%02d:%02d.%03d] - Call %s() Failed with Error: %d - %s\r\n"),
st.wYear,
st.wMonth,
st.wDay,
st.wHour,
st.wMinute,
st.wSecond,
st.wMilliseconds,
lpszDescription,
dwErrorId,
szBuffer);
}相关推荐
系统服务用CreateProcessAsUser实现创建界面进程
一、需求 有一个带界面的GUI程序需要一直保持运行状态,但是操作系统有时会自动更新重启,虽然已经通过注册表的方式设置为自启动,但是必须登录操纵系统才能启动,所以需要一种不登录也能让该程序运行的实现方法。 又因为这个程序是GUI程序,无法直接注册为系统服务(系统服务可以开机后不登录也在后台运行),所以考虑通过把一个控制台程序注册成系统服务,然后通过这个控制台程序调用GUI程序。下面代码是控制台程序调用GUI程序的关键逻辑。 经测试,在Win10 和 window...
在服务中用管理员权限创建一个可弹出UI的进程 (转载)
转载:http://blog.youkuaiyun.com/woshinia/article/details/7850295 转载:http://blog.youkuaiyun.com/hurryboylqs/article/details/53004970 转载:http://blog.youkuaiyun.com/fakine/article/details/8537763 HANDLE hToken = NU...
Windows系统图标定制:彻底去除快捷方式箭头与UAC盾牌
在Windows系统管理与个性化定制领域,图标渲染机制是系统界面交互的基础技术之一。系统通过图标覆盖层合成技术,在原始图标上叠加特定标识(如快捷方式箭头、UAC盾牌)来传达文件属性与安全状态。这项技术虽然提升了系统的易用性与安全性提示,但在追求视觉统一和桌面美化的场景下,这些默认覆盖层可能破坏整体设计风格。通过深入理解注册表键值与系统资源调用的原理,用户可以在不破坏系统核心功能的前提下,精准控制图标渲染流程,实现视觉元素的定制化。本文聚焦于通过注册表修改这一安全可逆的方案,详细解析如何去除快捷方式小箭头和U
windows系统服务 启动带有管理员权限的GUI进程
事情是这样的,公司的产品有个守护进程(windows Service)需要启动产品的主程序exe,让主程序它运行为管理员权限(因为主程序会加载一个插件,插件中有列出端口监听的功能,需要由端口查找到进程PID,由进程PID查找进程名或进程镜像路径,这些对于一些特殊进程例如svchost需要有管理员权限才能查到进程名和路径)。windows下的程序是不能在运行时获得管理员权限的,只能在创建进程的时候提升为管理员权限。如果是普通进程运行一个管理员权限程序,可以调用ShellExcute API。双击鼠标运行e..
Inno Setup 进阶:如何通过修改Manifest实现管理员权限自动获取
本文详细解析了Inno Setup安装包获取管理员权限的两种核心方法。针对Windows UAC机制导致的安装中断问题,重点介绍了通过修改脚本参数PrivilegesRequired的官方配置法,以及通过Resource Hacker工具修改SetupLdr.e32引导器清单的进阶技巧,帮助开发者实现安装程序的自动权限提升,提升用户体验与软件专业性。
Windows权限管理:手动添加“管理员取得所有权”右键菜单的完整指南
在Windows系统管理与开发运维中,文件权限控制是核心基础。访问控制列表(ACL)和用户账户控制(UAC)机制共同构成了系统的安全防线,通过所有者(Owner)和权限条目来管理资源访问。其技术价值在于平衡安全性与操作便利性,确保系统文件不被误改,同时允许授权用户进行必要管理。在软件部署、系统迁移、遗留文件处理等应用场景中,管理员常需快速取得文件或文件夹所有权以解决“拒绝访问”问题。本文聚焦于利用takeown和icacls命令行工具,通过直接修改Windows注册表,在右键菜单中安全、高效地集成“管理员取
大家知道如何去掉电脑桌面图标的小盾牌吗
小盾牌是Windows操作系统中文件和文件夹的安全属性的标志,它表示该文件或文件夹受到了系统的保护,对其进行修改需要管理员权限。虽然小盾牌的作用是为了保护文件不被误操作或非法访问,但在某些情况下,用户可能需要对特定文件或文件夹进行修改或删除的操作,此时小盾牌就成为了阻碍。通过本文介绍的几种方法,您可以轻松地去除小盾牌,更便捷地管理和操作自己的电脑。⑤ 在“权限”对话框中,找到自己的用户名,勾选“完全控制”或其他需要的权限。⑧ 在“输入的对象名称”栏目中输入你的用户名,然后点击“检查名称”按钮确认。
Windows安全中心空白界面修复:从服务重置到系统文件修复的完整指南
在Windows操作系统中,系统服务与核心组件是保障安全功能正常运行的基础。当关键服务状态异常或系统文件损坏时,依赖这些组件的安全应用界面可能出现加载失败,表现为空白或卡顿。从技术原理看,Windows安全中心作为UWP应用,其运行依赖于SecurityHealthService、WinDefend等后台服务,以及完整的系统文件与注册表项。一旦服务被禁用、系统映像损坏或组件注册失效,前端界面将无法获取数据。在工程实践中,通过PowerShell命令重启服务、重置应用缓存,或使用DISM和SFC工具修复系统文
Qt应用程序自启动及管理员权限
Windows开机自启动的程序很多,包括系统软件、杀毒软件、一些其他安装软件等等。自启动当然是可以禁止的,通过软件管理或者手动删除对应的注册表中的键值项即可!但是为了系统的服务或者操作上的方便,我们往往需要在开机的时候自启动一些服务。Qt程序也不例外,在发布Qt程序的时候,我们通常也需要开机自启动自己的程序,那么如何实现呢?主要采用修改注册表的方式。 代码比较简单: #define RE...
使用Windbg时遇到的几个典型问题说明
详细讲述在使用Windbg过程中遇到的几个典型问题
【Linux系统】Kdenlive软件多机位同音频视频同步化处理
Kdenlive简介 官网链接:https://kdenlive.org/zh/ 命令行安装: apt-get install kdenlive Kdenlive能够进行多轨道视频编辑,可以使用和调整多条音频、视频轨道。每条轨道可以按需进行单独锁定、静音。 Kdenlive多机位同音频视频同步化处理步骤 1. 新建Kdenlive文件 选择<文件>-<新建>,建立新的kdenlive文件,初始设置为<视频轨:2>,<音频轨:2>。 视.
Qt Windows应用管理员权限启动:UAC机制、清单配置与QMake实战
在Windows桌面应用开发中,用户账户控制(UAC)机制是保障系统安全的核心设计,它基于最小权限原则,默认以标准用户权限运行程序。其原理是通过可执行文件的清单资源声明权限级别,开发者可配置requestedExecutionLevel字段控制程序行为。这项技术的核心价值在于平衡安全性与功能性,使需要访问系统资源或注册表的工具软件能合法获取权限,避免运行时出现“拒绝访问”错误。典型的应用场景包括安装程序、系统配置工具、服务管理及端口监听应用等。本文聚焦于Qt框架下的具体工程实践,详细解析如何通过QMake构
微信H5网页授权通用方案:中转页破解域名限制,适配Hash/History路由
在Web开发中,OAuth 2.0授权码模式是实现第三方登录的通用标准,其核心原理是通过授权服务器颁发临时代码,再由客户端交换访问令牌。这一机制在微信公众号H5开发中尤为重要,用于安全获取用户身份。然而,微信平台对网页授权回调域名有严格的数量限制,这成为多子域名、多环境及微前端架构下业务扩展的主要瓶颈。其技术价值在于通过设计一个统一的中转授权页,将授权逻辑与业务逻辑解耦,让所有业务页面共享一个已配置的授权入口,从而突破域名配额限制。该方案的关键在于适配不同的前端路由模式,需精准处理Hash模式与Histor
Windows 系统 OpenClaw 执行策略报错及管理员权限设置深度解析与实操指南
本文深入解析Windows系统中OpenClaw工具常见的执行策略报错和管理员权限问题,提供系统化解决方案。首先剖析PowerShell执行策略机制(Restricted/RemoteSigned等)和UAC权限控制原理,指出OpenClaw运行时的典型错误场景。针对执行策略问题,详解临时/永久修改策略、数字签名脚本等方法;针对权限问题,提供以管理员身份运行、修改快捷方式、调整UAC设置等方案。
嵌入式Linux网络调试踩坑记:YT8531/YT8521 PHY驱动移植与设备树配置实战
本文深入解析嵌入式Linux系统中YT8531/YT8521 PHY驱动移植与设备树配置的实战经验。从网络不通的常见现象入手,详细介绍了驱动移植关键点、设备树配置详解及常见问题排查技巧,帮助开发者快速解决RGMII接口调试难题,提升嵌入式网络开发效率。
21、空间数据处理中的克里金方法及应用
本文介绍了空间数据处理中的克里金方法,特别是带外部漂移的克里金法(KED)及其在遥感数据融合和支持变化问题中的应用。讨论了克里金方法的基本原理、优缺点以及在不同空间分辨率遥感图像融合中的具体操作流程。同时,还涉及了地统计数据融合和支持变化问题的解决方案,包括块克里金法、面到点克里金法和多边形克里金法等。
管理员以标准权限运行时
http://blog.youkuaiyun.com/bingghost/article/details/7592043 在XP时代,大多数用户都用一个管理员(administrator)帐号来登录Windows 利用这个账户,用户几乎能没有任何限制的访问重要的系统资源,因为该账户被授予了很高的权限,一旦用这个帐号登录了xp以及xp之前的操作系统,Windows操作系统就会创建一个安全令牌
RH850从0搭建Autosar开发环境【3X】- Davinci Configurator之Port模块配置详解(MCAL配置)
RH850从0搭建Autosar开发环境【3X】- Davinci Configurator之Port模块配置详解(MCAL配置)
【第36节】windows原理:权限管理和内存管理
遇到这种情况,我们可以用HeapCreate函数创建一个独立的内存堆,等使用完之后,直接用HeapDestroy函数,就能把这个内存堆里的所有内存都释放掉。而这个进程创建的线程,默认和进程的权限相同。VirtualAllocEx、ReadProcessMemory与WriteProcessMemory三个函数,可实现跨进程的内存分配、读取、写入等操作,是很多安全技术的基础函数,后续学习远程线程注入时,会详细讲解这些函数的用法。所以,在自己的进程里,是访问不了其他进程内存的,尽管不同进程的地址看上去很像。
Moviepy自动化剪辑视频中的广告
本教程展示了如何使用 Python 中的 MoviePy 库,通过检测和剪辑广告段落来实现视频内容的清洁播放。通过广告检测算法和 MoviePy 剪辑功能的结合,可以自动化处理视频,极大提升编辑效率。在学习和应用中,理解广告检测的原理及其实现方法尤为重要,以便针对不同类型的视频进行调整。此外,MoviePy 的灵活性使其适用于多种视频编辑场景,适合自动化内容制作与优化。
【机器学习与数据挖掘实战 | 医疗】案例18:基于Apriori算法的中医证型关联规则分析
本案例针对三阴乳腺癌患者,经问卷调查收集数据并筛选处理形成原数据,经清洗、特征选择与变换后,构建Apriori模型,基于业务理解与建模结果,分析患者症状与中医证型关联,并据症状给出建议 。
WIN7下权限问题分析与解答
1.WIN7下运行软件为什么会提示权限不足? 为了降低计算机系统的风险,Windows Vista引入UAC(User Access Control)机制,默认情况下,应用程序都运行在普通用户权限下。Windows 7继承了这一机制。一般应用程序通常都假设以管理员权限运行,在其它操作系统上(如:windows XP)没有UAC的限制,运行程序的权限不会降低。若以管理员账户登录后,安装软件不会
Linux ARM平台开发系列讲解(GPIO子系统) 2.3.2 GPIO子系统常用函数解析
1. 概述 该章节会记录一年常用的GPIO子系统常用函数,会更具情况不断更新 static inline int gpio_get_value(unsigned int gpio) 功能 :用于获取某个GPIO引脚上的值 gpio : gpio引脚号 返回值:非负值,得到的 GPIO 值;负值,获取失败。 static inline void gpio_set_value(unsigned int gpio, int value) static inline int gpio_cansleep(unsi
如何在windows开启UAC(用户账号控制)的情况下优雅的管理程序的权限申请方案(一)
问题起源: 简单的说就是在windows vista之前的windows系统,只要是管理员(比如Administrator)账户登录系统以后,该账户下的任何程序的启动权限都具有管理员权限;这个权限是很高的(仅仅比System权限低),具有这个权限的程序几乎可以“为所欲为”,试想如果一个病毒程序拥有了这个权限,那它可以做很多的“破坏”活动,这将给系统的安全造成了极大的安全隐患。 U...
WINCC7.3破解文件
WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!
STM32F407中文手册
STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。
程序以管理员方式运行的原因分析
这是 Windows(从 Vista 系统开始引入 UAC 用户账户控制机制)最重要的安全设计之一。简单来说,系统将权限分为两个等级,绝大多数程序默认在“标准用户权限”下运行,就像在一个受保护的沙箱里,而当程序需要执行“危险”操作时,必须明确请求“管理员权限”。操作系统通过UAC弹窗询问你:“这个程序要动用万能钥匙,你确定要给它吗?” 你的回答必须是谨慎和有判断力的。:现代操作系统的“管理员权限”是一把能打开系统所有大门的。
SAP B1中文培訓教材_SDK
公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说
4130



被折叠的 条评论
为什么被折叠?



