因为我正在尝试进行测试并了解本机p / invoke函数,我试图仅使用pinvoke,然后比较使用.net简单获取进程信息所需的时间
Process myProc = Process.GetProcessByName("WinRAR");
虽然我觉得我需要真正测量近2页的长度代码,使用P / invoke只是这样我可以得到相同的结果,但这次只有本机代码,我想它应该更快,我想要至少得到两者的基准,所以请在这里帮助。
所以似乎我的代码是1)...好吧我想我可以数到20 “列举”所有问题,但主要是:
(我正在使用Winforms应用,但你可以硬编码所需的ProcessName
以“搜索”正确的过程)
这里的大部分评论都是作者的代码的大部分内容 我之后只修改了一点枚举,以便您可以选择通过窗口标题或进程名称进行搜索
所以这是代码:
主要条目 - 创建类的实例:
pinvokers Pi = new pinvokers();
// Find all Internet Explorer instances(i used winrar, as my second task in this project is also test application performance... later on, and again, using only native calls)
Pi.FindWindows(0, pinvokers.SearchWin.ProcName, null, new Regex(TBX_SelectedWinName.Text), new pinvokers.FoundWindowCallback(pinvokers.foundWindowToPrint));
public class pinvokers
{
// Win32 constants.
const int WM_GETTEXT = 0x000D;
const int WM_GETTEXTLENGTH = 0x000E;
[DllImport("user32.Dll")]
private static extern Boolean EnumChildWindows(int hWndParent, PChildCallBack lpEnumFunc, int lParam);
[DllImport("user32.Dll")]
private static extern int GetWindowText(int hWnd, StringBuilder text, int count);
[DllImport("user32.Dll")]
private static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId);
[DllImport("user32.Dll")]
private static extern Int32 SendMessage(int hWnd, int Msg, int wParam, StringBuilder lParam);
[DllImport("user32.Dll")]
private static extern Int32 SendMessage(int hWnd, int Msg, int wParam, int lParam);
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint GetWindowModuleFileName(IntPtr hwnd,
StringBuilder lpszFileName, uint cchFileNameMax);
[DllImport("psapi.dll")]
private static extern uint GetModuleFileNameEx(IntPtr hWnd, IntPtr hModule, StringBuilder lpFileName, int nSize);
// The PChildCallBack delegate that we used with EnumWindows.
private delegate bool PChildCallBack(int hWnd, int lParam);
// This is an event that is run each time a window was found that matches the search criterias. The boolean
// return value of the delegate matches the functionality of the PChildCallBack delegate function.
static event FoundWindowCallback foundWindowCB;
public delegate bool FoundWindowCallback(int hWnd);
int parentHandle;
Regex process;
#region <<=========== not nedded - search by window title. i am looking to search via process name ===========>>
/* <- commented all unsuesd
Regex windowText;
public static bool foundWindowToPrint(int handle)
{
// Print the window info.
printWindowInfo(handle);
// Continue on with next window.
return true;
}
static void printWindowInfo(int handle)
{
// Get the text.
int txtLength = SendMessage(handle, WM_GETTEXTLENGTH, 0, 0);
StringBuilder sbText = new StringBuilder(txtLength + 1);
SendMessage(handle, WM_GETTEXT, sbText.Capacity, sbText);
// Now we can write out the information we have on the window.
MessageBox.Show("Handle: " + handle);
MessageBox.Show("Text : " + sbText);
}
=====>end of un needed search bywindowtitle1
*/
#endregion
// my plan was to use enum instead of if !empty or null value for ither title name or process name so that's how the original code ditermin wich one to execute.
public enum SearchWin
{
Title, ProcName
}
//first method (and that's all i could really tell.. as it is full of callbacks and private extern, and delegates ... so complex
public void FindWindows(int parentHandle, SearchWin By, Regex windowText, Regex process, FoundWindowCallback fwc)
{
this.parentHandle = parentHandle;
//this.windowText = windowText;
this.process = process;
// Add the FounWindowCallback to the foundWindow event.
foundWindowCB = fwc;
// Invoke the EnumChildWindows function.
EnumChildWindows(parentHandle, new PChildCallBack(enumChildWindowsCallback), 0);
}
// This function gets called each time a window is found by the EnumChildWindows function. The foun windows here
// are NOT the final found windows as the only filtering done by EnumChildWindows is on the parent window handle.
private bool enumChildWindowsCallback(int handle, int lParam)
{
#region <<=========== not nedded - search by window title. #2 ===========>>
/* <--here too window title portion of code commented
// If a window text was provided, check to see if it matches the window.
if (windowText != null)
{
int txtLength = SendMessage(handle, WM_GETTEXTLENGTH, 0, 0);
StringBuilder sbText = new StringBuilder(txtLength + 1);
SendMessage(handle, WM_GETTEXT, sbText.Capacity, sbText);
// If it does not match, return true so we can continue on with the next window.
if (!windowText.IsMatch(sbText.ToString()))
return true;
}
*/
#endregion //endr2
// If a process name was provided, check to see if it matches the window.
if (process != null)
{
int processID;
GetWindowThreadProcessId(handle, out processID);
// Now that we have the process ID, we can use the built in .NET function to obtain a process object.
var ProcessName = GetProcNameByID(processID);
// If it does not match, return true so we can continue on with the next window.
if (!process.IsMatch(ProcessName))
return true;
}
// If we get to this point, the window is a match. Now invoke the foundWindow event and based upon
// the return value, whether we should continue to search for windows.
return foundWindowCB(handle);
}
private string GetProcNameByID(int ProcID)
{
IntPtr hProcess = OpenProcess(0x0410, false, ProcID);
StringBuilder text = new StringBuilder(1000);
GetWindowModuleFileName(hProcess, text, (uint)text.Capacity);
//GetModuleFileNameEx(hProcess, IntPtr.Zero, text, text.Capacity);
//CloseHandle(hProcess); here i am trying to catch what enumeration of windows got in its net , all this code does work just copy and paste it .
var t = text.ToString();
if (t.ToLower().Contains("inra"))
MessageBox.Show(t);
return t;
}
}
所以这可能会更短一些是一个侧面问题 主要是:
为什么不列举所有流程?
答案 0 :(得分:-1)
我不知道这是否是我能得到的最好的,或者可能是某人知道他在做什么与win api,或p / invoke或者我必须尝试使unmanagedLand赢得.net内置的calsses 我可能已经卷起袖子并将一些c ++代码放在一起(可能需要一周时间) 并将其编译为一个DLL,以便在一个DLL中将所有函数组合在一起(如果它有一些性能增益) 然后我可能会缩小一些差距。 (顺便说一句,现在它更接近系统诊断结果,我认为它会更快,我错了)
但仍然只是因为知道我可以安全使用.net C# 并且相信微软对我的了解要比我好得多(:如何制作一门优秀的程序语言。
这是我用来通过所有dllllls导入的代码。我本应该知道进口任何东西而且成本(这里可能是进口税,这是可行的)
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void But_StartPinvoke_Click(object sender, EventArgs e)
{
var userInputOK = TBX_SelectedProcessName.userInput();
if(!userInputOK)
MessageBox.Show(RApss.mesgs.EmptyTbx);
RApss.Strings.UserInput = TBX_SelectedProcessName.Text;
RApss.Globs.TbxPname = TBX_SelectedProcessName.Text.AddSufixEXE();
doWarmUp();
Stopwatch SwGpbn = Stopwatch.StartNew();
SwGpbn.Start();
//string _netProcName = Process.GetProcessesByName(RApss.Strings.UserInput)[0].ProcessName;
Process p = Process.GetProcessesByName(RApss.Strings.UserInput)[0];
if (p.ProcessName.ResultFetched())
SwGpbn.Stop();
var msElps_Net4 = SwGpbn.ElapsedMilliseconds;
SwGpbn.Reset();
SwGpbn.Start();
EnumProcessesV3.GetProcessByName();
SwGpbn.Stop();
var msElpsNat = SwGpbn.ElapsedMilliseconds;
SwGpbn.Reset();
SwGpbn.Reset();
if (RApss.Globs.Result.ResultFetched()) MessageBox.Show(string.Concat(RApss.Globs.Result, "\r\nWas Fetched In: ", msElpsNat, " Via PinVoke\r\n Was Fetched In: ", msElps_Net4," Via C#.NET !" ));
}
private void doWarmUp()
{
List<string> swarm = new List<string>();
for (int i = 0; i < 50000; i++)
{
swarm.Add((i + 1 *500).ToString());
}
}
}
public class RApss
{
public class Globs
{
public static string TbxPname;
public static string Result = string.Empty;
}
public class Strings
{
public static string intputForProcessName = "Requiered Process Name";
public static string UserInput = string.Empty;
}
public class mesgs
{
public static string EmptyTbx = string.Concat("please fill ", Strings.intputForProcessName, " field");
}
}
public class EnumProcessesV3
{
#region APIS
[DllImport("psapi")]
private static extern bool EnumProcesses(
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] [In][Out] IntPtr[] processIds,
UInt32 arraySizeBytes,
[MarshalAs(UnmanagedType.U4)] out UInt32 bytesCopied);
[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, IntPtr dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);
[DllImport("psapi.dll")]
static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName, [In] [MarshalAs(UnmanagedType.U4)] int nSize);
[DllImport("psapi.dll", SetLastError = true)]
public static extern bool EnumProcessModules(IntPtr hProcess,
[Out] IntPtr lphModule,
uint cb,
[MarshalAs(UnmanagedType.U4)] out uint lpcbNeeded);
[DllImport("psapi.dll")]
static extern uint GetModuleBaseName(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName, [In] [MarshalAs(UnmanagedType.U4)] int nSize);
#endregion
#region ENUMS
[Flags]
enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VMOperation = 0x00000008,
VMRead = 0x00000010,
VMWrite = 0x00000020,
DupHandle = 0x00000040,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
Synchronize = 0x00100000
}
#endregion
public static void GetProcessByName()
{
UInt32 arraySize = 120;
UInt32 arrayBytesSize = arraySize * sizeof(UInt32);
IntPtr[] processIds = new IntPtr[arraySize];
UInt32 bytesCopied;
bool success = EnumProcesses(processIds, arrayBytesSize, out bytesCopied);
#region <<=========== some cleanUps ============>>
// trying to check what could have been taking extra mssssnds
//Console.WriteLine("success={0}", success);
//Console.WriteLine("bytesCopied={0}", bytesCopied);
//if (!success)
//{
// MessageBox.Show("Boo!");
// return;
//}
//if (0 == bytesCopied)
//{
// MessageBox.Show("Nobody home!");
// return;
//}
#endregion
UInt32 numIdsCopied = bytesCopied >> 2;
#region <<===========same here commenting anything that might cost nerowing the options ============>>
//if (0 != (bytesCopied & 3))
//{
// UInt32 partialDwordBytes = bytesCopied & 3;
// MessageBox.Show(String.Format("EnumProcesses copied {0} and {1}/4th DWORDS... Please ask it for the other {2}/4th DWORD",
// numIdsCopied, partialDwordBytes, 4 - partialDwordBytes));
// return;
//}
//taking initialisation of SB out of loop was a winning thought but nada no change maybe in nanos
#endregion
for (UInt32 index = numIdsCopied; index> 1 ; index--) // reversing from last process id(chitting) to erlier process id did not help to win the contest
{
StringBuilder szProcessName = new StringBuilder(1000);
int x = szProcessName.Capacity;
string sName = PrintProcessName(processIds[index-1],szProcessName,x);
if (sName.Equals(RApss.Globs.TbxPname)) // tryng hardcoded value instead of reading from a variable.(GlobalsClass)
{
RApss.Globs.Result = sName;
break;
}
////////IntPtr PID = processIds[index];
////////Console.WriteLine("Name '" + sName + "' PID '" + PID + "'");
}
}
static string PrintProcessName(IntPtr processID, StringBuilder sb, int Cpcty)
{
string sName = "";
//bool bFound = false;
IntPtr hProcess = OpenProcess(ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VMRead, false, processID);
if (hProcess != IntPtr.Zero)
{
IntPtr hMod = IntPtr.Zero;
uint cbNeeded = 0;
EnumProcessModules(hProcess, hMod, (uint)Marshal.SizeOf(typeof(IntPtr)), out cbNeeded);
if (GetModuleBaseName(hProcess, hMod, sb, Cpcty) > 0)
{
sName = sb.ToString();
//bFound = true;
}
// Close the process handle
CloseHandle(hProcess);
}
//if (!bFound)
//{
// sName = "<unknown>";
//}
return sName;
}
}
}
namespace RExt
{
public static class UserInputs
{
public static bool userInput(this TextBox tbxId)
{
return tbxId.Text.Length > 1;
}
}
public static class strExt
{
public static bool ResultFetched(this string StrToCheck)
{
return !string.IsNullOrWhiteSpace(StrToCheck);
}
public static string AddSufixEXE(this string StrToAppendEXE)
{
return string.Concat(StrToAppendEXE, ".exe");
}
}
}
如果那不起作用,请确保该项目的目标是x86 CPU和Rebuild 出于某种原因,我没有检查是什么使它适合x64和amp; 86