Доброго дня!



Предположим, что есть контрагент ООО "Сад и огород".

У этого контрагента есть 4 заказа в истории заказов со следующими продуктами в заказе.



Заказ №1 Яблоки, Груши, Картофель

Заказ №2 Сливы, Груши, Картофель

Заказ №3 Яблоки, Картофель, Сливы

Заказ №4 Груши, Картофель

В разделе "Заказы" создана деталь отображающая продукты в последнем заказе по данному контрагенту, т.е. в заказе №4 видны "продукты в заказе" заказа №3, в заказе №3 видны "продукты в заказе "заказа №2 и.т.д. Сейчас сформирован заказ №5 на Яблоки и Сливы.



А теперь сам вопрос: Есть ли возможность настроить фильтрацию (создать бизнес-процесс) для этой детали таким образом , чтобы в ней отображались предыдущие заказы только по продуктам в текущем заказе? Т.е. если в новом заказе "продукт в заказе" Яблоки и Сливы, то следовательно в детали должны отображаться последние заказы либо с Яблоками, либо со Сливами, либо с Яблоками и Сливами вместе.

 

Нравится

2 комментария

Попробуйте посмотреть в этой теме и сделать аналогично для своего кейса https://community.terrasoft.ru/articles/primery-filtrov-v-detali

Бизнес-процесс к фильтрации не относится.

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

Либо же разбираться с нестандартной фильтрацией на детали, как тут.

Показать все комментарии

Подскажите, пожалуйста, можно ли предзаполнять поле, в котором менеджеры расписывают сценарий звонка (в лиде, продаже). Скрин во вложении.

Прикрепленные файлы

Нравится

1 комментарий
Лучший ответ

1) Переопределить CallMessagePublisherPage.

2) в методе setDefaultValues добавить свой метод.

3) И в нем прописать что-то вроде this.$Body = "TESTETSTETDWUJ"

1) Переопределить CallMessagePublisherPage.

2) в методе setDefaultValues добавить свой метод.

3) И в нем прописать что-то вроде this.$Body = "TESTETSTETDWUJ"

Показать все комментарии

Помогите разобраться: имею список названий колонок схемы, нужно на уровне Entity их очистить, чтобы гарантировать, что они не будут видны не только в конкретной форме, но и нигде. Предположил, что можно пройтись по GetColumnValueNames(), но для колонок-справочников имена отличаются, типа <имя>Id (Я так понимаю, как в БД), <имя>Value (lookup value из связанной таблицы). Подскажите, как гарантировано и эффективно очистить колонки по имени? Насколько быстрым будет вариант через Entity - Schema - EntitySchemaColumn? Может ли помочь знание не только ColumnName, но и UId?

Нравится

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

Нужно просто настроить запрещающий доступ по колонкам.

Так же вы на уровне можете скрыть поле на уроне Entity (будет существовать в БД, невозможно будет создать колонку с таким же именем и тд), но тогда обращение к нему стандартными методами будет затруднено. Для этого необходимо изменить режим использования 

Запрещающий доступ не подходит, поскольку администрировать нужно по каждой записи отдельно. Сценарий - индивидуальный менеджер видит все по своему контрагенту, любой менеджер - только часть. Может, есть где-то нормальная документация по sdk с комментариями чуть полнее, чем Overloaded :) ?

Вопрос комбинации доступа по записям и полям обсуждался неоднократно, простого решения нет, только доработка.

 

Зверев Александр,

Так доработку мы и ведем, сейчас наткнулись на то, что вычитать "запрещенные" колонки можем, но скрыть их - нет, поскольку в схеме и сущности разные нотации, а гарантированно сопоставить одни с другими не можем.

Наличие и отсутствие Id для всех справочных колонок работает одинаково. Посмотрите у одной и для остальных сделайте так же.

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

Если у справочной колонки уже есть «Id» как часть названия, то в базе будет, соответственно, «IdId». Но лучше таких названий избегать.

