1. Обязательно представиться на русском языке кириллицей (заполнить поле "Имя").
  2. Фиктивные имена мы не приветствуем. Ивановых и Пупкиных здесь уже достаточно.
  3. Не надо писать свой вопрос в первую попавшуюся тему - всегда лучше создать новую тему.
  4. За поиск, предложение и обсуждение пиратского ПО и средств взлома - бан без предупреждения. Непонятно? - Читать здесь.
  5. Рекламу и частные объявления "куплю/продам/есть халтура" мы не размещаем ни на каких условиях.
  6. Перед тем как что-то написать - читать здесь, а затем здесь и здесь.
  7. Не надо писать в ЛС администраторам свои технические вопросы. Администраторы форума отлично знают как работает форум, а не все-все контроллеры, о которых тут пишут.

Закрытие программы EPLAN

Сценарии / Модули API

Модератор: специалисты Eplan

Ответить

Автор темы
epic
здесь недавно
здесь недавно
Сообщения: 16
Зарегистрирован: 25 авг 2017, 23:17
Имя: Руслан
Благодарил (а): 7 раз

Закрытие программы EPLAN

Сообщение epic »

Здравствуйте!

Есть такой класс EplApplication, у которого есть метод Exit. С помощью него получаю результат такой, что закрываются открытые проекты. Закрытие проекта тоже устраивает, хотя цель закрыть сам Eplan.
Подскажите пожалуйста, на сколько это правильно так закрывать проекты? И безопасно ли это для БД проектов?
Аватара пользователя

Barmaley4
знаток Eplan
знаток Eplan
Сообщения: 58
Зарегистрирован: 30 окт 2018, 09:17
Имя: Павел
Страна: РФ
город/регион: Москва
Благодарил (а): 2 раза
Поблагодарили: 54 раза

Закрытие программы EPLAN

Сообщение Barmaley4 »

Вроде как EplApplication это класс для создания инстанса рантайма среды еплан (для выполнения операций с проектом без GUI еплана), и по идее метод Exit() закрывает рантайм в инстансе.
Если все проекты закрыты, то ничего страшного если применить немного варварства:

Код: Выделить всё

foreach (var process in Process.GetProcessesByName("EPLAN"))
{
    process.Kill();
}

wapdimon72ru
здесь недавно
здесь недавно
Сообщения: 19
Зарегистрирован: 11 апр 2019, 06:55
Имя: Марат
Благодарил (а): 1 раз
Поблагодарили: 1 раз

Закрыть EPLAN

Сообщение wapdimon72ru »

Данный метод конечно работает, но оставлю его использование на потом

Код: Выделить всё

foreach (var process in Process.GetProcessesByName("EPLAN"))
{
    process.Kill();
}
Так же можно закрыть его с помощью, тоже закроет, но этот вариант оставлю пока

Код: Выделить всё

Environment.Exit(0);
Меня интересует класс EplApplication , именно метод Exit
Вот такой вариант не закроет же сам еплан, потому что это новый экземляр класса,

Код: Выделить всё

EplApplication e = new EplApplication();
e.Exit();
а ссылку на текущее запущенное окно еплана не пойму где узнать

Вопрос: Как закрыть с помощью EplApplication или еще может какой метод есть сам Eplan, с примером в пару строк желательно бы...
Аватара пользователя

Barmaley4
знаток Eplan
знаток Eplan
Сообщения: 58
Зарегистрирован: 30 окт 2018, 09:17
Имя: Павел
Страна: РФ
город/регион: Москва
Благодарил (а): 2 раза
Поблагодарили: 54 раза

Закрыть EPLAN

Сообщение Barmaley4 »

Добрый день!

А почему необходимо использовать именно класс EplApplication? Это же не аналог ProjectManager'a для управления GUI, согласно описанию класс предназначен для:
EplApplication Class
This class allows you to use EPLAN functions in other processes.

То есть он для выполнения операций Eplan не из под родного GUI Eplan, а не для работы с запущеным приложением с ярлыка.

Для безопасного закрытия Eplan тогда уж проще использовать WinAPI и отправлять команду Alt+F4 в окно Eplan.

wapdimon72ru
здесь недавно
здесь недавно
Сообщения: 19
Зарегистрирован: 11 апр 2019, 06:55
Имя: Марат
Благодарил (а): 1 раз
Поблагодарили: 1 раз

Закрыть EPLAN

Сообщение wapdimon72ru »

EplApplication да это не то, немного почитал о нем.
Barmaley4 писал(а): 28 авг 2019, 09:10 Для безопасного закрытия Eplan тогда уж проще использовать WinAPI и отправлять команду Alt+F4 в окно Eplan.
Как это сделать ?
Или как закрыть с помощью ProjectManager'a , можете показать пару строк кода для примера?
Аватара пользователя

Barmaley4
знаток Eplan
знаток Eplan
Сообщения: 58
Зарегистрирован: 30 окт 2018, 09:17
Имя: Павел
Страна: РФ
город/регион: Москва
Благодарил (а): 2 раза
Поблагодарили: 54 раза

Закрыть EPLAN

Сообщение Barmaley4 »

Если не нужно переключать фокус окон, и главное окно Eplan по умолчанию в фокусе, то можно использовать пакет InputSimulator из NuGet менеджера, и выполнить отправку комбинации:

Код: Выделить всё

using WindowsInput;
using WindowsInput.Native;


            InputSimulator InpSim = new InputSimulator();
            InpSim.Keyboard.ModifiedKeyStroke(VirtualKeyCode.LMENU, VirtualKeyCode.F4);
Если же перефокусировка окна всё таки понадобится, то придётся подключить WinAPI:

Код: Выделить всё

	[DllImport("user32")]
        private static extern bool SetForegroundWindow(IntPtr hwnd);

        private void SetEplanWindow()
        {
            var proc = Process.GetProcessesByName("EPLAN").FirstOrDefault();
            if (proc != null && proc.MainWindowHandle != IntPtr.Zero)
                SetForegroundWindow(proc.MainWindowHandle);
        }

wapdimon72ru
здесь недавно
здесь недавно
Сообщения: 19
Зарегистрирован: 11 апр 2019, 06:55
Имя: Марат
Благодарил (а): 1 раз
Поблагодарили: 1 раз

Закрыть EPLAN

Сообщение wapdimon72ru »

Ага, спасибо за ответ. Но ваш способ не закроет еплан)) Конкретно в случае если из еплана, но нажатию кнопки была нарисована форма. Поможет решение если искать найти хэндл этого окна с помощью вин апи. Конкретный рабочий пример:

Код: Выделить всё

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

        static uint WM_CLOSE = 0x10;

        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        private static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);

        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        private static extern int GetWindowTextLength(IntPtr hWnd);

        [DllImport("user32.dll")]
        private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);

        // Delegate to filter which windows to include 
        public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);

        /// <summary> Получить текст для окна, на которое указывает hWnd </summary>
        public static string GetWindowText(IntPtr hWnd)
        {
            int size = GetWindowTextLength(hWnd);
            if (size > 0)
            {
                var builder = new StringBuilder(size + 1);
                GetWindowText(hWnd, builder, builder.Capacity);
                return builder.ToString();
            }

            return String.Empty;
        }

        /// <summary> Найти все окна, соответствующие заданному фильтру </summary>
        /// <param name="filter"> A delegate that returns true for windows
        ///    that should be returned and false for windows that should
        ///    not be returned </param>
        public static IEnumerable<IntPtr> FindWindows(EnumWindowsProc filter)
        {
            IntPtr found = IntPtr.Zero;
            List<IntPtr> windows = new List<IntPtr>();

            EnumWindows(delegate (IntPtr wnd, IntPtr param)
            {
                if (filter(wnd, param))
                {
                    // добавляют только те окна, которые подходят под фильтр - названия формы
                    windows.Add(wnd);
                }

                // but return true here so that we iterate all windows
                return true;
            }, IntPtr.Zero);

            return windows;
        }

        /// <summary> Поиск всех окон, содержащих данный текст заголовка </summary>
        /// <param name="titleText"> Текст, который должен содержать заголовок окна. </param>
        public static IEnumerable<IntPtr> FindWindowsWithText(string titleText)
        {
            return FindWindows(delegate (IntPtr wnd, IntPtr param)
            {
                return GetWindowText(wnd).Contains(titleText);
            });
        }

        [StructLayout(LayoutKind.Sequential)]
        struct LASTINPUTINFO
        {
            public static readonly int SizeOf = Marshal.SizeOf(typeof(LASTINPUTINFO));

            [MarshalAs(UnmanagedType.U4)]
            public UInt32 cbSize;
            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dwTime;
        }

        [DllImport("user32.dll")]
        static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

        static int GetLastInputTime()
        {
            int idleTime = 0;
            LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
            lastInputInfo.cbSize = (UInt32)Marshal.SizeOf(lastInputInfo);
            lastInputInfo.dwTime = 0;

            int envTicks = Environment.TickCount;

            if (GetLastInputInfo(ref lastInputInfo))
            {
                int lastInputTick = (Int32)lastInputInfo.dwTime;

                idleTime = envTicks - lastInputTick;
            }

            return ((idleTime > 0) ? (idleTime / 1000) : 0);
        }



И тогда вызвав

