Закрытие навязчивых окон 1С

Программа для закрытия навязчивых окон в 1С и других приложениях. Использую ее, т.к. часто в копиях баз, предоставляемых клиентом при работе возникают навязчивые сообщения, на закрытие которых тратится драгоценное время.


Клиенты часто предоставляют мне копии своих баз. В последнее время 1С стало выдавать много навязчивых оповещений, которые мешают мне, как разработчику. Я трачу своё время на закрытие этих ненужных мне оповещений.

Вот примеры таких оповещений:

Приходится снимать галочку «Показывать при начале работы».
Это сообщение вообще не отключается.

Чтобы решить проблему раз и навсегда, я заказал программисту небольшую программку на Си, которая закрывает окна по их заголовку.

Как использовать программу

Программа называется kwnd.exe.

Заголовки окон нужно написать в файле kwnd без расширения и разместить в одной папке с kwnd.exe. Каждый заголовок должен быть с новой строки.

Для приведенных выше навязчивых окон 1С файл заголовков окон kwnd выглядит так:

Информация - Бухгалтерия предприятия, редакция 3.0
Рекомендуется обновить версию конфигурации

Программа консольная, не имеет графического интерфейса.

Программа работает в бесконечном цикле, но не завершается, проверяет список окон по таймеру. Если указать при запуске kwnd.exe числовой параметр, то очередь будет опрашиваться раз в указанное количество секунд.

Пример для запуска проверки очереди раз в секунду:

kwnd.exe 1 

Второй экземпляр kwnd.exe не запускается, программа выдает предупреждение, что она уже запущена. Снять программу можно через диспетчер задач:

Программа не нагружает процессор, несмотря на то, что постоянно проверяет список окон.

Для автозапуска программы используйте команду shell:startup или shell:common startup для открытия папки автозапуска текущего или всех пользователей.

В папке разместите ярлык на программу:

После этого можно забыть о навязчивых сообщениях.

У некоторых пользователей были проблемы с работой программы, т.к. они прописывали запуск из планировщика и, возможно, программа запускалась от имени администратора, а не текущего пользователя, поэтому лучше прописывать ярлык в папку автозапуска.

Как определить заголовок программы

Обычно нет проблем визуально определить заголовок окна. Но иногда нужно получить точное название.

Для точного определения заголовка я использую Au3Info.exe от программы AutoIt.

Ее можно получить после установки AutoIT. Или скачать отдельно, она работает и отдельно от пакета AutoIt.

Также можно использовать AU3_Spy из пакета AutoHotKey и множество других подобных программ.

Получить программу

Исходный код программы:

#pragma hdrstop
#pragma argsused
 
#ifdef _WIN32
#include <tchar.h>
#else
  typedef char _TCHAR;
  #define _tmain main
#endif
 
#include <stdio.h>
#include <iostream>
#include <windows.h>
#include <ctime>
#include <tchar.h>
#include <string> // подключаем строки
#include <fstream> // подключаем файлы
 
 #define NAME_CONSOLE "myConsole"
 
using namespace std;
 
HWND hWnd;
HANDLE mutex;//Глобальный хендл мютекса
 
 int _tmain(int argc, _TCHAR* argv[])
{
 
 //При открытии программы пытаемся создать мютекс.
 //Мютекс - такой объект, который можно увидеть из любого приложения системы
   mutex=CreateMutex(NULL,true,"kWnd");
   DWORD result;
   result = WaitForSingleObject(mutex,0);//А теперь пытаемся его захватить себе
   //Если его захватить не получается, значит мютекс уже захватил кто-то другой
   if(result!=WAIT_OBJECT_0)
	 {
	  cout<<"the program is already running, and the second copy cannot be started"<<endl;
	  Sleep(5000);
	  exit(-1);
	 }
 
 
 FreeConsole();
 
 // переменная для сброса строки, прочитанной из файла.
 // Используется в ходе подсчета строк в файле, больше ни для чего не нужна
 string AS;
 
 // определим количество строк в файле в переменной i
  int i=1;
  ifstream file("kWnd");
  while (getline(file, AS))
  {
	i++;
  }
  if (i <= 0)
  {
	cout << "Файл пуст" << endl;
	return -1;
  }
 
 
 // Динамическое выделение памяти для массива s
  string *s;
  s=new string[i];
 // запишем все строки в массив, чтобы постоянно не ходить на диск
 // Заполнение массива s значениями строк из файла
  file.clear();
  file.seekg(0, std::ios::beg);
  for (int k = 1; k < i; k++)
  {
	getline(file, s[k]);
  }
 file.close(); // обязательно закрываем файл что бы не повредить его
 //   ...поехали ....
 char str[1024];
 while (1)
 {
	  for (int k = 1; k < i; k++)
	  {
		strcpy(str,s[k].c_str());
		hWnd = FindWindow(NULL, _T(str));
		 if(IsWindow(hWnd))
		  {
			SendMessage(hWnd,WM_SYSCOMMAND,SC_CLOSE,0);
		  }
	   }
   if (argc>0) Sleep(argc*1000);
 }
 
 //При выключении программы освобождаем мютекс, если он был у нас захвачен
 ReleaseMutex(mutex);
 //И удаляем его.
 CloseHandle(mutex);
 delete[] s;
 return 0;
}

