从“CreateProcess需要管理员权限”问题到最终解决过程总结

📑 从“CreateProcess需要管理员权限”问题到最终解决过程总结


1. 问题起因

ModuleLoginSDK::LoadLoginModule() 中调用:

CreateProcess(filePath.c_str(), NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);

发现启动 sdologin.exe 失败CreateProcess 返回 FALSE
GetLastError 返回错误码 740 (ERROR_ELEVATION_REQUIRED)。


2. 初步分析

  • CreateProcess 自身不需要管理员权限
  • 但是如果被启动的子程序(sdologin.exe要求管理员权限,而父进程没有提权,则 CreateProcess 会直接失败。

3. 进一步排查 Manifest 文件

提取 sdologin.exe.manifest 内容,发现如下:

<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>

确认:

  • requireAdministrator 意味着:必须管理员权限才能启动
  • 普通权限的 CreateProcess 无法直接启动它。

4. 初步方案

有两种应对方式:

方案方法特点
使用 ShellExecuteEx"runas"让系统弹出 UAC 确认用户体验差,弹窗
修改 manifestasInvoker子程序随父进程权限运行最干净,免弹窗

最终决定:修改 manifest 文件内容,降级到普通权限。


5. 排查项目配置(.vcproj

阅读 sdologin.vcproj 后发现:

  • 没有直接写 /MANIFESTUAC 指令。

  • 但是在 <Tool Name="VCLinkerTool" ...> 节点下有:

    <?xml version="1.0" encoding="gb2312"?>
    <VisualStudioProject
    	ProjectType="Visual C++"
    	Version="9.00"
    	Name="sdologin"
    	ProjectGUID="{C5E8C5E9-7E64-4A77-9964-59A0679EABDC}"
    	RootNamespace="GameLogin"
    	Keyword="Win32Proj"
    	TargetFrameworkVersion="131072"
    	>
    	<Platforms>
    		<Platform
    			Name="Win32"
    		/>
    	</Platforms>
    	<ToolFiles>
    	</ToolFiles>
    	<Configurations>
    		<Configuration
    			Name="Debug|Win32"
    			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
    			IntermediateDirectory="$(ConfigurationName)"
    			ConfigurationType="1"
    			CharacterSet="1"
    			>
    			<Tool
    				Name="VCPreBuildEventTool"
    			/>
    			<Tool
    				Name="VCCustomBuildTool"
    			/>
    			<Tool
    				Name="VCXMLDataGeneratorTool"
    			/>
    			<Tool
    				Name="VCWebServiceProxyGeneratorTool"
    			/>
    			<Tool
    				Name="VCMIDLTool"
    			/>
    			<Tool
    				Name="VCCLCompilerTool"
    				Optimization="0"
    				AdditionalIncludeDirectories=".;./LianXiang;./ADSClient;../../include;../public;../CrashRpt/CrashReport;../duiex/;../../include/sdgupdate/"
    				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;USE_SDO_CUSTOMUI;NOTCATCH_EXCEPTION;DUILIB_DEBUGVIEW"
    				MinimalRebuild="true"
    				BasicRuntimeChecks="3"
    				RuntimeLibrary="1"
    				UsePrecompiledHeader="0"
    				WarningLevel="3"
    				Detect64BitPortabilityProblems="false"
    				DebugInformationFormat="4"
    				CallingConvention="0"
    			/>
    			<Tool
    				Name="VCManagedResourceCompilerTool"
    			/>
    			<Tool
    				Name="VCResourceCompilerTool"
    			/>
    			<Tool
    				Name="VCPreLinkEventTool"
    			/>
    			<Tool
    				Name="VCLinkerTool"
    				AdditionalDependencies="Protectedsd.lib tinyxmlsd.lib SafeStored.lib procnetd.lib CrashRptd.lib SdoBaseClientd.lib sdostatesvrclientd.lib sdologinkitd.lib DuiExLibD.lib duilibd.lib ADSClientSDK.lib libeay32.lib ssleay32.lib"
    				OutputFile="../../bin/$(ConfigurationName)/sdologin/sdologin.exe"
    				LinkIncremental="2"
    				AdditionalLibraryDirectories="../../lib/"
    				IgnoreDefaultLibraryNames=""
    				GenerateDebugInformation="true"
    				SubSystem="2"
    				RandomizedBaseAddress="1"
    				DataExecutionPrevention="0"
    				TargetMachine="1"
    			/>
    			<Tool
    				Name="VCALinkTool"
    			/>
    			<Tool
    				Name="VCManifestTool"
    			/>
    			<Tool
    				Name="VCXDCMakeTool"
    			/>
    			<Tool
    				Name="VCBscMakeTool"
    			/>
    			<Tool
    				Name="VCFxCopTool"
    			/>
    			<Tool
    				Name="VCAppVerifierTool"
    			/>
    			<Tool
    				Name="VCPostBuildEventTool"
    			/>
    		</Configuration>
    		<Configuration
    			Name="Release|Win32"
    			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
    			IntermediateDirectory="$(ConfigurationName)"
    			ConfigurationType="1"
    			CharacterSet="1"
    			WholeProgramOptimization="1"
    			>
    			<Tool
    				Name="VCPreBuildEventTool"
    			/>
    			<Tool
    				Name="VCCustomBuildTool"
    			/>
    			<Tool
    				Name="VCXMLDataGeneratorTool"
    			/>
    			<Tool
    				Name="VCWebServiceProxyGeneratorTool"
    			/>
    			<Tool
    				Name="VCMIDLTool"
    			/>
    			<Tool
    				Name="VCCLCompilerTool"
    				WholeProgramOptimization="false"
    				AdditionalIncludeDirectories=".;./LianXiang;../../include;../public;../CrashRpt/CrashReport;../duiex/;../../include/sdgupdate/"
    				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;USE_SDO_CUSTOMUI;USE_BINFORMAT_CONFIG"
    				RuntimeLibrary="0"
    				UsePrecompiledHeader="0"
    				WarningLevel="3"
    				Detect64BitPortabilityProblems="false"
    				DebugInformationFormat="3"
    			/>
    			<Tool
    				Name="VCManagedResourceCompilerTool"
    			/>
    			<Tool
    				Name="VCResourceCompilerTool"
    			/>
    			<Tool
    				Name="VCPreLinkEventTool"
    			/>
    			<Tool
    				Name="VCLinkerTool"
    				AdditionalDependencies="Protecteds.lib tinyxmls.lib safestore.lib duilib.lib procnet.lib Crashrpt.lib sdostatesvrclient.lib sdologinkit.lib DuiExLib.lib ADSClientSDK.lib libeay32.lib ssleay32.lib SdoBaseClient.lib"
    				OutputFile="../../bin/$(ConfigurationName)/sdologin/sdologin.exe"
    				LinkIncremental="1"
    				AdditionalLibraryDirectories="../../lib"
    				UACExecutionLevel="0"
    				GenerateDebugInformation="true"
    				ProgramDatabaseFile="../../bin/$(ConfigurationName)/pdb/$(TargetName).pdb"
    				GenerateMapFile="true"
    				MapFileName="../../bin/$(ConfigurationName)/pdb/$(TargetName).map"
    				SubSystem="2"
    				OptimizeReferences="2"
    				EnableCOMDATFolding="2"
    				RandomizedBaseAddress="1"
    				DataExecutionPrevention="0"
    				ImportLibrary="$(ConfigurationName)\$(TargetName).lib"
    				TargetMachine="1"
    			/>
    			<Tool
    				Name="VCALinkTool"
    			/>
    			<Tool
    				Name="VCManifestTool"
    				EmbedManifest="false"
    			/>
    			<Tool
    				Name="VCXDCMakeTool"
    			/>
    			<Tool
    				Name="VCBscMakeTool"
    			/>
    			<Tool
    				Name="VCFxCopTool"
    			/>
    			<Tool
    				Name="VCAppVerifierTool"
    			/>
    			<Tool
    				Name="VCPostBuildEventTool"
    			/>
    		</Configuration>
    	</Configurations>
    	<References>
    	</References>
    	</Files>
    	<Globals>
    	</Globals>
    </VisualStudioProject>
    
    
UACExecutionLevel="2"

这行配置直接导致了生成的 manifest 强制为 requireAdministrator

UACExecutionLevel="2"` ➔ `requireAdministrator`
 `UACExecutionLevel="1"` ➔ `highestAvailable`
 `UACExecutionLevel="0"` ➔ `asInvoker

6. 初步改动

第一次修改时,将 UACExecutionLevel2 改成了 1
结果 .manifest 变成了:

<requestedExecutionLevel level="highestAvailable" uiAccess="false"/>

虽然不强制要求管理员,但如果父进程是管理员还是会请求提权,不是完全跟随父进程权限


7. 正确最终修改

为了彻底做到普通权限,最终操作是:

  • .vcproj 文件里的 UACExecutionLevel="2" 改成:
UACExecutionLevel="0"

或者直接删除 UACExecutionLevel 这一行。

然后重新编译。

最终生成的 .manifest 文件内容变为:

<requestedExecutionLevel level="asInvoker" uiAccess="false"/>

✅ 彻底跟随父进程权限。
✅ 不再需要管理员权限。
CreateProcess 成功启动子进程,无需弹出UAC确认。


8. 解决结果确认

  • sdologin.exe 编译生成的 manifest 成功降级为 asInvoker
  • 程序通过普通权限的 CreateProcess 成功启动。
  • 整个过程无UAC弹窗,提升了用户体验。
  • 以后无需修改其他逻辑。

📌 总结一张表

阶段发现的问题处理操作结果
初步 CreateProcess 失败子程序需要管理员权限查看 manifest确认是 requireAdministrator
尝试修改修改 UACExecutionLevel="1"生成 highestAvailable仍有轻微提权行为
正确修改改成 UACExecutionLevel="0" 或删掉生成 asInvoker成功以普通权限运行

📚 重要补充知识

什么是 requestedExecutionLevel

Level含义使用场景
asInvoker跟随父进程权限,完全无感知普通应用、子进程
highestAvailable能提权就提,不能提就普通运行开发工具
requireAdministrator必须提权,否则不能运行安装程序、服务管理工具

🚀 小提示

如果想快速检查 .exe 里面的 manifest 内容,可以用 mt.exe

mt.exe -inputresource:your_program.exe;#1 -out:manifest.txt

这条命令能直接提取 embedded manifest 文件,确认权限等级。


✨ 最后一行总结

已经成功把 sdologin.exe 从必须管理员权限 ➔ 降级成跟随父进程权限 (asInvoker),CreateProcess彻底正常,用户体验无弹窗,流程完美!

🛡 遇到 CreateProcess 错误740快速排查 Checklist

步骤检查项说明
1检查子程序的 Manifest 文件是否包含 requireAdministrator
2检查父进程权限是否以管理员权限运行父程序
3检查 .vcproj 文件是否有 UACExecutionLevel="2" 配置
4使用 mt.exe 提取 Manifest确认真实运行时嵌入的 Manifest 内容
5修改 Manifest 为 asInvoker.vcproj ➔ 重新编译
6最后重新测试 CreateProcess确认是否成功,无需弹UAC
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

森明帮大于黑虎帮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值