zoukankan      html  css  js  c++  java
  • 2019-11-29-dotnet-获取指定进程的输入命令行

    title author date CreateTime categories
    dotnet 获取指定进程的输入命令行
    lindexi
    2019-11-29 08:35:11 +0800
    2019-02-22 11:25:47 +0800
    dotnet

    本文告诉大家如何在 dotnet 获取指定的进程的命令行参数

    很多的程序在启动的时候都需要传入参数,那么如何拿到这些程序传入的参数?

    我找到两个方法,一个需要引用 C++ 库支持 x86 和 x64 程序,另一个都是C#代码,但是只支持 x64 程序

    本文提供一个由 StackOverflow 大神开发的库拿到进程的命令行

    在使用下面的代码需要引用两个 C++ 的库,可以从 csdn 下载

    使用下面的代码就可以拿到传入进程的参数,在使用之前,需要在输出的文件夹里面包含 ProcCmdLine32.dll 和 ProcCmdLine64.dll 可以从csdn 下载

            public static string GetCommandLineOfProcess(Process process)
            {
                // max size of a command line is USHORT/sizeof(WCHAR), so we are going
                // just allocate max USHORT for sanity sake.
                var stringBuilder = new StringBuilder(0xFFFF);
                if (Environment.Is64BitProcess)
                {
                    GetProcCmdLine64((uint) process.Id, stringBuilder, (uint) stringBuilder.Capacity);
                }
                else
                {
                    GetProcCmdLine32((uint) process.Id, stringBuilder, (uint) stringBuilder.Capacity);
                }
    
                return stringBuilder.ToString();
            }
    
            [DllImport("ProcCmdLine32.dll", CharSet = CharSet.Unicode, EntryPoint = "GetProcCmdLine")]
            private static extern bool GetProcCmdLine32(uint nProcId, StringBuilder stringBuilder, uint dwSizeBuf);
    
            [DllImport("ProcCmdLine64.dll", CharSet = CharSet.Unicode, EntryPoint = "GetProcCmdLine")]
            private static extern bool GetProcCmdLine64(uint nProcId, StringBuilder stringBuilder, uint dwSizeBuf);

    获取所有的进程的命令行可以使用这个代码

                foreach (var process in Process.GetProcesses())
                {
                    Console.WriteLine($"{process.ProcessName} {GetCommandLineOfProcess(process)}");
                }

    代码请看 https://github.com/lindexi/lindexi_gd/tree/cf4054b0f479986bd295a8e5b69c31ad8fd7fe10/GetProcessCommandLine

    上面的代码需要引用一个 C++ 的库,看起来不清真,下面通过全部 C# 的代码

            public static string GetCommandLineOfProcess(int processId)
            {
                var pid = processId;
    
                var pbi = new NativeMethods.PROCESS_BASIC_INFORMATION();
    
                IntPtr proc = NativeMethods.OpenProcess
                (
                    PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid
                );
    
                if (proc == IntPtr.Zero)
                {
                    return "";
                }
    
                if (NativeMethods.NtQueryInformationProcess(proc, 0, ref pbi, pbi.Size, IntPtr.Zero) == 0)
                {
                    var buff = new byte[IntPtr.Size];
                    if (NativeMethods.ReadProcessMemory
                    (
                        proc,
                        (IntPtr) (pbi.PebBaseAddress.ToInt32() + 0x10),
                        buff,
                        IntPtr.Size, out _
                    ))
                    {
                        var buffPtr = BitConverter.ToInt32(buff, 0);
                        var commandLine = new byte[Marshal.SizeOf(typeof(NativeMethods.UNICODE_STRING))];
    
                        if
                        (
                            NativeMethods.ReadProcessMemory
                            (
                                proc, (IntPtr) (buffPtr + 0x40),
                                commandLine,
                                Marshal.SizeOf(typeof(NativeMethods.UNICODE_STRING)), out _
                            )
                        )
                        {
                            var ucsData = ByteArrayToStructure<NativeMethods.UNICODE_STRING>(commandLine);
                            var parms = new byte[ucsData.Length];
                            if
                            (
                                NativeMethods.ReadProcessMemory
                                (
                                    proc, ucsData.buffer, parms,
                                    ucsData.Length, out _
                                )
                            )
                            {
                                return Encoding.Unicode.GetString(parms);
                            }
                        }
                    }
                }
    
                NativeMethods.CloseHandle(proc);
    
                return "";
            }
    
            private const uint PROCESS_QUERY_INFORMATION = 0x400;
            private const uint PROCESS_VM_READ = 0x010;
    
            private static T ByteArrayToStructure<T>(byte[] bytes) where T : struct
            {
                var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
                var stuff = (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
                handle.Free();
                return stuff;
            }
    
            private static class NativeMethods
            {
                [DllImport("kernel32.dll", SetLastError = true)]
                [return: MarshalAs(UnmanagedType.Bool)]
                internal static extern bool CloseHandle(IntPtr hObject);
    
                [DllImport("kernel32.dll", SetLastError = true)]
                internal static extern IntPtr OpenProcess
                (
                    uint dwDesiredAccess,
                    [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
                    int dwProcessId
                );
    
    
                [DllImport("kernel32.dll", SetLastError = true)]
                [return: MarshalAs(UnmanagedType.Bool)]
                internal static extern bool ReadProcessMemory
                (
                    IntPtr hProcess,
                    IntPtr lpBaseAddress,
                    byte[] lpBuffer,
                    int nSize,
                    out IntPtr lpNumberOfBytesRead
                );
    
                [DllImport("ntdll.dll")]
                internal static extern int NtQueryInformationProcess
                (
                    IntPtr ProcessHandle,
                    uint ProcessInformationClass,
                    ref PROCESS_BASIC_INFORMATION ProcessInformation,
                    uint ProcessInformationLength,
                    IntPtr ReturnLength
                );
    
                [StructLayout(LayoutKind.Sequential, Pack = 1)]
                internal struct PROCESS_BASIC_INFORMATION
                {
                    internal int ExitProcess;
                    internal IntPtr PebBaseAddress;
                    internal IntPtr AffinityMask;
                    internal int BasePriority;
                    internal IntPtr UniqueProcessId;
                    internal IntPtr InheritedFromUniqueProcessId;
    
                    internal uint Size => (uint) Marshal.SizeOf(typeof(PROCESS_BASIC_INFORMATION));
                }
    
                [StructLayout(LayoutKind.Sequential, Pack = 1)]
                internal struct UNICODE_STRING
                {
                    internal ushort Length;
                    internal ushort MaximumLength;
                    internal IntPtr buffer;
                }
            }

    获取所有进程的参数

            [STAThread]
            private static void Main(string[] args)
            {
                if (Environment.Is64BitProcess)
                {
                    throw new InvalidOperationException("暂时只支持x86程序");
                }
    
                foreach (var process in Process.GetProcesses())
                {
                    Console.WriteLine($"{process.ProcessName} {GetCommandLineOfProcess(process.Id)}");
                }
            }

    更简单是通过 WMI 获取指定进程的输入命令行

  • 相关阅读:
    抓鱼社区
    DotNetTextBox V3.0 所见即所得编辑器控件Ver3.3.3 Free(免费版)
    Pet Shop 4.0系统
    北大青鸟PPT/ Net学习课件/asp.net,AJAX,ADO.net视频教程
    [开源]ASP.NET通用权限管理系统(FrameWork) 1.0.1 Release
    sql isnull函数
    几种常见算法的介绍及复杂度分析(转)
    ajaxpro配置与使用
    C#对图片的几种简单处理
    [你必须知道的.NET] 开篇有益
  • 原文地址:https://www.cnblogs.com/lindexi/p/12085409.html
Copyright © 2011-2022 走看看