Process.executablePath property returns nullstring in 64-bit environment [duplicate] - vbscript

Why do some processes from wmic process get name, commandline, processid, executablePath not display a value for ExecutablePath?
But I can find it in taskmanager?
Is there any way to get executable path from wmic?

Thank you all, especially to #Eryk Sun, here is my quite simple solution for others who will contend with same problem.
import com.sun.jna.platform;
String getExPath(int pid) {
Kernel32 kernel32 = Kernel32.INSTANCE;
WinNT.HANDLE hProcess = kernel32.OpenProcess(WinNT.PROCESS_QUERY_LIMITED_INFORMATION, false, pid);
char buffer[] = new char[1024];
IntByReference size = new IntByReference(buffer.length);
kernel32.QueryFullProcessImageName(hProcess, 0, buffer, size);
return new String(buffer).trim();
}
I was looking for similar method for obtain a commandline of process but i was not sucessfull. I appreciate an advice.

Related

wmic process empty executablepath

Why do some processes from wmic process get name, commandline, processid, executablePath not display a value for ExecutablePath?
But I can find it in taskmanager?
Is there any way to get executable path from wmic?
Thank you all, especially to #Eryk Sun, here is my quite simple solution for others who will contend with same problem.
import com.sun.jna.platform;
String getExPath(int pid) {
Kernel32 kernel32 = Kernel32.INSTANCE;
WinNT.HANDLE hProcess = kernel32.OpenProcess(WinNT.PROCESS_QUERY_LIMITED_INFORMATION, false, pid);
char buffer[] = new char[1024];
IntByReference size = new IntByReference(buffer.length);
kernel32.QueryFullProcessImageName(hProcess, 0, buffer, size);
return new String(buffer).trim();
}
I was looking for similar method for obtain a commandline of process but i was not sucessfull. I appreciate an advice.

ShellExecute bat file elevated (FMX, Win32)

I want to spawn a batch file from my FMX app (on Win32) with elevated privileges. From Remy's answer at the bottom of this thread on ShellExecute I found how to launch the batch file. Now, i can't figure out how to launch it with elevated privilege. Below is my code:
String Prog = "c:\\Users\\rwp\\Desktop\\test.bat";
int nErrorCode = (int) ShellExecute(NULL, L"runas", Prog.c_str(), NULL, NULL, SW_SHOWNORMAL);
if (nErrorCode <= 32) {
ShowMessage("an error occured");
}
I added "runas" for the second argument after reading this to no avail. Running the batch file manually (right-click and run as admin) works. Here is content of the batch file fyi (just kicks of a system imaging):
c:\Windows\system32\wbAdmin.exe start backup -backupTarget:D: -include:C: -allCritical -quiet
How can i ShellExecute this batch file as admin?
UPDATE 1: I'm attempting to use CreateProcess per Remy suggestion. Here is my code (based on this example):
//Code is inside a __fastcall button click
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.lpReserved = NULL;
siStartInfo.lpReserved2 = NULL;
siStartInfo.cbReserved2 = 0;
siStartInfo.lpDesktop = NULL;
siStartInfo.dwFlags = 0;
// String strCmdLine = "C:\\Users\\rwpatter\\Desktop\\test.bat";
String strCmdLine = "C:\\Windows\\System32\\wbAdmin.exe start backup -backupTarget:T: -include:C: -allCritical -quiet";
// Create the child process.
int rtrn = CreateProcess(
NULL,
strCmdLine.c_str(),
NULL, // process security attributes
NULL, // primary thread security attributes
0, // handles are inherited
0, // creation flags
0, // use parent's environment
0, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
// Wait for the processs to finish
DWORD rc = WaitForSingleObject(
piProcInfo.hProcess, // process handle
INFINITE);
ShowMessage(IntToStr(rtrn));
If I run it as shown (right-click on exe and run as admin) it returns 0 which means it failed. If I run it by putting the wbAdmin command line in the test.bat file (see commented line right above String strCmdLine in the code) then CreateProcess returns a 1 (success) but wbAdmin is still not running. It flashed a DOS window and i captured it as shown in the picture below. It shows oriental characters in the title bar and says not recognized as internal or external command. But, if i run that test.bat directly (elevated) it runs wbAdmin no problem.
Any ideas on what is wrong? Besides me obviously being ignorant. (p.s. i'll get to testing Golvind's answer on the ShellExecute after this...)
Running the batch file manually (right-click and run as admin) works.
Because you are running the 64-bit version of cmd when you start it manually.
It shows oriental characters in the title bar and says not recognized
as internal or external command.
Because your application is 32-bit. A 32-bit application does not see the same System32 folder as 64-bit applications. You can access the 64-bit System32 folder in 32-bit applications with the virtual sysnative folder.
#include <shellapi.h>
...
String strCmdLine = "wbAdmin.exe start backup -backupTarget:T: -include:C: -allCritical -quiet";
int rtrn = CreateProcess(
NULL,
strCmdLine.c_str(),
NULL, // process security attributes
NULL, // primary thread security attributes
0, // handles are inherited
0, // creation flags
0, // use parent's environment
0, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
if (!rtrn)
{
String newCmdLine = "c:\\windows\\sysnative\\wbAdmin.exe start backup -backupTarget:T: -include:C: -allCritical -quiet";
rtrn = CreateProcess(
NULL,
newCmdLine.c_str(),
NULL, // process security attributes
NULL, // primary thread security attributes
0, // handles are inherited
0, // creation flags
0, // use parent's environment
0, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION
}
Or compile your application to 64-bit.
You need to launch CMD.exe as Administrator with "runas", and specify the batch file as a "run-me-then-exit" (i.e. /c) argument to command prompt, as so:
WCHAR wszCmdPath[MAX_PATH];
GetEnvironmentVariableW(L"ComSpec", wszCmdPath, MAX_PATH);
ShellExecuteW(NULL, L"runas", wszCmdPath, L"/c \"C:\\Path\\BatchFile.bat\"", L"", SW_SHOW);
Both functions called here can fail, and robust code would test for success before proceeding.

Getting process information of every process

I am trying to create a program that any normal user can run on windows and generate a process list of all processes, including the executable location. I have used CreateToolhelp32Snapshot() to get all process names, pid, ppid. But having issues getting the image path. Everything I do results in pretty much Access Denied.
I have tried ZwQueryInformationProcess, GetProcessImageFileName, etc. and also using OpenProcess to get the handle to each process. I can get the handle by using PROCESS_QUERY_LIMITED_INFORMATION, but any other option doesn't work. I am lost and have been at this for a few days. Can anyone point me in the right direction?
This is the code that works for non-admin user on Windows. Use the szExeFile member of PROCESSENTRY32 to get the path:
HANDLE hProcessSnap = NULL;
HANDLE hProcess = NULL;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass = 0;
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
return;
}
// Set the size of the structure before using it.
pe32.dwSize = sizeof(PROCESSENTRY32);
// Retrieve information about the first process,
// and exit if unsuccessful
if (!Process32First(hProcessSnap, &pe32))
{
CloseHandle(hProcessSnap); // clean the snapshot object
return;
}
// Now walk the snapshot of processes, and
// display information about each process in turn
do
{
// do something with the pe32 struct.
// pe32.szExeFile -> path of the file
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);

How to implement "Open With" command using ShellExecuteEx and wait for it to finish?

Seemingly simple task: I want to open the standard Windows dialog for picking the application to be used for opening the file, and then wait for this application to finish. The internet tells that ShellExecuteEx is the way to go.
Ok, so here's the code:
SHELLEXECUTEINFO sei;
::ZeroMemory(&sei,sizeof(sei));
sei.cbSize = sizeof(sei);
sei.lpFile = L"path/to/document";
sei.lpVerb = L"openas";
sei.lpParameters = L"";
sei.nShow = SW_SHOW;
sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_INVOKEIDLIST ;
BOOL ret = ::ShellExecuteEx(&sei);
DWORD waitResult = ::WaitForSingleObject(sei.hProcess, INFINITE);
But it doesn't work: specifying SEE_MASK_INVOKEIDLIST flag makes hProcess to always be NULL, even if a new process was indeed launched.
How can this be fixed? Thanks in advance!
The shell was never designed to do this and even if it was it would not work 100% of the time because not everything launches a new process (DDE, IShellExecuteHook, IDropTarget, IExecuteCommand etc).
If writing your own dialog is acceptable then you might want to take a look at IEnumAssocHandlers. Raymond Chen recently did a blog post about it.

ShellExecuteEx function always returning error code 5 (C++)

I need to start a process and have access to the PID, so I am trying to use ShellExecuteEx. I am attempting to open a batch file. However, no matter how I pass the parameters and no matter where the file is located and what permission's I have on the file, the function is returning with Error Code 5: Access is denied.
The File is located in the same location as the config files that have already been read successfully.
The File is set for full access permissions with any user.
It does this with any file type. I've tried just opening text files with the same outcome (Error 5)
If I use ShellExecute() instead, the batch file is run successfully.
Here is some of the code I've tried:
SHELLEXECUTEINFO exInfo;
exInfo.cbSize = sizeof(SHELLEXECUTEINFO);
exInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
exInfo.lpVerb = "open";
exInfo.lpFile = "C:\\batchtest.bat";
exInfo.nShow = SW_NORMAL;
BOOL hReturnCode = ShellExecute(&exInfo);
DWORD LastError = GetLastError();
I've also tried:
SHELLEXECUTEINFO exInfo;
exInfo.cbSize = sizeof(SHELLEXECUTEINFO);
exInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
exInfo.lpVerb = "open";
exInfo.lpFile = "C:\\Windows\\system32\\cmd.exe";
exInfo.lpParameters = "batchtest.bat";
And many variations of the above.
Also, I've tried something really simple like from here:
Get PID from ShellExecute
to no avail.
However this:
ShellExecute(NULL, "open", "C:\\testbat.bat", NULL, NULL, SW_SHOWNORMAL);
works without an error. Unfortunately, I need the PID, so I can't use ShellExecute.
Any suggestions would be greatly appreciated. I feel like I've exhausted all of my options.
Environment:
VS 2008
Windows 7
EDIT: fixed the code to "C:\batchtest.bat"; as suggested. (Still same result)
Figured it out.
In order to run batch file and I guess some other types of exe's on Windows 7, you have to elevate the call using the lpVerb = _TEXT("runas") -- even if you have UAC turned off. This isn't documented in the SHELLEXECUTEINFO structure documentation on MDSN (it isn't even given as an option), since it says: "The following verbs are commonly used"
The final code was as follows:
SHELLEXECUTEINFO exInfo;
exInfo.cbSize = sizeof(SHELLEXECUTEINFO);
exInfo.fMask = SEE_MASK_NOCLOSEPROCESS; //allows the PID to be returned
exInfo.hwnd = NULL;
exInfo.lpVerb = _TEXT("runas"); //elevates for Windows 7
exInfo.lpFile = "C:\\BatchTest.bat";
exInfo.lpParameters = NULL;
exInfo.nShow = SW_MAXIMIZE;
exInfo.hInstApp = NULL;
exInfo.lpDirectory = NULL;
BOOL hReturnCode = ShellExecuteEx(&exInfo);
I hope that helps others out.
Shouldn't the line
exInfo.lpFile = "C:\\batchtest.exe";
be
exInfo.lpFile = "C:\\batchtest.bat";

Resources