Исправить первый пост не могу, там не <имя>Value, а <имя>Name, что впрочем не принципиально. Принципиально, что о гглупости, или незнанию, или умышленно созданная колонка ContactName не будет отличаться от Contact.Name, а потом такую ошибку черта лысого найдешь.

Посмотреть список полей можно в дизайнере объекта в конфигурации, а список колонок таблицы — подключившись к базе. Если есть риск, что пользователи по глупости, незнанию или злому умыслу создадут колонки с неподходящими именами — не давайте им прав администратора.

Спасибо, мы все это смотрели, но мы делаем более-менее generic решение, с тем, чтобы оно работало без дополнительных ограничений и не только в момент сдачи, поэтому варианты посмотреть, перечислить явно и т.п. никак не подходят. Нужна или аутентичная процедура получения одного из другого (или хотя бы документированное API, по которому не приходится догадываться, что имеется в виду), или официальній документ о требованиях к именованию, или (что хуже всего) авторитетное утверждение, что єти колонки каждій именует как Бог на душу положит и задача не решается в принципе.

Требования к именованию публиковались ещё во времена 3.Х.

Если Вы делаете универсальный механизм выдачи прав, можно делать подобно уже существующим: права для колонок хранятся в таблице SysEntitySchemaColumnRight. Там указывается не название, а именно Id колонки.

Мы так и делаем, правда там хранятся не Id, а UId, и я пытаюсь от имеющихся UId перейти к columnName, которые можно передать в Entity.SetColumnValue. Думал, что нашел, но см. первый пост этой ветки.

Поскольку на https://community.terrasoft.ru/questions/spisok-ne-administriruemyh-kol… никто не отвечает по сути вопроса, я просто пробую другой подход, основная часть задачи решена, а то, что казалось очевидным при беглом взгляде на имеющийся API, оказалось проблемой.

Обычно имена в базе и схеме совпадают, отличие только для справочных. Можно проверять, справочник ли это и затем добавлять или удалять «Id».

Также можно получить в виде JSON метаданные объекта и анализировать их: для каждой  справочной колонки там в соответствующих полях есть тройка названий: для поля-объекта, поля с Guid и поля для отображения. Например, "Type", "TypeId" и "TypeName".

Показать все комментарии

Сущности в системе идентифицируются Guid. который, будучи преобразованным в строку, имеет вид типа "846d8d33-004b-4a3e-b778-10cfd163f3bb" (буквы строчные, в таком виде он фигурирует, например, в параметрах запросов http)

С другой стороны в БД сущности хранятся с первичным ключем, построенным на id varchar2(38), но содержиное там заключено в фигурные скобки и буквы заглавные.

Есть ли стандартная функция преобразования одного в другое? В запрос нужно передать Id текущего контакта, но "{"+UserConnection.CurrentUser.ContactId.ToUpper()+"}" выглядит достаточно неуклюже.

Нравится

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

Могу предложить "элегантный костыль":

string contact = "846d8d33-004b-4a3e-b778-10cfd163f3bb";

string result = String.Join(String.Empty, "{", contact.ToUpper(), "}");

Если используете механизмы EntityShchemaQuery или Select/Insert/Update/Delete, то ничего преобразовывать не нужно, в функции передаётся переменная типа Guid и при генерации SQL в нужном формате подставится само. Если же самостоятельно создаёте SQL, воспользуйтесь своим кодом или советом выше.

Эелегантность костыля в виде сокращения записи обращения к переменной иррелевантна задаче :)

Меня больше интересовал источник подобных сложностей, почему сразу было не привести к одному формату? Ведь была ж какая-то причина?

Причина в том, что основная поддерживаемая база  — MS SQL, где есть тип «uniqueidentifier» и база поймёт вставку в любом формате. А поддержка Oracle добавлена опционально.

