mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 03:21:12 +07:00
platform: added custom utility to get list of running processes on Windows, it works faster than standard wmic.exe (RIDER-IC-CR-2)
This commit is contained in:
BIN
bin/win/WinProcessListHelper.exe
Normal file
BIN
bin/win/WinProcessListHelper.exe
Normal file
Binary file not shown.
6
native/WinProcessListHelper/.gitignore
vendored
Normal file
6
native/WinProcessListHelper/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
*.opensdf
|
||||
*.suo
|
||||
*.sdf
|
||||
Debug
|
||||
Release
|
||||
ipch
|
||||
22
native/WinProcessListHelper/WinProcessListHelper.sln
Normal file
22
native/WinProcessListHelper/WinProcessListHelper.sln
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.40629.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinProcessListHelper", "WinProcessListHelper\WinProcessFetcherNative.vcxproj", "{3AA23150-835F-4EB4-A0DB-92BD17F31E40}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{3AA23150-835F-4EB4-A0DB-92BD17F31E40}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{3AA23150-835F-4EB4-A0DB-92BD17F31E40}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{3AA23150-835F-4EB4-A0DB-92BD17F31E40}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{3AA23150-835F-4EB4-A0DB-92BD17F31E40}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{3AA23150-835F-4EB4-A0DB-92BD17F31E40}</ProjectGuid>
|
||||
<RootNamespace>WinProcessListHelper</RootNamespace>
|
||||
<ProjectName>WinProcessListHelper</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
193
native/WinProcessListHelper/WinProcessListHelper/main.cpp
Normal file
193
native/WinProcessListHelper/WinProcessListHelper/main.cpp
Normal file
@@ -0,0 +1,193 @@
|
||||
|
||||
#define _WIN32_DCOM
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
#include <comdef.h>
|
||||
#include <Wbemidl.h>
|
||||
|
||||
#pragma comment(lib, "wbemuuid.lib")
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
HRESULT hres;
|
||||
|
||||
// Step 1: --------------------------------------------------
|
||||
// Initialize COM. ------------------------------------------
|
||||
|
||||
hres = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
if (FAILED(hres))
|
||||
{
|
||||
cout << "Failed to initialize COM library. Error code = 0x"
|
||||
<< hex << hres << endl;
|
||||
return 1; // Program has failed.
|
||||
}
|
||||
|
||||
// Step 2: --------------------------------------------------
|
||||
// Set general COM security levels --------------------------
|
||||
|
||||
hres = CoInitializeSecurity(
|
||||
nullptr,
|
||||
-1, // COM authentication
|
||||
nullptr, // Authentication services
|
||||
nullptr, // Reserved
|
||||
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
|
||||
nullptr, // Authentication info
|
||||
EOAC_NONE, // Additional capabilities
|
||||
nullptr // Reserved
|
||||
);
|
||||
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
cout << "Failed to initialize security. Error code = 0x"
|
||||
<< hex << hres << endl;
|
||||
CoUninitialize();
|
||||
return 1; // Program has failed.
|
||||
}
|
||||
|
||||
// Step 3: ---------------------------------------------------
|
||||
// Obtain the initial locator to WMI -------------------------
|
||||
|
||||
IWbemLocator *pLoc = nullptr;
|
||||
|
||||
hres = CoCreateInstance(
|
||||
CLSID_WbemLocator,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_IWbemLocator, reinterpret_cast<LPVOID *>(&pLoc));
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
cout << "Failed to create IWbemLocator object."
|
||||
<< " Err code = 0x"
|
||||
<< hex << hres << endl;
|
||||
CoUninitialize();
|
||||
return 1; // Program has failed.
|
||||
}
|
||||
|
||||
// Step 4: -----------------------------------------------------
|
||||
// Connect to WMI through the IWbemLocator::ConnectServer method
|
||||
|
||||
IWbemServices *pSvc = nullptr;
|
||||
|
||||
// Connect to the root\cimv2 namespace with
|
||||
// the current user and obtain pointer pSvc
|
||||
// to make IWbemServices calls.
|
||||
hres = pLoc->ConnectServer(
|
||||
_bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
|
||||
nullptr, // User name. NULL = current user
|
||||
nullptr, // User password. NULL = current
|
||||
nullptr, // Locale. NULL indicates current
|
||||
NULL, // Security flags.
|
||||
nullptr, // Authority (for example, Kerberos)
|
||||
nullptr, // Context object
|
||||
&pSvc // pointer to IWbemServices proxy
|
||||
);
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
cout << "Could not connect. Error code = 0x"
|
||||
<< hex << hres << endl;
|
||||
pLoc->Release();
|
||||
CoUninitialize();
|
||||
return 1; // Program has failed.
|
||||
}
|
||||
|
||||
//cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
|
||||
|
||||
|
||||
// Step 5: --------------------------------------------------
|
||||
// Set security levels on the proxy -------------------------
|
||||
|
||||
hres = CoSetProxyBlanket(
|
||||
pSvc, // Indicates the proxy to set
|
||||
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
|
||||
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
|
||||
nullptr, // Server principal name
|
||||
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
|
||||
nullptr, // client identity
|
||||
EOAC_NONE // proxy capabilities
|
||||
);
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
cout << "Could not set proxy blanket. Error code = 0x"
|
||||
<< hex << hres << endl;
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
CoUninitialize();
|
||||
return 1; // Program has failed.
|
||||
}
|
||||
|
||||
// Step 6: --------------------------------------------------
|
||||
// Use the IWbemServices pointer to make requests of WMI ----
|
||||
|
||||
// For example, get the name of the operating system
|
||||
IEnumWbemClassObject* pEnumerator = nullptr;
|
||||
hres = pSvc->ExecQuery(
|
||||
bstr_t("WQL"),
|
||||
bstr_t("SELECT * FROM Win32_Process"),
|
||||
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
|
||||
nullptr,
|
||||
&pEnumerator);
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
cout << "Query for processes failed."
|
||||
<< " Error code = 0x"
|
||||
<< hex << hres << endl;
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
CoUninitialize();
|
||||
return 1; // Program has failed.
|
||||
}
|
||||
|
||||
// Step 7: -------------------------------------------------
|
||||
// Get the data from the query in step 6 -------------------
|
||||
|
||||
IWbemClassObject *pclsObj = nullptr;
|
||||
ULONG uReturn = 0;
|
||||
int i = 0;
|
||||
while (pEnumerator)
|
||||
{
|
||||
i++;
|
||||
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
|
||||
&pclsObj, &uReturn);
|
||||
|
||||
if (0 == uReturn)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
VARIANT vtId;
|
||||
pclsObj->Get(L"ProcessId", 0, &vtId, nullptr, nullptr);
|
||||
wprintf_s(L"%d\n", vtId.intVal);
|
||||
VARIANT vtName;
|
||||
pclsObj->Get(L"Name", 0, &vtName, nullptr, nullptr);
|
||||
if (vtName.bstrVal != nullptr)
|
||||
wprintf_s(L"%ls\n", vtName.bstrVal);
|
||||
else
|
||||
wprintf_s(L"\n");
|
||||
VARIANT vtCmd;
|
||||
pclsObj->Get(L"CommandLine", 0, &vtCmd, nullptr, nullptr);
|
||||
if (vtCmd.bstrVal != nullptr)
|
||||
wprintf_s(L"%ls\n", vtCmd.bstrVal);
|
||||
else
|
||||
wprintf_s(L"\n");
|
||||
VariantClear(&vtId);
|
||||
VariantClear(&vtName);
|
||||
VariantClear(&vtCmd);
|
||||
|
||||
pclsObj->Release();
|
||||
}
|
||||
// Cleanup
|
||||
// ========
|
||||
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
pEnumerator->Release();
|
||||
CoUninitialize();
|
||||
return 0; // Program successfully completed.
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.execution.process.ProcessInfo;
|
||||
import com.intellij.execution.process.ProcessOutput;
|
||||
import com.intellij.execution.util.ExecUtil;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
@@ -32,10 +33,7 @@ import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -44,6 +42,7 @@ import java.util.List;
|
||||
|
||||
public class ProcessListUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.execution.process.impl.ProcessListUtil");
|
||||
private static final String WIN_PROCESS_LIST_HELPER_FILENAME = "WinProcessListHelper.exe";
|
||||
|
||||
@NotNull
|
||||
public static ProcessInfo[] getProcessList() {
|
||||
@@ -55,6 +54,9 @@ public class ProcessListUtil {
|
||||
private static List<ProcessInfo> doGetProcessList() {
|
||||
List<ProcessInfo> result;
|
||||
if (SystemInfo.isWindows) {
|
||||
result = getProcessList_WinNativeFetcher();
|
||||
if (result != null) return result;
|
||||
LOG.info("Cannot get process list via NativeFetcher, fallback to wmic");
|
||||
|
||||
result = getProcessList_WindowsWMIC();
|
||||
if (result != null) return result;
|
||||
@@ -90,7 +92,7 @@ public class ProcessListUtil {
|
||||
ProcessOutput processOutput = ExecUtil.execAndGetOutput(new GeneralCommandLine(command));
|
||||
int exitCode = processOutput.getExitCode();
|
||||
if (exitCode != 0) {
|
||||
LOG.error("Cannot get process list, 'ps' exited with code " + exitCode + ", stdout:\n"
|
||||
LOG.error("Cannot get process list, command '" + StringUtil.join(command, " ") +"' exited with code " + exitCode + ", stdout:\n"
|
||||
+ processOutput.getStdout()
|
||||
+ "\nstderr:\n"
|
||||
+ processOutput.getStderr());
|
||||
@@ -253,6 +255,69 @@ public class ProcessListUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static List<ProcessInfo> getProcessList_WinNativeFetcher() {
|
||||
try {
|
||||
File nativeFetcher = findNativeFetcher();
|
||||
return parseCommandOutput(Collections.singletonList(nativeFetcher.getAbsolutePath()), ProcessListUtil::parseWinNativeFetcherOutput);
|
||||
} catch (FileNotFoundException e) {
|
||||
LOG.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<ProcessInfo> parseWinNativeFetcherOutput(String output) throws IllegalStateException {
|
||||
String[] strings = StringUtil.splitByLines(output, false);
|
||||
ArrayList<ProcessInfo> result = new ArrayList<>();
|
||||
int processCount = strings.length / 3;
|
||||
for (int i = 0; i < processCount; i++) {
|
||||
int offset = i * 3;
|
||||
int id = StringUtil.parseInt(strings[offset], -1);
|
||||
if (id == -1 || id == 0)
|
||||
continue;
|
||||
String name = strings[offset + 1];
|
||||
if (StringUtil.isEmpty(name))
|
||||
continue;
|
||||
String commandLine = strings[offset + 2];
|
||||
String args = "";
|
||||
if (commandLine.isEmpty()) {
|
||||
commandLine = name;
|
||||
}
|
||||
else {
|
||||
args = findArgs(commandLine, name);
|
||||
}
|
||||
result.add(new ProcessInfo(id, commandLine, name, args));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String findArgs(String commandLine, String name) {
|
||||
List<String> commandLineList = StringUtil.splitHonorQuotes(commandLine, ' ');
|
||||
if (commandLineList.isEmpty())
|
||||
return "";
|
||||
String first = StringUtil.unquoteString(commandLineList.get(0));
|
||||
if (StringUtil.endsWithIgnoreCase(first, name)) {
|
||||
List<String> argsList = commandLineList.subList(1, commandLineList.size());
|
||||
return StringUtil.join(argsList, " ");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static File findNativeFetcher() throws FileNotFoundException {
|
||||
String prefix = "win";
|
||||
String[] dirs = {
|
||||
PathManager.getBinPath(),
|
||||
PathManager.getHomePath() + "/ultimate/community/bin/" + prefix,
|
||||
PathManager.getHomePath() + "/community/bin/" + prefix,
|
||||
PathManager.getBinPath() + '/' + prefix
|
||||
};
|
||||
for (String dir : dirs) {
|
||||
File file = new File(dir, WIN_PROCESS_LIST_HELPER_FILENAME);
|
||||
if (file.exists() && file.isFile())
|
||||
return file;
|
||||
}
|
||||
throw new FileNotFoundException(String.format("%s was not found at: %s", WIN_PROCESS_LIST_HELPER_FILENAME, String.join(",", (CharSequence[]) dirs)));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static List<ProcessInfo> getProcessList_WindowsWMIC() {
|
||||
return parseCommandOutput(Arrays.asList("wmic.exe", "path", "win32_process", "get", "Caption,Processid,Commandline,ExecutablePath"),
|
||||
@@ -294,10 +359,7 @@ public class ProcessListUtil {
|
||||
commandLine = name;
|
||||
}
|
||||
else {
|
||||
int nameIndex = StringUtil.indexOfIgnoreCase(commandLine, name, 0);
|
||||
if (nameIndex != -1) {
|
||||
args = commandLine.substring(nameIndex + name.length()).trim();
|
||||
}
|
||||
args = findArgs(commandLine, name);
|
||||
}
|
||||
|
||||
result.add(new ProcessInfo(pid, commandLine, name, args, executablePath));
|
||||
|
||||
Reference in New Issue
Block a user