Код: Выделить всё

                                        IEnumerable<IntPtr> windows = FindWindowsWithText("EPLAN");
                                        foreach (IntPtr hndl in windows)
                                        {
                                            SendMessage(hndl, WM_CLOSE, new IntPtr(0), new IntPtr(0));
                                        }
в любом нужном месте, eplan закроется как будто на крестик нажали. Это вот точно сработает, в данный момент на этом решении остановился.

Надеюсь кому нибудь поможет данное решение, ибо я нормально времени на это потратил...
Аватара пользователя

Barmaley4
знаток Eplan
знаток Eplan
Сообщения: 58
Зарегистрирован: 30 окт 2018, 09:17
Имя: Павел
Страна: РФ
город/регион: Москва
Благодарил (а): 2 раза
Поблагодарили: 54 раза

Закрыть EPLAN

Сообщение Barmaley4 »

:thankyou: Сохраню , хорошо работает)
С отрисованой формой я вызывал с паузой комбинацию Alt+F4 пока еплан не закроется

kolbasist
здесь недавно
здесь недавно
Сообщения: 39
Зарегистрирован: 05 авг 2019, 15:51
Имя: Григорий Останин
Страна: Россия
город/регион: Санкт-Петербург
Благодарил (а): 10 раз
Поблагодарили: 4 раза

Закрытие программы EPLAN

Сообщение kolbasist »

У меня получилось закрывать через такую прокладку:

Код: Выделить всё

        public void StartDialogClosingTask()
        {
            Logger.SendMSGToEplanLog("[DialogWindowCloser] Starting dialog closing task.");

            Task.Run(() =>
            {
                try
                {
                    CloseDialogsUntilEditorIsActive();
                }
                catch (Exception ex)
                {
                    Logger.SendMSGToEplanLog($"[DialogWindowCloser] Exception in dialog closing task: {ex.Message}");
                }
            });
        }
Вот остальной код класса. Правда, я закрываю не главное окно, а диалоги открытые поверх главного окна, но думаю с главным окном тоже может получиться.

Код: Выделить всё

        // Импорт необходимых функций из user32.dll
        [DllImport("user32.dll")]
        private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);

        private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);

        [DllImport("user32.dll")]
        private static extern bool IsWindowVisible(IntPtr hWnd);

        [DllImport("user32.dll")]
        private static extern bool IsWindowEnabled(IntPtr hWnd);

        [DllImport("user32.dll")]
        private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);

        [DllImport("user32.dll")]
        private static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int maxLength);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        private const uint WM_CLOSE = 0x0010;

        [DllImport("user32.dll")]
        private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

        [StructLayout(LayoutKind.Sequential)]
        private struct INPUT
        {
            public uint type;
            public INPUTUNION u;
        }

        [StructLayout(LayoutKind.Explicit)]
        private struct INPUTUNION
        {
            [FieldOffset(0)] public MOUSEINPUT mi;
            [FieldOffset(0)] public KEYBDINPUT ki;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct KEYBDINPUT
        {
            public ushort wVk;
            public ushort wScan;
            public uint dwFlags;
            public uint time;
            public IntPtr dwExtraInfo;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct MOUSEINPUT
        {
            public int dx;
            public int dy;
            public uint mouseData;
            public uint dwFlags;
            public uint time;
            public IntPtr dwExtraInfo;
        }

        private const int INPUT_KEYBOARD = 1;
        private const uint KEYEVENTF_KEYUP = 0x0002;
        private const ushort VK_ESCAPE = 0x1B;
        private const uint WM_KEYDOWN = 0x0100;
        private const uint WM_KEYUP = 0x0101;
        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        public void CloseDialogsUntilEditorIsActive()
        {
            uint eplanProcessId = (uint)Process.GetCurrentProcess().Id;
            int maxAttempts = 10; // Максимальное количество попыток подряд
            int attempt = 0;

            // Определяем класс окна редактора
            const string editorWindowClass = "AfxMDIFrame140u";

            do
            {
                Logger.SendMSGToEplanLog($"[DialogWindowCloser] Attempt {attempt + 1} to close dialogs.");

                IntPtr activeWindowHandle = IntPtr.Zero;
                bool foundActiveWindow = false;
                bool editorWindowEnabled = false;

                // Перечисляем окна и обновляем состояние
                EnumWindows((hWnd, lParam) =>
                {
                    uint processId;
                    GetWindowThreadProcessId(hWnd, out processId);

                    if (processId == eplanProcessId)
                    {
                        bool isVisible = IsWindowVisible(hWnd);

                        // Игнорируем окна, у которых IsVisible = false
                        if (!isVisible)
                            return true;

                        bool isEnabled = IsWindowEnabled(hWnd);

                        StringBuilder className = new StringBuilder(256);
                        GetClassName(hWnd, className, className.Capacity);

                        // Получаем заголовок окна для логирования
                        StringBuilder windowText = new StringBuilder(256);
                        GetWindowText(hWnd, windowText, windowText.Capacity);

                        // Проверяем, является ли это окно редактором
                        if (className.ToString() == editorWindowClass)
                        {
                            editorWindowEnabled = isEnabled;
                            Logger.SendMSGToEplanLog($"[DialogWindowCloser] Editor window found. Enabled: {editorWindowEnabled}");
                            return true; // Продолжаем перечисление
                        }

                        // Если нашли активное диалоговое окно (класс #32770)
                        if (className.ToString() == "#32770" && isEnabled)
                        {
                            activeWindowHandle = hWnd;
                            foundActiveWindow = true;
                            Logger.SendMSGToEplanLog($"[DialogWindowCloser] Active dialog window to close: Handle: {hWnd}, Title: \"{windowText}\", Class: \"{className}\"");
                            return false; // Останавливаем перечисление
                        }
                    }
                    return true;
                }, IntPtr.Zero);

                // Проверяем состояние редактора перед закрытием окна
                if (editorWindowEnabled)
                {
                    Logger.SendMSGToEplanLog("[DialogWindowCloser] Editor window is active. Exiting loop.");
                    break;
                }

                if (!foundActiveWindow)
                {
                    // Если не найдено активных диалоговых окон
                    Logger.SendMSGToEplanLog("[DialogWindowCloser] No active dialog windows found. Exiting loop.");
                    break;
                }

                if (foundActiveWindow && activeWindowHandle != IntPtr.Zero)
                {
                    try
                    {
                        // Закрываем только активное окно
                        CloseWindow(activeWindowHandle);

                        // Добавляем задержку, чтобы окно успело закрыться
                        Thread.Sleep(500);

                        // Проверяем, исчезло ли окно после попытки закрытия
                        if (!IsWindowVisible(activeWindowHandle))
                        {
                            Logger.SendMSGToEplanLog($"[DialogWindowCloser] Successfully closed active dialog window.");
                            attempt = 0; // Обнуляем счётчик после успешного закрытия окна
                        }
                        else
                        {
                            Logger.SendMSGToEplanLog($"[DialogWindowCloser] Failed to close the window. It is still visible.");
                            attempt++;
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.SendMSGToEplanLog($"[DialogWindowCloser] Exception occurred while closing window: {ex.Message}");
                        attempt++;
                    }
                }

                // Проверяем, не достигли ли максимального количества попыток
                if (attempt >= maxAttempts)
                {
                    Logger.SendMSGToEplanLog("[DialogWindowCloser] Maximum number of attempts reached. Exiting loop to prevent possible infinite loop.");
                    break;
                }

                // Добавляем задержку между попытками
                Thread.Sleep(500);

            } while (true);
        }

        private void CloseWindow(IntPtr hWnd)
        {
            try
            {
                if (hWnd != IntPtr.Zero)
                {
                    // Устанавливаем фокус на окно
                    SetForegroundWindow(hWnd);

                    // Добавляем задержку для установки фокуса
                    Thread.Sleep(200);

                    // Попытка закрыть через WM_CLOSE
                    PostMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
                    Logger.SendMSGToEplanLog($"[DialogWindowCloser] Sent WM_CLOSE message to window: {GetWindowTitle(hWnd)}");

                    // Ждем и проверяем, закрылось ли окно
                    Thread.Sleep(1000);
                    if (!IsWindowVisible(hWnd))
                    {
                        Logger.SendMSGToEplanLog($"[DialogWindowCloser] Window successfully closed: {GetWindowTitle(hWnd)}");
                        return;
                    }

                    // Если окно все еще открыто, пытаемся через Escape
                    INPUT[] inputs = new INPUT[2];
                    inputs[0].type = INPUT_KEYBOARD;
                    inputs[0].u.ki.wVk = VK_ESCAPE;
                    inputs[0].u.ki.dwFlags = 0;

                    inputs[1].type = INPUT_KEYBOARD;
                    inputs[1].u.ki.wVk = VK_ESCAPE;
                    inputs[1].u.ki.dwFlags = KEYEVENTF_KEYUP;

                    SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));

                    Logger.SendMSGToEplanLog($"[DialogWindowCloser] Sent Escape to window: {GetWindowTitle(hWnd)}");
                }
            }
            catch (Exception ex)
            {
                Logger.SendMSGToEplanLog($"[DialogWindowCloser] Error closing window: {ex.Message}");
            }
        }

        private string GetWindowTitle(IntPtr hWnd)
        {
            StringBuilder windowText = new StringBuilder(256);
            GetWindowText(hWnd, windowText, windowText.Capacity);
            return windowText.ToString();
        }
    }
}
Ответить

Вернуться в «Eplan API»