-
Close a process
I'm trying to programatically close a process.
I know I can use TerminateProcess(), but I heard it's not a preferred method. I then however came across a method of terminating a process within Windows by using this command via command prompt or the Run dialog:
Code:
C:\Windows\System32\taskkill.exe -f -im explorer.exe
Using the same technique I came up with this code
Code:
ShellExecute(NULL, (LPCWSTR)"open", TEXT("C:\\Windows\\System32\\taskkill.exe"), TEXT("-f -im explorer.exe"), NULL, SW_SHOWNORMAL);
It compiles fine, but doesn't close the process. Any ideas what I'm doing wrong?
-
I'd use SendMessage(WM_CLOSE) or something like this to send close message to process. It would work like normal close, because when you click X, it sends this message.
-
Is this what you had in mind?
Code:
SendMessage((HWND)"C:\\Windows\\explorer.exe", WM_CLOSE, 0, 0);
This doesn't work either. I think I'm getting the process wrong though not sure :S.
Here is what I'm after, I want to close the explorer.exe shell on the current users profile, then open up a new shell as the local admin (I'm assuming I would use the shellexecute function to open it with run as parameters and then it would ask for the admin credentials before it executed.
After the shell executes, the user logged in as admin will be able to make any modifications\changes that they need to do, it would then terminate the the local admin shell (explorer.exe) and execute the users original shell (explorer.exe).
The sole purpose of this is when I remote into a user's pc to help them out at work, I'll be able to run this executable and do what I need to do and then easily revert back to their profile without worrying about having them log off\ log on. The users don't have proper permissions or credentials to make any modification (for obvious security reasons), but the IT dept could easily use a executable to perform the tasks they need within the users login without any fussing.
Hope that my logic makes sense. I've tested this out first hand, and it works, however it would be much more convenient being able to package this into a executable file that you can just double click on and it does the rest.
-
Get HWND by using HWND myHandle = FindWindow("...") , or by using PID = GetProcessId("explorer.exe"), and then HWN myHandle = OpenProcess(PID, ...)
Then you can send message with SendMessage(myHandle, ...)
Then call CloseHandle(myHandle);
-
Quote:
Originally Posted by
James
Code:
SendMessage((HWND)"C:\\Windows\\explorer.exe", WM_CLOSE, 0, 0);
HWND is a window handle,
How is a string (in this case it happens to be a path) ever a valid handle to a window?
ps:
C:\Windows\System32\taskkill.exe -f -im explorer.exe
Is basically the same as saying TerminateProcess,
but then you have a process (TaskKill.exe) do it for you.
-
Thanks for the help. I tried what you said razo, but it till didn't close out the process, I also tried some other code I found online and still nothing.
I can't really use sendmessage() with this method because I don't know the window for explorer.exe and I cant use findwindow() to find the window. Anywho, this is what I currently use and this doesn't work either argh.
Code:
int _tmain(int argc, char* argv[])//_TCHAR
{
PROCESSENTRY32 entry;
entry.dwFlags = sizeof( PROCESSENTRY32 );
HANDLE snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, NULL );
if(Process32First(snapshot, &entry ) == TRUE)
{
while(Process32Next(snapshot, &entry ) == TRUE)
{
if(stricmp((const char *)entry.szExeFile, "explorer.exe") == 0)
{
HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID );
//Terminate Process
TerminateProcess(hProcess, 0);
CloseHandle( hProcess );
}
}
}
CloseHandle( snapshot );
return 0;
}
-
Just a quick update, I accomplished the task a half-assed way, but it does everything I want it to do (so far). Here is the code so far:
Code:
// Admin.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
#include <cstdio>
#include <iostream>
void CloseExplorer()
{
char *cmd = "C:\\Windows\\System32\\taskkill.exe -f -im explorer.exe";
system(cmd);
}
void RunAsAdmin()
{
//First we need to run a Command Prompt Window as admin
char *cmd = "runas/user:admin cmd.exe";
char *cmd2 = "C:\\Windows\\explorer.exe";
system(cmd);
//Second we open up a new Explorer Window now
system(cmd2);
}
int _tmain(int argc, _TCHAR argv[])//
{
//Variables
//FindWindowEx(0&, lhwnd, "#32770", vbNullString)
// HWND msgbox = FindWindow(/*(LPCWSTR)L"#32770"*/NULL,(LPCWSTR)L"Information");
HWND msgbox = FindWindowEx(HWND_MESSAGE,NULL,(LPCWSTR)L"#32770",NULL);
//Hide Command Prompt Window
FreeConsole();
//Close the user's explorer window
CloseExplorer();
//Run a new Explorer.exe shell under admin
RunAsAdmin();
//Once we have the new explorer window open, we want to pause while we're logged in as this user.
MessageBox(0, (LPCWSTR)L"Running as Admin", (LPCWSTR)L"Information", MB_OK);
ShowWindow(msgbox,SW_FORCEMINIMIZE || SW_MINIMIZE || SW_HIDE || SW_SHOWMINNOACTIVE);
return 0;
}
What I'm trying to figure out now is figure out some way to trigger some event so that once the admin finishes doing what they need to do, they can quickly revert back to the users original explorer window. What I'm thinking of doing is putting up a message box and forcing it minimized (so that it's not an annoyance for the admin while they are performing "stuff" on the clients pc. Once they are complete, they click the button on the message box which will trigger the event to close off the explorer window they are logged in as and relaunch the users one.
I'm not sure if there is an effective way of doing it, maybe instead of a messagebox() I can redo everything using win32 API and draw a button say right above the taskbar. Anywho, right now the project is a console window (because it's simple and I don't need to go totally classy here. Anywho, maybe someone has some ideas or feedback.
BTW, for whatever reason, I can't figure out how to force minimize the messagebox. :(
-
Hmmm, I now rewrote it to a win32 API, but when I press the button, I don't get the messagebox(). Any ideas?
Code:
// Admin2.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "Admin2.h"
#define MAX_LOADSTRING 100
#define TOGGABLE_KEYS 10002
#define IDT_TIMER WM_USER + 200
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HWND hWnd = CreateWindow(WC_DIALOG,(LPCWSTR)L"", WS_VISIBLE|WS_OVERLAPPEDWINDOW, 400,100,100,80,NULL,NULL,NULL,NULL);
HWND static_label = CreateWindow((LPCWSTR)L"Static", (LPCWSTR)L"", WS_CHILD | WS_VISIBLE, 0, 0, 200, 25, hWnd,(HMENU)-1, NULL, NULL );
HWND myButton = CreateWindow((LPCWSTR)L"BUTTON", (LPCWSTR)L"OK", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 0, 0 , 105, 50, hWnd, (HMENU)ID_BUTTON1, NULL, NULL );
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
// UNREFERENCED_PARAMETER(hPrevInstance);
// UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
// LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_ADMIN2, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_ADMIN2));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ADMIN2));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_ADMIN2);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, SW_FORCEMINIMIZE);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_INITDIALOG:
//** Set timers
SetTimer(hWnd, TOGGABLE_KEYS, 1, NULL);
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case ID_BUTTON1:
{
MessageBox(0, (LPCWSTR)L"Testing...", (LPCWSTR)L"Information", MB_OK);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_TIMER:
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
-
Hmm, can you please tell me what's wrong with this:
Code:
char *cmd2 = "C:\\Windows\\explorer.exe";
char name[100];
char compName[100];
DWORD length=100;
GetComputerName((LPWSTR)name, &length);
compName == name;
sprintf_s(compName, "runas/user:%s\admin cmd.exe",name);
system(compName);
system(cmd2);
It compiles fine, but it doesn't load the admin profile properly hmmm.
-
might be just a syntax error, == is just a comparison and not an assigment which I think you want to do here
should be