AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 31.08.2016, 20:42   #1  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,952 / 3230 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
hwnd --> pid
Привет всем.

Есть метод
X++:
static container GetWindowThreadProcessId(HWND _hwnd)
{
    container   ret = [0.0];
    DLL         _DLL             = new DLL('USER32');
    DLLFunction dllFunction      = new DLLFunction(_DLL, 'GetWindowThreadProcessId');
    Binary      lpdwProcessId    = new Binary(#SizeOfInt);
    int         pid;
    ;
    dllFunction.returns(ExtTypes::DWord); // DWORD WINAPI
    dllFunction.arg(ExtTypes::DWord);     // _In_      HWND    hWnd,
    dllFunction.arg(ExtTypes::Pointer);   // _Out_opt_ LPDWORD lpdwProcessId

    pid = dllFunction.call(_hwnd, lpdwProcessId);
    if (pid)
    {
        ret = [pid, lpdwProcessId.dWord(0)];
    }
    return ret;
}
/*
[url]https://msdn.microsoft.com/en-us/library/windows/desktop/ms633522%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396[/url]

DWORD WINAPI GetWindowThreadProcessId(
  _In_      HWND    hWnd,
  _Out_opt_ LPDWORD lpdwProcessId
);

Parameters

hWnd [in]

    Type: HWND

    A handle to the window.
lpdwProcessId [out, optional]

    Type: LPDWORD

    A pointer to a variable that receives the process identifier. If this parameter is not NULL, GetWindowThreadProcessId copies the identifier of the process to the variable; otherwise, it does not.

Return value

Type:

Type: DWORD

The return value is the identifier of the thread that created the window.
*/


Он позволяет по hwnd окна определить pid.
Мы его используем для определения pid процесса excel c которым работаем через com или .net (com объект возвращает hwnd через который мы данным методом получаем pid). Соответственно если есть куча Excel то можно найти концы - понять какой com объект породил проблему и оставил зависший Excel после построения отчета.

Хочется переписать его на .Net
Может кто-нибудь подскажет как этот код переписать так, чтобы он работал на сервере?
Старый 31.08.2016, 22:03   #2  
Link is offline
Link
Британский учённый
Аватар для Link
Соотечественники
 
568 / 523 (19) +++++++
Регистрация: 25.11.2005
Адрес: UK
Записей в блоге: 9
Я бы попробовал через Process.GetProcessesByName. Excel не позволяет открывать два разных файла с одним именем, т.е. можно получить процесс по имени, а потом вызвать kill().
__________________
Людям физического труда для восстановления своих сил нужен 7-8 часовой ночной сон. Людям умственного труда нужно спать часов 9-10. Ну а программистов будить нельзя вообще.
За это сообщение автора поблагодарили: Logger (5).
Старый 31.08.2016, 23:49   #3  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,952 / 3230 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Я решаю другую проблему.
Моя задача не поубивать Excel не глядя.
А понять среди нескольких десятков зависших Excel-ей на сервере - каким кодом аксапты они порождены, чтобы этот кривой код вылечить (реально есть несколько сотен выгрузок в Excel - нужно понять какая гадит).

Пока хочется при создании SysExcel или ComExcelDocument_RU просто писать в лог стек вызовов и pid процесса excel. Ну и может еще какую полезную инфу. Тогда можно быстро находить проблемные места в коде и лечить их.
Старый 01.09.2016, 00:08   #4  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,952 / 3230 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от Link Посмотреть сообщение
Excel не позволяет открывать два разных файла с одним именем,
Позволяет если это разные экземпляры Excel
В моем случае это либо com объект Excel либо .Net обертка над Excel. Они приводят к созданию нового инстанса Excel. Но по достижению какого то числа Excel-ей (сколько то десятков) новые уже не создаются, а выскакивает ошибка. В общем идет "утечка" Excel-ей пока не затопит.

Последний раз редактировалось Logger; 01.09.2016 в 00:11.
Старый 01.09.2016, 07:36   #5  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Будет ли ваш HWND равен Process.MainWindowHandle ? Или если excel скажем скрыт (visible = false), то окна у процесса вообще не будет? Хотя если есть HWND, то должно быть и окно. Будет ли оно основным для процесса?

Если будет, то тогда можно перебрать все процессы и найти нужный. Или тот же самый отбор сделать через скрипт PowerShell (System.Management.Automation)
http://stackoverflow.com/questions/4...rom-com-object
Цитата:
(Get-Process -Name iexplore)| Where-Object {$_.MainWindowHandle -eq $ie.HWND}
За это сообщение автора поблагодарили: Logger (5).
Старый 01.09.2016, 11:35   #6  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,952 / 3230 (115) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Будет ли ваш HWND равен Process.MainWindowHandle ? Или если excel скажем скрыт (visible = false), то окна у процесса вообще не будет? Хотя если есть HWND, то должно быть и окно. Будет ли оно основным для процесса?

Если будет, то тогда можно перебрать все процессы и найти нужный. Или тот же самый отбор сделать через скрипт PowerShell (System.Management.Automation)
http://stackoverflow.com/questions/4...rom-com-object
Спасибо за идею.
Набросал джобик
X++:
static void _2(Args _args)
{
    SysExcelApplication     SysExcelApplication;
    hwnd            hwnd;
    System.Diagnostics.Process[]    pr;
    System.Diagnostics.Process      proc;
    int             pCount;
    int             i;
    str             toString;
    str             procName;
    int             id;
    System.IntPtr   mainWindowHandle;
    int             iMainWindowHandle;
    int64           i64MainWindowHandle;
    System.IntPtr   handle;
    int             iHandle;
    container getWindowThreadProcessId(HWND _hwnd)
    {
        #define.sizeOfInt(4)
        container   ret = [0, 0];
        DLL         _DLL             = new DLL('USER32');
        DLLFunction dllFunction      = new DLLFunction(_DLL, 'GetWindowThreadProcessId');
        Binary      lpdwProcessId    = new Binary(#SizeOfInt);
        int         pid;
        ;
        dllFunction.returns(ExtTypes::DWord); // DWORD WINAPI
        dllFunction.arg(ExtTypes::DWord);     // _In_      HWND    hWnd,
        dllFunction.arg(ExtTypes::Pointer);   // _Out_opt_ LPDWORD lpdwProcessId

        pid = dllFunction.call(_hwnd, lpdwProcessId);
        if (pid)
        {
            ret = [pid, lpdwProcessId.dWord(0)];
        }
        return ret;
    }
    ;

    //SysExcelApplication = SysExcelApplication_NET::construct();
    SysExcelApplication = SysExcelApplication::construct();


    hwnd = SysExcelApplication.HWND();

    info(strFMT("%1", hwnd));
    info(con2str(GetWindowThreadProcessId(hwnd)));

    pr = System.Diagnostics.Process::GetProcesses();
    pCount = pr.get_Length();
    for (i = 1; i < pCount; i++)
    {
        proc = pr.GetValue(i);

        toString = proc.ToString();
        procName = proc.get_ProcessName();
        id       = proc.get_Id();
        mainWindowHandle = proc.get_MainWindowHandle();
        iMainWindowHandle = mainWindowHandle.ToInt32();
        i64MainWindowHandle = mainWindowHandle.ToInt64();
        handle  = proc.get_Handle();
        iHandle = handle.ToInt32();

        info(con2str([
            id,
            imainWindowHandle,
            i64MainWindowHandle,
            ihandle,
            procName,
            toString
        ]));
    }

// [url]http://www.cyberforum.ru/csharp-beginners/thread4966.html[/url]
}
где SysExcelApplication.HWND();
это
X++:
//pkoz 31.08.2016
HWND HWND()
{
    return application.Hwnd();
}
В общем, вызов GetWindowThreadProcessId работает корректно даже при невидимом Excel. Возвращает контейнер где вторым параметром стоит pid

А цикл по System.Diagnostics.Process::GetProcesses() возвращает почти везде нулевой get_MainWindowHandle() что очень странно. Т.е. при использовании перебора всех System.Diagnostics.Process из под аксапты - не получается одновременно получить pid и hwnd и, соответственно, не получается связать их.

Последний раз редактировалось Logger; 01.09.2016 в 11:38.
Теги
com-объект, excel, excel com формат, hwnd, pid

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
AX2009 -> RU5 -> RU6 -> RU7 Pustik DAX: Прочие вопросы 8 21.05.2011 15:25
Dynamics AX Sustained Engineering: Sale Order Batch Invoicing reprints invoices from prior runs, when “Print” is set to ‘After’ on AR >> Periodic >> Sales Update >> Invoice form Blog bot DAX Blogs 0 24.03.2010 02:06
Журнал переноса->Строки->Поле "Количество" . Нужен "0" по умолчанию вместо ATimTim DAX: Функционал 5 26.06.2004 12:17
query->DataSource->grid ald DAX: Программирование 2 06.02.2004 09:24
Заказов -> Строки заказов -> Запросы -> Пункт "Производство" Андре DAX: Программирование 1 20.09.2002 10:43
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 02:51.