C#调用CreateProcess传EXTENDED_STARTUPINFO_PRESENT时触发AccessViolationException
问题原因及修复方案
核心错误
调用UpdateProcThreadAttribute传递父进程属性时参数不符合API要求:PROC_THREAD_ATTRIBUTE_PARENT_PROCESS属性要求lpValue参数传入父进程句柄变量的内存地址,而非直接传入句柄值本身。你当前代码直接把hShellProcess句柄值作为地址传入,系统会尝试读取该句柄值对应的内存地址(比如句柄值为0x4时就会读取0x00000004地址),直接触发访问违例。
修复步骤
1. 修正UpdateProcThreadAttribute参数
将父进程句柄变量固定后取内存地址传入,替换原有UpdateProcThreadAttribute调用代码:
// 固定hShellProcess变量获取其内存地址 GCHandle parentProcHandle = GCHandle.Alloc(hShellProcess, GCHandleType.Pinned); try { if (!UpdateProcThreadAttribute( sInfoEx.lpAttributeList, 0, (IntPtr)PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, parentProcHandle.AddrOfPinnedObject(), // 传入句柄变量的地址,而非句柄值 (IntPtr)IntPtr.Size, IntPtr.Zero, IntPtr.Zero)) { return 0; } } finally { parentProcHandle.Free(); }
你的代码已经引入System.Runtime.InteropServices命名空间,无需额外添加依赖。
2. 修正结构体对齐规则
Windows API要求相关结构体按8字节对齐,x64环境下默认对齐规则可能导致结构体布局错位,修改两个结构体的定义:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 8)] public struct STARTUPINFO { // 原有字段保持不变 } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 8)] public struct STARTUPINFOEX { public STARTUPINFO StartupInfo; public IntPtr lpAttributeList; }
3. 可选:修正程序路径拼接逻辑
你当前拼接的s1没有正确用双引号包裹路径,当路径含空格时会触发CreateProcess调用失败,修改为:
string s1 = $"\"{strAppPath}\"";
修改完成后重新运行代码,即可正常创建继承桌面进程权限的非提权子进程,不会再触发访问违例。
内容的提问来源于stack exchange,提问作者h.s.
相关产品推荐
相关产品推荐

