- Обязательно представиться на русском языке кириллицей (заполнить поле "Имя").
- Фиктивные имена мы не приветствуем. Ивановых и Пупкиных здесь уже достаточно.
- Не надо писать свой вопрос в первую попавшуюся тему - всегда лучше создать новую тему.
- За поиск, предложение и обсуждение пиратского ПО и средств взлома - бан без предупреждения. Непонятно? - Читать здесь.
- Рекламу и частные объявления "куплю/продам/есть халтура" мы не размещаем ни на каких условиях.
- Перед тем как что-то написать - читать здесь, а затем здесь и здесь.
- Не надо писать в ЛС администраторам свои технические вопросы. Администраторы форума отлично знают как работает форум, а не все-все контроллеры, о которых тут пишут.
Закрытие программы EPLAN
Модератор: специалисты Eplan
-
- здесь недавно
- Сообщения: 16
- Зарегистрирован: 25 авг 2017, 23:17
- Имя: Руслан
- Благодарил (а): 7 раз
Закрытие программы EPLAN
Здравствуйте!
Есть такой класс EplApplication, у которого есть метод Exit. С помощью него получаю результат такой, что закрываются открытые проекты. Закрытие проекта тоже устраивает, хотя цель закрыть сам Eplan.
Подскажите пожалуйста, на сколько это правильно так закрывать проекты? И безопасно ли это для БД проектов?
Есть такой класс EplApplication, у которого есть метод Exit. С помощью него получаю результат такой, что закрываются открытые проекты. Закрытие проекта тоже устраивает, хотя цель закрыть сам Eplan.
Подскажите пожалуйста, на сколько это правильно так закрывать проекты? И безопасно ли это для БД проектов?
-
- знаток Eplan
- Сообщения: 58
- Зарегистрирован: 30 окт 2018, 09:17
- Имя: Павел
- Страна: РФ
- город/регион: Москва
- Благодарил (а): 2 раза
- Поблагодарили: 54 раза
Закрытие программы EPLAN
Вроде как EplApplication это класс для создания инстанса рантайма среды еплан (для выполнения операций с проектом без GUI еплана), и по идее метод Exit() закрывает рантайм в инстансе.
Если все проекты закрыты, то ничего страшного если применить немного варварства:
Если все проекты закрыты, то ничего страшного если применить немного варварства:
Код: Выделить всё
foreach (var process in Process.GetProcessesByName("EPLAN"))
{
process.Kill();
}
-
- здесь недавно
- Сообщения: 19
- Зарегистрирован: 11 апр 2019, 06:55
- Имя: Марат
- Благодарил (а): 1 раз
- Поблагодарили: 1 раз
Закрыть EPLAN
Данный метод конечно работает, но оставлю его использование на потом
Так же можно закрыть его с помощью, тоже закроет, но этот вариант оставлю пока
Меня интересует класс EplApplication , именно метод Exit
Вот такой вариант не закроет же сам еплан, потому что это новый экземляр класса,
а ссылку на текущее запущенное окно еплана не пойму где узнать
Вопрос: Как закрыть с помощью EplApplication или еще может какой метод есть сам Eplan, с примером в пару строк желательно бы...
Код: Выделить всё
foreach (var process in Process.GetProcessesByName("EPLAN"))
{
process.Kill();
}
Код: Выделить всё
Environment.Exit(0);
Вот такой вариант не закроет же сам еплан, потому что это новый экземляр класса,
Код: Выделить всё
EplApplication e = new EplApplication();
e.Exit();
Вопрос: Как закрыть с помощью EplApplication или еще может какой метод есть сам Eplan, с примером в пару строк желательно бы...
-
- знаток Eplan
- Сообщения: 58
- Зарегистрирован: 30 окт 2018, 09:17
- Имя: Павел
- Страна: РФ
- город/регион: Москва
- Благодарил (а): 2 раза
- Поблагодарили: 54 раза
Закрыть EPLAN
Добрый день!
А почему необходимо использовать именно класс 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.
А почему необходимо использовать именно класс 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.
-
- здесь недавно
- Сообщения: 19
- Зарегистрирован: 11 апр 2019, 06:55
- Имя: Марат
- Благодарил (а): 1 раз
- Поблагодарили: 1 раз
Закрыть EPLAN
EplApplication да это не то, немного почитал о нем.
Или как закрыть с помощью ProjectManager'a , можете показать пару строк кода для примера?
Как это сделать ?
Или как закрыть с помощью ProjectManager'a , можете показать пару строк кода для примера?
-
- знаток Eplan
- Сообщения: 58
- Зарегистрирован: 30 окт 2018, 09:17
- Имя: Павел
- Страна: РФ
- город/регион: Москва
- Благодарил (а): 2 раза
- Поблагодарили: 54 раза
Закрыть EPLAN
Если не нужно переключать фокус окон, и главное окно Eplan по умолчанию в фокусе, то можно использовать пакет InputSimulator из NuGet менеджера, и выполнить отправку комбинации:
Если же перефокусировка окна всё таки понадобится, то придётся подключить WinAPI:
Код: Выделить всё
using WindowsInput;
using WindowsInput.Native;
InputSimulator InpSim = new InputSimulator();
InpSim.Keyboard.ModifiedKeyStroke(VirtualKeyCode.LMENU, VirtualKeyCode.F4);
Код: Выделить всё
[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);
}
-
- здесь недавно
- Сообщения: 19
- Зарегистрирован: 11 апр 2019, 06:55
- Имя: Марат
- Благодарил (а): 1 раз
- Поблагодарили: 1 раз
Закрыть EPLAN
Ага, спасибо за ответ. Но ваш способ не закроет еплан)) Конкретно в случае если из еплана, но нажатию кнопки была нарисована форма. Поможет решение если искать найти хэндл этого окна с помощью вин апи. Конкретный рабочий пример:
И тогда вызвав
в любом нужном месте, eplan закроется как будто на крестик нажали. Это вот точно сработает, в данный момент на этом решении остановился.
Надеюсь кому нибудь поможет данное решение, ибо я нормально времени на это потратил...
Код: Выделить всё
[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
- Сообщения: 58
- Зарегистрирован: 30 окт 2018, 09:17
- Имя: Павел
- Страна: РФ
- город/регион: Москва
- Благодарил (а): 2 раза
- Поблагодарили: 54 раза
Закрыть EPLAN
Сохраню , хорошо работает)
С отрисованой формой я вызывал с паузой комбинацию Alt+F4 пока еплан не закроется
С отрисованой формой я вызывал с паузой комбинацию Alt+F4 пока еплан не закроется
-
- здесь недавно
- Сообщения: 39
- Зарегистрирован: 05 авг 2019, 15:51
- Имя: Григорий Останин
- Страна: Россия
- город/регион: Санкт-Петербург
- Благодарил (а): 10 раз
- Поблагодарили: 2 раза
Закрытие программы EPLAN
У меня получилось закрывать через такую прокладку:
Вот остальной код класса. Правда, я закрываю не главное окно, а диалоги открытые поверх главного окна, но думаю с главным окном тоже может получиться.
Код: Выделить всё
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();
}
}
}