Commands CMD to c++

Apr 11, 2020 at 8:02pm
hi, I was looking for a way in c ++ to run the tasklist command of the cmd and then save the result in a string, so as to search within the string for a program name and see if in use. all this without opening a console page in addition to that of visual studio debug
Last edited on Apr 11, 2020 at 8:06pm
Apr 11, 2020 at 8:36pm
I don't know what the output of tasklist looks like, but maybe something like this would work. It's mostly a C program since _popen deals with FILE pointers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <cstdio>   // _popen for Windows declared here (?)
#include <cstdlib>
#include <cstring>

bool is_program_running(const char* prog)
{
    bool ret = false;

    FILE *p = _popen("tasklist", "r");
    if (!p)
    {
        std::cerr << "_popen failed\n";
        exit(1);
    }

    char line[512];
    while (fgets(line, sizeof line, p))
    {
        if (strstr(line, prog))
        {
            ret = true;
            break;
        }
    }

    _pclose(p);
    return ret;
}

int main()
{
    std::cout << is_program_running("my_prog") << '\n';
}

Apr 12, 2020 at 3:51am
Just want to say, utilities for things like this already exist.

You can do tasklist | findstr "program name" to filter the results of tasklist.

>tasklist | findstr "notepad"
notepad++.exe                 5020 Console                    1      9,324 K
notepad.exe                  12340 Console                    1      1,552 K

(grep could also be used instead of findstr. There are versions of grep available on Windows, which I use often.)

If that's all you want, you don't need C++.
Apr 12, 2020 at 5:52am
It’s actually pretty stupidly easy to do with the Windows API. There are a gazillion ways, but https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsenumerateprocessesa is a good API to use.

I chose to use a map (name → pid). You could easily use a set with just names, or whatever. Heck, you could specify the desired name as argument and return true or false.

Also, notice that you must be exact with the process name. If that is an issue you’ll need to add code to deal with it the way you want, such as allowing ".exe" to be optional in the name, or ignoring letter case, etc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <map>
#include <string>

#include <windows.h>
#include <wtsapi32.h>

#pragma comment(lib,"WtsApi32")

std::map <std::string, DWORD> get_running_processes()
{
  std::map <std::string, DWORD> result;
  WTS_PROCESS_INFOA*            pWPIs;
  DWORD                         dwProcessCount;
  if (WTSEnumerateProcessesA( WTS_CURRENT_SERVER_HANDLE, NULL, 1, &pWPIs, &dwProcessCount ))
  {
    for (DWORD n = 0; n < dwProcessCount; n++) result[ pWPIs[n].pProcessName ] = pWPIs[n].ProcessId;
    WTSFreeMemory( pWPIs );
  }
  return result;
}


#include <iostream>

int main( int argc, char** argv )
{
  auto processes = get_running_processes();
  
  if (argc == 1)
    // List all running process names
    for (auto name_id : processes)
      std::cout << name_id.first << "\n";
    
  else
    // PID of process given its name
    std::cout << processes[ argv[1] ] << "\n";
}

C:\Users\Michael\Programming\foo> cl /EHsc /W4 /Ox /std:c++17 pl.cpp
...

C:\Users\Michael\Programming\foo> pl notepad++.exe
380

C:\Users\Michael\Programming\foo> pl notepad++
0

C:\Users\Michael\Programming\foo> █

If you want the full file name of the process (assuming it exists), you can use OpenProcess() and QueryFullProcessImageName().

Enjoy!
Topic archived. No new replies allowed.