комментариев 48

  1. bob:

    Да, время написания минут 5. Нафиг заказывать.
    Автор еще и С++ плохо знает и код не безопасен.

    • 5 минут, если постоянно пишешь на Си, не спорю.
      Поэтому я и заплатил не дорого программисту, который в теме.
      Чем не безопасен код? Посоветуй, поправим.

      • NorthWind:

        вместо strcpy лучше юзать strncpy, в противном случае появляется возможность набить в память процесса чего-нибудь вредоносного. В вашем случае это сделать довольно просто, потому что содержимое файла kwnd никак и ни на что не проверяется.

        • Да, ну тут пользователь сам себе буратино. Вряд ли пользователь будет составлять сам себе битый файл kwnd.
          😉
          Не, я не против улучшений, но перекомпилировать вряд ли буду. Код открыт — вперед!

      • NorthWind:

        и еще — у меня в win10 наклонный шрифт после заголовка «Закрытие навязчивых окон 1С» в начале страницы отображатется зябрами. Видимо, он какой-то нестандартный.

  2. Lolz:

    Оказыется, сережа не смекает, что сто лет в обед есть AutoHotKey. Гений my ass.

    https://www.autohotkey.com/docs/commands/WinClose.htm по кэпшену

  3. Fepafal:

    И ты, «программист» со стажем во много лет, заплатил деньги за это… Надеюсь, не очень много хотя бы. Хотя что это я, для фрилансера-вот-вот-миллионера нет такого понятия как «много».

    • Не вижу ничего плохого в делегировании программисту. Я за час получаю 1500, почему бы и не заказать что-то другому?

  4. naf2000:

    Почему не сделать расширением в 1с? Взял базу — установил расширение. Потом удалил.

    • Подумай сам почему?
      Видимо из-за экономии времени.
      Расширение ставить не надо, в автозагрузку один раз прописал и забыл.
      Автоматизация называется.

      • Я:

        База клиент сервер, пользователи подключаются к базе через вэб клиент, и тонкий клиент. Как будешь помогать своим коллегам ? Напрягать сис админа, писать скрипты для AD ? ну или сценарного исполнения в линуксовой среде ? ))))
        А, чисто для себя если, на своем ПК — то не вижу практического применения, ради чего ? ради того что бы закрыть окно столько кипеша ? Накидал расширение, при загрузки базы для каждого пользователя блокируется работа всех окон, и не важно, в каком видео работает клиент, через вэб, в тонком или толстом клиенте, да хоть с луны.

        • Тут такой момент, что окна эти платформенны.
          Не проверял, правда, попадают ли они в список ПолучитьОкна. Но думаю, вряд ли.
          Но если попадают, то да, можно закрывать и в расширении.

  5. хорошее дело! и статья грамотно написана. Всё четко и понятно.
    Молодец Фиксин!

  6. Виталий:

    А что нужно добавить для автонажатия ОК в предупреждении «Небезопасное открытие файла»?
    (Вылазит при обновлении из файла дополнительных обработок и, например, портативной ИРки ).
    Закладка для отслеживания новых комментов https://forum.mista.ru/topic.php?id=854603.

    • я думаю, такие окна не отлавливаются, тк у них нет заголовка. Но проверь через Au3info или другой инспектор окон.
      например, нет заголовка у окна, которое напоминает о бэкапе. поэтому его нельзя идентифицировать.

  7. Ёся:

    //При выключении программы освобождаем мютекс, если он был у нас захвачен
    ReleaseMutex(mutex);
    //И удаляем его.
    CloseHandle(mutex);
    delete[] s;
    return 0;

    вот эта часть кода когда выполняется?

  8. Спасибо, а то задолбало уже каждые 5 минут выскакивать в самый неподходящий момент!

  9. Денис:

    … в RemoteApp не закрывает окна((

  10. Morgen:

    Отличная программа.
    Даже и не знаю как раньше жил без нее.
    Эти окна 1С, особенно окна с рекламой, которая предлагает, что-то мне.
    Я и так уже купил 1С и ИТС, ещё и рекламу мне пихают

  11. Ктото Там:

    Хе Хе Хе я программку вашу все равно попробую но осадочек: Trojan.Malware.300983.susgen

    https://www.virustotal.com/gui/file/91db11f5dfe11e97894503d14d1000e8d5ec865bf2a2cbaa3f3530e4b6cb1488?nocache=1

    И вопрос касательно RemoteApp без вариантов?

    • сейчас модно неугодные программы маркировать как вирусы, как будто это защитит от вирусов.
      наоборот, это подрывает доверие к антивирусам.
      Но если что, у меня есть на страничке исходники этой программы, можете скомпилировать сами.

      Про Remote App не понял вопроса.

      • ryadovoi_zidiot:

        это не из-за неугодности, а потому что в программе потенциальная пропись в памяти

  12. Андрей:

    В текст добавил строку
    Проверка правомерности использования конфигурации

    Но это окно не закрывается …

    • проверьте текст заголовка утилитами autoit

      • Евгений:

        Такая же проблема, не закрывает этот тип окна. А как получить через autoit вообще не понятно( Сначала скачал exe файл, он либо вылетает с ошибкой, либо просит указать какой-то файл. Затем скачал установщик, установил, и тоже самое. Можете помочь с заголовком окна?

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

          Информация — Бухгалтерия предприятия, редакция 3.0
          Рекомендуется обновить версию конфигурации
          Проверка правомерности использования конфигурации
          Подключение Интернет-поддержки
          Информация

          • sema:

            убери (точнее введи ошибочный, например 1 / 1) в интернет-поддержке (зуп 3.1.26.13)

          • да, такой способ тоже есть.
            Но там надо кодом это делать. Ошибочный пароль не будет сохранен 1с.

  13. Влад:

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

    • Влад:

      Я понимаю что окна без заголовка отловить труднее, но может их по совокупности ключей можно будет идентифицировать: Class/Position/Style например. Все то, что показывает AutoIt_Info. Впрочем, учитывая что делал прогу не сам Гений, хотелки вряд-ли будут реализованы. В любом случае — спасибо за то, что поделилились. Даже с той функциональностью, что в программе заложена, она очень полезная.

      • да, дописать не могу. источник кода открытый, пишите. Можно нанять исполнителя на kwork, как это сделал я.

    • да, было бы неплохо, но как их идентифицировать.

  14. Евгений:

    Доброго дня! Мне удалось применить это решение в опубликованном приложении 1С (вариант терминала). Поэтому, с одной стороны, готов поделиться решением (если нужно), а с другой — просьба. Можно попросить пересобрать программу без задержки вывода (минимум), а лучше вообще без вывода сообщения о ранее запущенной копии? 🙂 (сам попробовал, но лет 10 не программил и сходу не получилось)

    • увы, приложение писал не я. Я заказывал фрилансеру под клиента. Так что пересобрать не смогу.
      Если решение есть, делитесь, внесу изменения в статью.

  15. Мазай:

    Странная реализация через постоянный скан. Почему не через хуки на открытие окон, это куда как менее затратно по ресурсам.

  16. Дмитрий:

    Спасибо автору!

  17. Александр:

    Благодарю автора!
    Приятная и полезная мелочь, которой от души безкорысно делится человек. Успехов.

  18. sawer:

    чат жипити накалякал скприпт на повершел. батник в автозагрузку ))

    # Заголовки окон, которые вы хотите закрыть
    $targetWindowTitles = @(«Заголовок_Окна_1», «Заголовок_Окна_2», «Заголовок_Окна_3»)

    while ($true) {
    foreach ($targetWindowTitle in $targetWindowTitles) {
    # Получение списка процессов по заголовку окна
    $targetProcesses = Get-Process | Where-Object { $_.MainWindowTitle -eq $targetWindowTitle }

    # Закрытие окон
    foreach ($process in $targetProcesses) {
    $process.CloseMainWindow()
    }

    Write-Host «Окна с заголовком ‘$targetWindowTitle’ были закрыты.»
    }

    # Задержка в 2 секунды
    Start-Sleep -Seconds 2
    }

Добавить комментарий для fixin Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *