Войти

Показать полную графическую версию : Получение PID процесса, запущенного из программы


Delirium
04-12-2009, 01:52
Имеется приложение на C#. В приложении есть опция - создать отчет. Отчет формируется в Excel.

//экземпляр Excel
oXL = new Excel.Application();
//экземпляр книги
oWB = (Excel._Workbook)(oXL.Workbooks.Add(Missing.Value));
//экземпляр листа
oSheet = (Excel._Worksheet)oWB.ActiveSheet;

и т.д. Т.е. все стандартно. Формирование отчета запускается в параллельном потоке, и после завершения формирования отчет выводится на экран (excel.Visible=true). Все работает, но иногда, крайне редко (например, отчет слишком большой, а пользователь закрыл программу и забыл что формировал его) в процессах остается экземпляр Excel.
Вот и подумал, может имеет смысл при закрытии программы проверять PID процессов Excel и закрывать их принудительно? В таком случае возникает проблема с уже запущенными клиентом копиями Excel.
Я думал взять список процессов Excel до запуска отчета и после
listBoxBefore.Text = System.Diagnostics.Process.GetProcessesByName("Excel")[0].Id.ToString();
listBoxAfter.Text = System.Diagnostics.Process.GetProcessesByName("Excel")[0].Id.ToString();
И при закрытии программы проверять, есть ли в списке новые PID. Но этот вариант мало подходит, т.к. пользователь мог во время работы программы сам запустить дополнительно Excel.
Может есть способ сразу при активации экземпляра Excel из программы, получать его PID? Чтобы быть уверенным на 100%, что закрывается нужное приложение.

Admiral
05-12-2009, 20:01
Delirium, когда в МультиБут понадобилось определить кто запускал консоль/GUI процесс, нашёл эту тему Как узнать имя процесса-родителя (http://forum.oszone.net/thread-134729.html), а там ссылку в посте под номер 4;)
Тем не менее, код, переписанный с Делфи на С, не добавил, так как представил, что помимо explorer.exe и cmd.exe, программу может запускать totalcmd.exe, far.exe и т.д., что делает данный подход не надёжным.
http://s55.radikal.ru/i148/0912/b8/b12174f23117x.jpg (http://s55.radikal.ru/i148/0912/b8/b12174f23117.png)
#define PSAPI_VERSION 1

#include <windows.h>
#include <stdio.h>
#include <Winternl.h>
#include <Psapi.h>

#pragma comment(lib, "Psapi.lib")

int WINAPI wWinMain (HINSTANCE hThisInst, HINSTANCE hPrevInst, LPWSTR lpszArgs, int nWinMode)
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId());
if(hProcess == INVALID_HANDLE_VALUE)
return -1;

HMODULE hNtDll = LoadLibrary(L"ntdll.dll");
if(hNtDll == NULL)
return -1;

typedef NTSTATUS (NTAPI *pfnNtQueryInformationProcess)(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL
);

pfnNtQueryInformationProcess gNtQueryInformationProcess = (pfnNtQueryInformationProcess)GetProcAddress(hNtDll, "NtQueryInformationProcess");
if(gNtQueryInformationProcess == NULL)
{
FreeLibrary(hNtDll);
return -1;
}

typedef struct _PROCESS_BASIC_INFORMATION {
NTSTATUS ExitStatus;
PPEB PebBaseAddress;
ULONG_PTR AffinityMask;
LONG BasePriority;
ULONG_PTR UniqueProcessId;
ULONG_PTR InheritedFromUniqueProcessId;
};
_PROCESS_BASIC_INFORMATION Info ={0};

gNtQueryInformationProcess(hProcess, ProcessBasicInformation, &Info, sizeof(Info), NULL);// == NO_ERROR)
CloseHandle(hProcess);

hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, (DWORD)Info.InheritedFromUniqueProcessId);
wchar_t szFileName[MAX_PATH] = L"";
GetModuleFileNameEx(hProcess, NULL, szFileName, MAX_PATH);
CloseHandle(hProcess);

MessageBox(NULL, szFileName, L"Hi", MB_ICONINFORMATION);

if(hNtDll != NULL)
FreeLibrary(hNtDll);

return 0;
}
На C# наверное можно перенести, а там и в Excel.
Не писал под .NET в Excel, так что не знаю нюансов, но разве при запуске второго экземпляра Excel не создаёт новой вкладке в своём окне? Или с рапортами выделяется отдельный поток и всё?

Delirium
07-12-2009, 02:17
разве при запуске второго экземпляра Excel не создаёт новой вкладке в своём окне »
Это зависит от настроек самого Excel. У меня всегда открывает новое окно при формировании запроса, тестировал на Excel 2003 и 2007 с разными настройками.




© OSzone.net 2001-2012