В этом и была суть вопроса: если в Oracle используется просто текст, какая разница, что туда писать? Зачем эти скобочки? Чтобы что-то в базе посмотреть, скопировать Id из URL не получится, это минус. Как и при склеивании ESQ и Select. А плюсы вообще есть?

Этот текст, хоть и не является отдельным типом «uniqueidentifier», но служит в качестве первичного или внешнего ключа. Соответственно, если писать в двух полях один GUID разным способом, связи между ними не получится.

Зверев Александр,

В каких 2-х полях??? Почему не писать ОДНИМ способом, в нижнем регистре и без скобок? Везде.

В версии для MS SQL пишите как вам нужно, а в Oracle — именно требуемым способом.

Зверев Александр,

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

Дмитрий, оно и приведено к единому знаменателю — с фигурными скобками в верхнем регистре. Нет смысла в версиях с 3.0 по 7.13 использовать один формат, а потом внезапно менять просто потому, что не нравятся скобки.

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

При обычной работе с форматом написания не сталкиваются никак, все C#-классы принимают значения типа Guid и преобразуют в нужный формат при генерации SQL автоматически. В чём именно негативное влияние фигурных скобок, Вы так и не объяснили. 

Вероятно, первоисточник именно такого написания — стандартная функция CreateGuid в Delphi, на котором была написана система Terrasoft 3.X. Она генерирует именно в таком формате. И в таблицу базы Firebird и Oracle, где нет встроенных типов для хранения GUID, так и записывали.

В Microsoft для C# рекомендуют для получения нужного формата использовать для переменной типа Guid метод ToString("N") в сочетании с String.ToUpper.

Показать все комментарии

Хочу отловить двойной клик по записи в разделе.

Зачем - раздел отформатирован специальным образом (стилями) и кнопки туда добавлять нельзя, а действие сделать нужно.

Вопрос как?

Нравится

3 комментария
Лучший ответ

Добрый день. В 7.13 или 7.13.1 это есть уже в коробке. Можете посмотреть, как реализовано там. Работает и в разделах, и в деталях.

 

Проверьте метод onGridDoubleClick, возможно это то, что вам нужно

Пример работы с этим методом есть на детали «Пользователи» раздела «Организационные роли». По двойному клику открывается карточка пользователя. Логика реализована в схеме UsersDetailV2.

Добрый день. В 7.13 или 7.13.1 это есть уже в коробке. Можете посмотреть, как реализовано там. Работает и в разделах, и в деталях.

 

Показать все комментарии

Простой и в то же время распространенный вопрос: как узнать разницу между временем на у клиента и на сервере. К примеру: передаем из клиента на сервер датувремя для сравнения, из сервера возвращает какой то результат. Разница составляет 2 или 3 часа, вопрос, как получить значение на которое нужно увеличивать(уменшать) дату от клиента

Нравится

2 комментария
Лучший ответ

Посмотрите в конфигурации реализацию TimezoneService и TimezoneHelper.

Посмотрите в конфигурации реализацию TimezoneService и TimezoneHelper.

Добрый день. Если речь идет именно о сравнении, то дату и время лучше сравнивать в UTC.

Показать все комментарии

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

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

1. Передать список нужных Id в бизнес-процесс, открыть из этого процесса преднастроенную страницу с выбором параметров, и произвести запись. Здесь проблема в том, как передать этот список Id в БП. Их можно сериализовать в строку, но строка большой длины не передастся в качестве параметра, во всяком случае вызов:

ProcessModuleUtilities.executeProcess(processArgs)

выдает ошибку при передаче длинной строки. А количество Id у меня может достигать нескольких тысяч.

2. Сделать insert нужных мне данных прямо из раздела. Но для этого мне всё равно нужно открыть преднастроенную страницу и получить от неё нужные параметры.

Подскажите, пожалуйста, есть ли какое-нибудь решение моей задачи?

Нравится

4 комментария
Лучший ответ

Добрый день Иван.



Я бы тогда создал Временную таблицу и туда бы с помощью Insert "Terrasoft.BatchQuery" поклал на стороне JavaScript все выбранные ID записи. И далее бы вызвал БП. Но скорее всего если записей много то это скорее приведет к долгому ожиданию

Второй способ по которому бы я пошел это перехватил бы и выгрузил в TXT SQL запрос что система генерирует, где результат запроса это выбранные ID записи. И данный запрос передал бы уже на C# сторону и там бы его уже выполнил и далее обработал бы. я бы пошел по 2 пути.

Вы можете получив список ID, вызвать мини-карточку(предварительно создав), там предоставьте выбор параметров, а при сохранении уже по данным параметрам делайте вставку в БД ранее полученных записей.

Добрый день Иван.



Я бы тогда создал Временную таблицу и туда бы с помощью Insert "Terrasoft.BatchQuery" поклал на стороне JavaScript все выбранные ID записи. И далее бы вызвал БП. Но скорее всего если записей много то это скорее приведет к долгому ожиданию

Второй способ по которому бы я пошел это перехватил бы и выгрузил в TXT SQL запрос что система генерирует, где результат запроса это выбранные ID записи. И данный запрос передал бы уже на C# сторону и там бы его уже выполнил и далее обработал бы. я бы пошел по 2 пути.

Власов Михаил Викторович,

Спасибо, Михаил! Я как раз пошел по первому из предложенных Вами вариантов, про второй я тоже думал, но не смог найти, как получить текст запроса из сформированного мной экземпляра esq. Если Вы знаете, и поделитесь этим знанием, я был бы очень признателен.

На сервере получить из ESQ запрос можно:

string esqSqlText = esqQuery.GetSelectQuery(UserConnection).GetSqlText(); 

По изначальному вопросу, можно ещё много разных подходов:

  • Записывать все данные в хранилище и передавать ключ.
  • Сделать не временную, а обычную таблицу и к ней схему в конфигурации. Писать в одно поле ключи интересующих записей, а в другое — одинаковый для всех Id, который и передать в процесс, а потом по нему фильтровать. Когда станут не нужны — по нему же фильтровать и в запросе удаления.
Показать все комментарии
Вопрос

Добрый день!

в BPM есть возможность экспортировать графики в Power Point?

Заранее благодарю.

Нравится

3 комментария
Лучший ответ

Nurlan ZH,

Вашу задачу можно решить но для этого потребуется немного доработать и использовать сторонние библиотеки чтобы это все сохранить в PowerPoint. Я на подобия такой задачи делал, только в моей задачи по определенному времени БП формировал все дашбоарды на Определенный момент времени и сохранял их на HTML страницы в виде отчета, чтобы потом отправить клиентам. 

Но еще раз повторюсь чтобы вы не выбрали, это все ровно доработка, стандартных способов в BPM'Online пока нет для решения такой задачи.

В разделе можно выгружать в виде картинки формата PNG при помощи пункта меню «Скриншот» в меню действий итогов по шестерёнке. Затем её можно вставить в презентацию. Выглядит примерно так:

Жалько. Спасибо за ответ.

Nurlan ZH,

Вашу задачу можно решить но для этого потребуется немного доработать и использовать сторонние библиотеки чтобы это все сохранить в PowerPoint. Я на подобия такой задачи делал, только в моей задачи по определенному времени БП формировал все дашбоарды на Определенный момент времени и сохранял их на HTML страницы в виде отчета, чтобы потом отправить клиентам. 

Но еще раз повторюсь чтобы вы не выбрали, это все ровно доработка, стандартных способов в BPM'Online пока нет для решения такой задачи.

Показать все комментарии

Добрый день,

 

Столкнулся с проблемой фильтрации справочных полей при помощи бизнес правил,

есть Справочник улиц (Street) у которого соответственно есть принадлежность к выше стоящим элементам(Городам, Районам, Регионам и др.) 

Выглядит примерно следующим образом

╔══════════════╤═════════════════════╤══════════════════════════════════════╤══════════════════════════════════════╤══════════════════════════════════════╤══════════════════════════════════════╗
║ Name         │ TerritorialObjectId │ LocalityId                           │ DistrictId                           │ RegionId                             │ CountryId                            ║
╠══════════════╪═════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╪══════════════════════════════════════╣
║ ул. Королёва │ NULL                │ NULL                                 │ NULL                                 │ B0FDED10-AEE0-4F1B-9C8D-198F7C154257 │ 5A1FEFDA-56A4-48A2-BC77-E40C71EEC73B ║
╟──────────────┼─────────────────────┼──────────────────────────────────────┼──────────────────────────────────────┼──────────────────────────────────────┼──────────────────────────────────────╢
║ ул. Ф.Торо   │ NULL                │ 967FC3D7-EBBA-4B76-AEDD-FE1CA5B48157 │ 7B11D4CE-D3E2-487F-BE03-A620015FB4FA │ EED82307-32D6-47EF-BDD8-FA64FE399614 │ 5A1FEFDA-56A4-48A2-BC77-E40C71EEC73B ║
╚══════════════╧═════════════════════╧══════════════════════════════════════╧══════════════════════════════════════╧══════════════════════════════════════╧══════════════════════════════════════╝

То есть в некоторых местах возможны пропуски иерархии, и улица напрямую принадлежит региону.

Бизнес правило по улице заполнено следующим образом

"Street": {
	"FiltrationStreetByTerritorialObject": {
		ruleType: BusinessRuleModule.enums.RuleType.FILTRATION,
		autocomplete: true,
		autoClean: true,
		baseAttributePatch: "TerritorialObject",
		comparisonType: Terrasoft.ComparisonType.EQUAL,
		type: BusinessRuleModule.enums.ValueType.ATTRIBUTE,
		attribute: "TerritorialObject"
	},
	"FiltrationStreetByLocality": {
		ruleType: BusinessRuleModule.enums.RuleType.FILTRATION,
		autocomplete: true,
		autoClean: true,
		baseAttributePatch: "Locality",
		comparisonType: Terrasoft.ComparisonType.EQUAL,
		type: BusinessRuleModule.enums.ValueType.ATTRIBUTE,
		attribute: "Locality"
	},
	"FiltrationStreetByDistrict": {
		ruleType: BusinessRuleModule.enums.RuleType.FILTRATION,
		autocomplete: true,
		autoClean: true,
		baseAttributePatch: "District",
		comparisonType: Terrasoft.ComparisonType.EQUAL,
		type: BusinessRuleModule.enums.ValueType.ATTRIBUTE,
		attribute: "District"
	},
	"FiltrationStreetByRegion": {
		ruleType: BusinessRuleModule.enums.RuleType.FILTRATION,
		autocomplete: true,
		autoClean: true,
		baseAttributePatch: "Region",
		comparisonType: Terrasoft.ComparisonType.EQUAL,
		type: BusinessRuleModule.enums.ValueType.ATTRIBUTE,
		attribute: "Region"
	},
	"FiltrationStreetByCountry": {
		ruleType: BusinessRuleModule.enums.RuleType.FILTRATION,
		autocomplete: true,
		autoClean: true,
		baseAttributePatch: "Country",
		comparisonType: Terrasoft.ComparisonType.EQUAL,
		type: BusinessRuleModule.enums.ValueType.ATTRIBUTE,
		attribute: "Country"
	}
}

Проблема в том, что при выборе улицы из справочника не подтягиваются автоматически ее выше стоящие элементы, как например город, район и т.д.

Я что то упускаю?

Нравится

4 комментария
Лучший ответ

Сериков Асхат Кайратович,

проблема в подтягивании автоматически ее "родителей", то есть при выборе улицы при незаполненных городах, районах не подтягиваются автоматически город и район к которым относится улица

Это решается также через другое свойство атрибута - dependencies.

Подробнее можно почитать здесь и посмотреть пример вот здесь.

