繁体   English   中英

使用 CREATE_SUSPENDED 标志和 JobObject 从 CreateProcessAsUser 为 C# 进程设置 ProcessStartInfo

[英]Setting up ProcessStartInfo for C# process from CreateProcessAsUser with CREATE_SUSPENDED flag and JobObject

在我的 C# 程序中,我需要 (1) 创建一个处于挂起状态的进程和 (2) 修改令牌。 我这样做是为了我可以将它注册到JobObject,这样如果父进程在子进程仍在运行时意外终止,子进程就会被杀死。 我需要根据业务要求修改令牌。

我发现无法将未启动的 C# Process 添加JobObject ,或创建处于挂起状态的Process或修改其令牌。 所以,我使用 C++ CreateProcessAsUser来完成这些事情。 到现在为止还挺好:

      [DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
      private static extern bool CreateProcessAsUser(
        IntPtr hToken,
        String lpApplicationName,
        String lpCommandLine,
        IntPtr lpProcessAttributes,
        IntPtr lpThreadAttributes,
        bool bInheritHandle,
        uint dwCreationFlags,
        IntPtr lpEnvironment,
        String lpCurrentDirectory,
        ref STARTUPINFO lpStartupInfo,
        out PROCESS_INFORMATION lpProcessInformation);

      public static uint CreateSuspendedProcess(string appPath, string cmdLine = null, bool visible = false)
            result = CreateProcessAsUser(
              hUserToken, // Modified token - working great
              appPath, // Application Name - doesn't end up in Process.ProcessStartInfo?
              cmdLine, // is null
              IntPtr.Zero,
              IntPtr.Zero,
              false,
              dwCreationFlags, // contains CREATE_SUSPENDED
              pEnv,
              null, // working directory
              ref startInfo, // not related to C# ProcessStartInfo?
              out procInfo);

// does other stuff, and then returns the Process ID

我遇到问题的地方实际上是启动过程。

从调用者(见下面的片段),我尝试从我用 CreateProcessAsUser 创建的进程的 ID 获取进程。 CreateProcessAsUser 进行的进程没有包含文件名的 StartInfo。 我希望 appPath 的功能与 StartInfo.FileName 相同,但是这里有一些我不明白的地方,因为 process.StartInfo 似乎是虚拟信息, 根据我在这里阅读的文档,GetProcesses 等不会返回 StartInfo 和 StartInfo进程启动后无法修改。 我想在暂停状态下创建一个进程算作开始。

我是一名新手开发人员,在试图解决这个问题之前从未使用过 C++,但我能够学到的是,也许我不应该尝试执行 Process.Start - 但我还没有找到任何替代方案满足将进程注册到JobObject 的需要

 var processId = CreateSuspendedProcess(startInfo.FileName, startInfo.Arguments);

 IntPtr hProcess = IntPtr.Zero;

 using (var job = new Job())
 using (var process = Process.GetProcessById((int)processId)) // use the suspended process
 {

    var jobSuccess = job.AddProcess(process.Id); // this works

    if (!jobSuccess)
    {
       // do not proceed if process cannot be run in job object; dispose of both
       throw new Exception("Failed to add process to job object.");
    }

    // === I want the start info to have the filename, but can't except in Debug
    //process.StartInfo.FileName = startInfo.FileName;

    // other code here
    Process.Start(); // Get a no FileName error

是的,答案是避免使用 C# Process 类方法,而是手动打开和恢复进程中的所有线程。

  [DllImport("kernel32.dll")]
  static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);

  [DllImport("kernel32.dll")]
  static extern int ResumeThread(IntPtr hThread);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM