I'm trying to run WSReset.exe on Windows 10 but keep getting a file not found error. The WSReset.exe is definitely in "C:\Windows\System32\WSReset.exe" but a CMD/Powershell window started from my program cannot seem to find it. But a CMD/Powershell window started outside my program does execute the file.
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
ZeroMemory(&processInfo, sizeof(processInfo));
int t = (CreateProcess(L"C:/Windows/System32/wsreset.exe", L"", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo));
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
or
SHELLEXECUTEINFO ShExecInfo = { 0 };
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = L"C:/Windows/System32/wsreset.exe";
ShExecInfo.lpParameters = L"";
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_SHOW;
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);
Produces the "Windows cannot find..." error message.
The app is 32 bits. Oddly System32 = 64 bit, SysWOW64 = 32 bit. So when I call "C:/Windows/System32/wsreset.exe" windows will turn it into "C:/Windows/SysWOW64/wsreset.exe" and there is no wsreset.exe at that location.
The solution is to disable redirection before calling CreateProcess/ShellExecuteEx/System.
//Disable redirection
PVOID OldValue = NULL;
Wow64DisableWow64FsRedirection(&OldValue);
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo = { 0 };
CreateProcess(L"C:/Windows/System32/WSReset.exe", L"", NULL, NULL, FALSE, 0, NULL, NULL, &info, &processInfo);
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
//Enable redirection (important, otherwise program can crash)
Wow64RevertWow64FsRedirection(OldValue);
Related
I want to start "telnet" through cmd.exe and write the result of this command execution into file. When I run "ipconfig" command I get all information I need, but after running of "telnet" command I get just empty file.
Here is my code:
#include "windows.h"
#include "iostream"
void SaveResult(const wchar_t *fileName, const wchar_t *commandLine)
{
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
HANDLE h = CreateFile(fileName, FILE_WRITE_DATA, FILE_SHARE_WRITE | FILE_SHARE_READ,
&sa, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE)
return;
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { sizeof(si) };
si.dwFlags |= STARTF_USESTDHANDLES;
si.hStdInput = NULL;
si.hStdError = h;
si.hStdOutput = h;
wchar_t *writable_cmdline = _wcsdup(commandLine);
BOOL success = CreateProcess(NULL, writable_cmdline,
NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
bool finished = false;
//wait for 1 second
for (int i = 0; i < 10; i++)
{
if (WaitForSingleObject(pi.hProcess, 100) <= 0)
{
finished = true;
break;
}
}
if (success)
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
CloseHandle(h);
free(writable_cmdline);
if (!finished)
printf("Process didn't finish\n");
}
int main()
{
SaveResult(L"telnet.txt", L"C:\\windows\\system32\\cmd.exe /c telnet test.com");
SaveResult(L"ipconfig.txt", L"C:\\windows\\system32\\cmd.exe /c ipconfig");
return 0;
}
Have you run telnet command directly in cmd console? Is there anything output? if so, The empty file may because the buffer has not been refreshed to the file. As#David pointed out,
you just wait for 1s, but if there be more than 1s to connect, then you will close the handler without refresh the buffer. Try to add the FlushFileBuffers(h) before CloseHandle(h).
For WaitForSingleObject, you could try WaitForSingleObject(pi.hProcess, INFINITE), wait until the telnet process exit.
How can I create a process (a.exe) using CreateProcessWithLogonW that is realtime (note that I'm not an admin user but the one I'm using with CreateProcessWithLogonW is admin) and launch another process (b.exe) from a.exe using CreateProcess and have it realtime also?
Here is the code to launch a.exe:
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { 0 };
if (!CreateProcessWithLogonW(argv[1], argv[2], argv[3], LOGON_NETCREDENTIALS_ONLY, NULL, _T("a.exe"),
REALTIME_PRIORITY_CLASS, NULL, NULL,
&si, &pi))
{
cout << "Error!!!!\n";
}
Here is the code to launch b.exe from a.exe:
SECURITY_ATTRIBUTES security_att;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&security_att, sizeof(security_att));
security_att.nLength = sizeof (SECURITY_ATTRIBUTES);
security_att.bInheritHandle = TRUE;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_NORMAL;
if(!CreateProcess(NULL, "b.exe", &security_att, &security_att, FALSE, REALTIME_PRIORITY_CLASS, NULL, NULL, &si, &pi))
{
cout << "Error!!!!\n";
}
Currently, a.exe will be realtime priority but b.exe is only high priority.
I want to show the stdout of commandline program in MFC edit control. So I start a worker thread by AfxBeginThread to update the UI by PostMessage (this part works great), and the worker thread communicates with the commandline child process by a pipe. But my worker thread cannot read anything from the pipe (ReadFile always return FALSE) and my worker cannot quit even if the child process quits. So please help me.
Here is my code.
create child process part:
BOOL CMFCApplication3Dlg::execCmd(LPCSTR pCmdArg)
{
//ASSERT(s_hCmdProcess == NULL);
if (s_hCmdProcess != NULL)
{
return FALSE;
}
STARTUPINFO si; // specifies startup parameters for child process.
ZeroMemory(&si, sizeof(STARTUPINFO));
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; // STARTF_USESTDHANDLES is Required.
si.hStdOutput = s_cmdout_ChildSide; // Requires STARTF_USESTDHANDLES in dwFlags.
si.hStdError = s_cmdout_ChildSide; // Requires STARTF_USESTDHANDLES in dwFlags.
// si.hStdInput remains null.
si.wShowWindow = SW_HIDE; // Prevents cmd window from flashing. Requires STARTF_USESHOWWINDOW in dwFlags.
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
// Create the child process.
BOOL result = CreateProcess(
NULL,
(LPSTR)pCmdArg, // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // TRUE=handles are inherited. Required.
CREATE_NEW_CONSOLE, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&si, // __in, STARTUPINFO pointer
&pi); // __out, receives PROCESS_INFORMATION
if (result)
{
s_hCmdProcess = pi.hProcess;
s_hCmdProcessThread = pi.hThread;
}
return result;
}
create pipe part:
LRESULT CMFCApplication3Dlg::createPipe()
{
ASSERT(s_cmdout_ChildSide == NULL && s_cmdout_MainSide == NULL);
if (s_cmdout_ChildSide != NULL || s_cmdout_MainSide != NULL) return FALSE;
SECURITY_ATTRIBUTES saAttr = { sizeof(SECURITY_ATTRIBUTES) };
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
return CreatePipe(&s_cmdout_MainSide, &s_cmdout_ChildSide, &saAttr, 0);
}
the worker thread part:
void CMFCApplication3Dlg::startWorkThread()
{
if (s_hThread == NULL)
{
if (s_hThreadEvent != NULL) CloseHandle(s_hThreadEvent);
s_hThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//s_hThread = AfxBeginThread(TestThreadProc, this);
s_hThread = AfxBeginThread(ReadCmdOutProc, this);
}
}
UINT ReadCmdOutProc(LPVOID pParam)
{
CWnd *hDlg = (CWnd *)pParam;
//start the child process
BOOL result = CMFCApplication3Dlg::execCmd("ping 127.0.0.1 -n 99");
ASSERT(CMFCApplication3Dlg::s_hCmdProcess != NULL);
for(;;)
{
DWORD dwRetVal_cmd;
//wait for child process quit.
dwRetVal_cmd = WaitForSingleObject(CMFCApplication3Dlg::s_hCmdProcess,100);
DWORD dwRead = 0;
CHAR chBuf[4096];
BOOL readResult = ReadFile(CMFCApplication3Dlg::s_cmdout_MainSide, chBuf, 4096, &dwRead, NULL);
if (readResult)
{
chBuf[dwRead] = 0;
TRACE("read: %s\n",chBuf);
CString* cmdread = new CString(chBuf, dwRead);
//send ui thread update message.
MsgWrapper::Post(hDlg, WM_APP + 11, (WPARAM)cmdread);
}
if (dwRetVal_cmd != WAIT_TIMEOUT)
{
TRACE("thread quit\n");
//release the resource
CMFCApplication3Dlg::releaseCmd();
GetExitCodeThread(CMFCApplication3Dlg::s_hThread, &dwExitCode);
AfxEndThread(dwExitCode);
CMFCApplication3Dlg::s_hThread = NULL;
break;
}
}
}
I need to run VsDevCmd.bat with parameters but, when I run this code, VsDevCmd.bat gets executed but no parameters get passed in.
The code is following :
SHELLEXECUTEINFO ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = NULL;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\Common7\\Tools\\VsDevCmd.bat";
ShExecInfo.lpParameters = "cl.exe /D_USRDLL /D_WINDLL C:\\MyDLL.cpp C:\\MyDLL.def /link /DLL /OUT:MyDLL.dll";
ShExecInfo.lpDirectory = "C:\\";
ShExecInfo.nShow = SW_MAXIMIZE;
ShExecInfo.hInstApp = NULL;
int nRet = (int) ShellExecuteEx(&ShExecInfo);
if (nRet >= 32)
{
DWORD dw = GetLastError();
char szMsg[250];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, dw, 0, szMsg, sizeof(szMsg), NULL);
MessageBox(hWnd, szMsg, "ERROR", MB_ICONEXCLAMATION | MB_OK);
}
WaitForSingleObject (ShExecInfo.hProcess, INFINITE);
If you want to compile a DLL from within your application and you're using Visual Studio why don't you execute devenv to build a solution file containing the DLL you want to build?
Have a look at the documentation of devenv.
So your code should look like this:
SHELLEXECUTEINFO ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = NULL;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = "devenv";
ShExecInfo.lpParameters = "/build yoursolution.sln";
ShExecInfo.lpDirectory = "C:\\";
ShExecInfo.nShow = SW_MAXIMIZE;
ShExecInfo.hInstApp = NULL;
if (ShellExecuteEx(&ShExecInfo) != FALSE)
{
WaitForSingleObject (ShExecInfo.hProcess, INFINITE);
DWORD exitCode;
if (GetExitCodeProcess(ShExecInfo.hProcess, &exitCode) != FALSE)
{
/*
** Process exit code of devenv
** I haven't found something on the internet but I assume that exitCode=0 means success!
*/
if (exitCode != 0)
{
MessageBox(hWnd, "devenv failed!", "ERROR", MB_ICONEXCLAMATION | MB_OK);
}
}
else
{
DWORD dw = GetLastError();
char szMsg[250];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, dw, 0, szMsg, sizeof(szMsg), NULL);
MessageBox(hWnd, szMsg, "ERROR", MB_ICONEXCLAMATION | MB_OK);
}
CloseHandle(ShExecInfo.hProcess);
}
else
{
DWORD dw = GetLastError();
char szMsg[250];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, dw, 0, szMsg, sizeof(szMsg), NULL);
MessageBox(hWnd, szMsg, "ERROR", MB_ICONEXCLAMATION | MB_OK);
}
I am seeking example code:
For a service calls CreateProcessAsUser() I want the process to run in the user's session, not session 0
thus far the created process is only running like a service in session 0
This was stripped from some old code that launched a console app from a service. It worked under NT4 but I haven't tested it with a modern version of Windows so can't guarantee it will work as it did on NT4.
EDIT: No, that's not going to work as-is. You need to add the code found here to create a desktop, set the SID, etc.
if (!LogonUser(userId,
domain,
password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&hUserToken))
{
return GetLastError();
}
if (!ImpersonateLoggedOnUser(hUserToken))
{
DWORD rc = GetLastError();
CloseHandle(hUserToken);
return rc;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi));
si.cb = sizeof(si);
rc = CreateProcessAsUser(hUserToken, // user token
0, // app name
"foo.exe", // command line
0, // process attributes
0, // thread attributes
FALSE, // don't inherit handles
DETACHED_PROCESS, // flags
0, // environment block
0, // current dir
&si, // startup info
&pi); // process info gets put here
if (!rc)
{
DWORD rc = GetLastError();
RevertToSelf();
CloseHandle(hUserToken);
return rc;
}
RevertToSelf();
CloseHandle(hUserToken);
return 0;
I know this is an ancient post but I happen to be working on this so here's some code that works for me.
Determine the session ID of the currently logged-on user
DWORD GetCurrentSessionId ()
{
WTS_SESSION_INFO *pSessionInfo;
DWORD n_sessions = 0;
BOOL ok = WTSEnumerateSessions (WTS_CURRENT_SERVER, 0, 1, &pSessionInfo, &n_sessions);
if (!ok)
return 0;
DWORD SessionId = 0;
for (DWORD i = 0; i < n_sessions; ++i)
{
if (pSessionInfo [i].State == WTSActive)
{
SessionId = pSessionInfo [i].SessionId;
break;
}
}
WTSFreeMemory (pSessionInfo);
return SessionId;
}
Launch process as the currently logged-on user
bool LaunchProcess (const char *process_path)
{
DWORD SessionId = GetCurrentSessioId ();
if (SessionId == 0) // no-one logged in
return false;
HANDLE hToken;
BOOL ok = WTSQueryUserToken (SessionId, &hToken);
if (!ok)
return false;
void *environment = NULL;
ok = CreateEnvironmentBlock (&environment, hToken, TRUE);
if (!ok)
{
CloseHandle (hToken);
return false;
}
STARTUPINFO si = { sizeof (si) } ;
PROCESS_INFORMATION pi = { } ;
si.lpDesktop = "winsta0\\default";
// Do NOT want to inherit handles here
DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT;
ok = CreateProcessAsUser (hToken, process_path, NULL, NULL, NULL, FALSE,
dwCreationFlags, environment, NULL, &si, &pi);
DestroyEnvironmentBlock (environment);
CloseHandle (hToken);
if (!ok)
return false;
CloseHandle (pi.hThread);
CloseHandle (pi.hProcess);
return true;
}