Насколько мне известно, такой код работать не будет.

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

Алла Савельева,

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

autocomplete: true,

должен был выполнять

Сериков Асхат Кайратович,

проблема в подтягивании автоматически ее "родителей", то есть при выборе улицы при незаполненных городах, районах не подтягиваются автоматически город и район к которым относится улица

Это решается также через другое свойство атрибута - dependencies.

Подробнее можно почитать здесь и посмотреть пример вот здесь.

Алла Савельева,

Спасибо, так и делаю на данный момент, думал может я что то упустил поэтому не работает автоматическое заполнение

Показать все комментарии

Возникла проблема, нужно работать с файлом экселя, использую библиотеку Microsoft.Office.Interop.Excel, запихнул ее во внешние сборки, подключил в методах БПМ. и в задании сценарии на строке

Excel.Application xlApp = new Excel.Application();

выбивает ошибку:

System.IO.FileNotFoundException: Не удалось загрузить файл или сборку "office, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" либо одну из их зависимостей. Не удается найти указанный файл.

Имя файла: 'office, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c'

   в Terrasoft.Core.Process.WisCreateKPMethodsWrapper.ScriptTask1Execute(ProcessExecutingContext context)

   в Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

WRN: Assembly binding logging is turned OFF.

To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.

Note: There is some performance penalty associated with assembly bind failure logging.

To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].

 

Нравится

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

Приветствую

советую посмотреть и скачать на данном сайте библиотеки NetOffice https://osdn.net/projects/netoffice/ . Я сам с помощью данных библиотек не одну задачу решал. И вся документация понятна и есть Темплейты разобранные на Кейсах. Скачиваем, ставим библиотеки и пользуемся в своих проектах.

Вот ссылка на проект на ГитХабе https://github.com/NetOfficeFw/NetOffice

Установил вод, ошибка изменилась на следующую:

System.Runtime.InteropServices.COMException (0x800A03EC): Приложению Microsoft Excel не удается получить доступ к файлу "E:\BPMReport\636790185921323443.xlsx". Это может быть вызвано одной из следующих причин.

• Указан несуществующий файл или путь.

• Файл используется другой программой.

• Имя книги, которую вы пытаетесь сохранить, совпадает с именем другой книги, открытой в данный момент.

   в Microsoft.Office.Interop.Excel.Workbooks.Open(String Filename, Object UpdateLinks, Object ReadOnly, Object Format, Object Password, Object WriteResPassword, Object IgnoreReadOnlyRecommended, Object Origin, Object Delimiter, Object Editable, Object Notify, Object Converter, Object AddToMru, Object Local, Object CorruptLoad)

   в Terrasoft.Core.Process.WisCreateKPMethodsWrapper.ScriptTask1Execute(ProcessExecutingContext context)

   в Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

Файл существует, вот код:

var userConnection = Get&lt;UserConnection&gt;("UserConnection");
MemoryStream ms = new MemoryStream((
				new Select(userConnection).Top(1).Column("Data")
				.From("KnowledgeBaseFile")
				.Where("KnowledgeBaseId").IsEqual(Column.Parameter("302eeb80-7559-4fcd-8827-833d94fa78e6"))as Select).ExecuteScalar&lt;byte[]&gt;());
string FileName = "E:\\BPMReport\\" + DateTime.Now.Ticks.ToString() + ".xlsx";
            FileStream fs = new FileStream(FileName, FileMode.Create, FileAccess.Write);
            byte[] bytes = new byte[ms.Length];
            ms.Read(bytes, 0, (int)ms.Length);
            fs.Write(bytes, 0, bytes.Length);
            fs.Close();
 
object m = Type.Missing;
Application xlApp = new Application();

 

Радчук Виталий Владимирович,

А у IIS-пользователя есть доступ на запись в E:/BPMReport ??

может кто налетит на эту проблему, вот решение, должна быть папка 

C:\Windows\SysWOW64\config\systemprofile\Desktop

Показать все комментарии