CreateProcessasuser - AccessViolationError 错误

发布于 2024-12-25 12:17:50 字数 3568 浏览 2 评论 0原文

我正在尝试使用 createProcessasUser 从 Windows 服务(LocalSystem)启动 Gui 托盘应用程序 - 就像这样:

    public static System.Diagnostics.Process StartProcessInSession(int sessionID, String commandLine)
    {
        IntPtr userToken;
        if (WTSQueryUserToken(sessionID, out userToken))
        {
            //note that WTSQueryUserToken only works when in context of local system account with SE_TCB_NAME
            IntPtr lpEnvironment;
            if (CreateEnvironmentBlock(out lpEnvironment, userToken, false))
            {
                StartupInfo si = new StartupInfo();
                si.cb = Marshal.SizeOf(si);
                si.lpDesktop = "winsta0\\default";
                si.dwFlags = STARTF.STARTF_USESHOWWINDOW;
                si.wShowWindow = ShowWindow.SW_SHOW;
                ProcessInformation pi;
                if (CreateProcessAsUser(userToken, null, new StringBuilder(commandLine), IntPtr.Zero, IntPtr.Zero, false, CreationFlags.CREATE_NEW_CONSOLE | CreationFlags.CREATE_UNICODE_ENVIRONMENT, lpEnvironment, null, ref si, out pi))
                {
                    CloseHandle(pi.hThread);
                    CloseHandle(pi.hProcess);
                    //context.Undo();
                    try
                    {
                        return System.Diagnostics.Process.GetProcessById(pi.dwProcessId);
                    }
                    catch (ArgumentException e)
                    {
                        //The process ID couldn't be found - which is what always happens because it has closed
                        return null;
                    }
                }
                else
                {
                    int err = Marshal.GetLastWin32Error();
                    throw new System.ComponentModel.Win32Exception(err, "Could not create process.\nWin32 error: " + err.ToString());
                }
            }
            else
            {
                int err = Marshal.GetLastWin32Error();
                throw new System.ComponentModel.Win32Exception(err, "Could not create environment block.\nWin32 error: " + err.ToString());
            }
        }
        else
        {
            int err = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
            if (err == 1008) return null; //There is no token
            throw new System.ComponentModel.Win32Exception(err, "Could not get the user token from session " + sessionID.ToString() + " - Error: " + err.ToString());
        }
    }

我正在使用该函数:

   protected override void OnStart(string[] args)
    {   
       _agentProcess = StartProcessInSession(WTSGetActiveConsoleSessionId(), "Some_correct_path");  
    }

这实际上工作了一段时间,但在我的一次运行中它突然停止工作。执行 CreateProccessAsUser 命令时出现以下错误(不能再深入)

{"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."}

我不知道为什么会发生这种情况,甚至不知道如何进一步调试它,无论如何有任何想法吗?因为这对我来说没有任何意义。

CreateProcessas用户定义:

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, [In] StringBuilder lpCommandLine, IntPtr /*to a SecurityAttributes struct or null*/ lpProcessAttributes, IntPtr /*to a SecurityAttributes struct or null*/ lpThreadAttributes, bool bInheritHandles, CreationFlags creationFlags, IntPtr lpEnvironment, String lpCurrentDirectory, ref StartupInfo lpStartupInfo, out ProcessInformation lpProcessInformation);

谢谢

I am trying to start a Gui tray application from a windows service (LocalSystem) using createProcessasUser - like so:

    public static System.Diagnostics.Process StartProcessInSession(int sessionID, String commandLine)
    {
        IntPtr userToken;
        if (WTSQueryUserToken(sessionID, out userToken))
        {
            //note that WTSQueryUserToken only works when in context of local system account with SE_TCB_NAME
            IntPtr lpEnvironment;
            if (CreateEnvironmentBlock(out lpEnvironment, userToken, false))
            {
                StartupInfo si = new StartupInfo();
                si.cb = Marshal.SizeOf(si);
                si.lpDesktop = "winsta0\\default";
                si.dwFlags = STARTF.STARTF_USESHOWWINDOW;
                si.wShowWindow = ShowWindow.SW_SHOW;
                ProcessInformation pi;
                if (CreateProcessAsUser(userToken, null, new StringBuilder(commandLine), IntPtr.Zero, IntPtr.Zero, false, CreationFlags.CREATE_NEW_CONSOLE | CreationFlags.CREATE_UNICODE_ENVIRONMENT, lpEnvironment, null, ref si, out pi))
                {
                    CloseHandle(pi.hThread);
                    CloseHandle(pi.hProcess);
                    //context.Undo();
                    try
                    {
                        return System.Diagnostics.Process.GetProcessById(pi.dwProcessId);
                    }
                    catch (ArgumentException e)
                    {
                        //The process ID couldn't be found - which is what always happens because it has closed
                        return null;
                    }
                }
                else
                {
                    int err = Marshal.GetLastWin32Error();
                    throw new System.ComponentModel.Win32Exception(err, "Could not create process.\nWin32 error: " + err.ToString());
                }
            }
            else
            {
                int err = Marshal.GetLastWin32Error();
                throw new System.ComponentModel.Win32Exception(err, "Could not create environment block.\nWin32 error: " + err.ToString());
            }
        }
        else
        {
            int err = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
            if (err == 1008) return null; //There is no token
            throw new System.ComponentModel.Win32Exception(err, "Could not get the user token from session " + sessionID.ToString() + " - Error: " + err.ToString());
        }
    }

I am using the function as so:

   protected override void OnStart(string[] args)
    {   
       _agentProcess = StartProcessInSession(WTSGetActiveConsoleSessionId(), "Some_correct_path");  
    }

This actually worked for a little while, but in one of my runs it suddenly stopped working... giving the following error when executing the CreateProccessAsUser command (cant go any deeper)

{"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."}

I have no idea why this is happening or even how to debug this any further, anyhow has any idea?? because this doesnt make any sense to me.

CreateProccessasuser definition:

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, [In] StringBuilder lpCommandLine, IntPtr /*to a SecurityAttributes struct or null*/ lpProcessAttributes, IntPtr /*to a SecurityAttributes struct or null*/ lpThreadAttributes, bool bInheritHandles, CreationFlags creationFlags, IntPtr lpEnvironment, String lpCurrentDirectory, ref StartupInfo lpStartupInfo, out ProcessInformation lpProcessInformation);

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

提笔书几行 2025-01-01 12:17:50

您的 ProcessInformation 类型是值类型(结构)还是引用类型(类)?

显示其定义以及 CreateProcessAsUser 的 p/invoke 声明。

顺便说一句,如果您使用正确的属性,所有 GetLastWin32Error 检查都是通过 p/invoke 为您完成的。

Is your ProcessInformation type a value type (struct) or a reference type (class)?

Show its definition and the p/invoke declaration for CreateProcessAsUser.

BTW, all that GetLastWin32Error checking is done for you by p/invoke if you use the right attributes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文