|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » CMD/BAT - Слияние файлов |
|
CMD/BAT - Слияние файлов
|
Новый участник Сообщения: 5 |
Всем привет
Нужна помощь Предыстория
Издревле поигрываю (с женой) в игру SimCity. Очень полюбилась нам SimCity 4, но вот незадача-сетевого режима нет и в помине. Регион в игре сохраняется файлом региона+фалы городов. Решение было найдено.Города поделены на карте, файлы с помощью символьных ссылок доступны на ноутбуке. И играли бы мы себе в удовольствие, если бы не одно НО! Недавно нарвался на "новую" SimCity 2013(она же SimCity 5). Всё что было между этими версиями-ужас! А это версия вполне ничего.
И вот, было принято решение перейти на новенькое, естественно покупать игры никто не будет(политика партии не позволяет). На просторах интернета тут же был найден торрент с интересующим контентом, игра скачана и установлена. Радость была не долгой-игра заточена под сервера EA, в локальном режиме только одиночная игра. Но ничего, где наша не пропадала. Имея опыт с SimCity 4, началось (далее со слов жены) "шаманство". Процесс проходил не быстро, т.к. завал на работе+это все же игра, а не жизнь, НО спортивный интерес у русского человека не отнимешь. Как и в SimCity 4, в SimCity 2013 сохранения поделены-файл региона+файлы городов+МЕТАДАННЫЕ! Вот тут то и возникла загвоздка. Метаданные 2 типов. Метаданные для файла региона переписываются при сохранении. Метаданные для файла города пишутся постоянно(при открытом городе), что не позволяло на 2х пк одновременно зайти в игру("костыльный" сетевой режим с общим доступом к сохранениям). Метаданные для городов победил-на каждом пк данные пишутся в свои папки и при выходе из игры удаляются(да, всё гениальное просто), при повторном входе в игру данные перечитываются из файла сохранения города. В общем, работает. С метаданными для файла региона интереснее. При сохранении игры переписывается весь файл. Результат-на 2х пк открываем игру, открываем разные города, вносим изменения и сохраняем. Файлы городов сохраняются нормально, но метаданные для региона переписываются тем пк, который вышел последним, из-за этого сохранения первого сохранившегося затираются(именно в метаданных),и при повторном входе в игру, в город уже зайти не получается-несоответствие данных в файле городе и в метаданных региона. Разобрав метаданные региона, выявлены закономерности, в ручную вносятся правки и все работает. Ура! Я могу вручную подправить файл, а вот жена нет, поэтому хотелось бы автоматизировать процесс... в этом и вопрос(далее) Дано: 3 файла(сейвы от игры). 2 фала со входными данными, 3й файл-необходимый при слиянии первых двух. Входные данные отличаются несколькими параметрами. В выходном файле необходимо учесть разницу во входных данных. Во вложении прикреплены 2 входных файла(формат прикрепленных ".txt" пришлось дописать,изначально без расширения) Формат файла: (это формат сохранения города,параметр "uid" : 1026-этот параметр у каждого города свой) (Здесь и далее код,для удобства чтения, идет построчно, в оригинальном файле не построчно, смотрим во вложении: MetaData1 и Metadata2) Скрытый текст
{ "abandoned" : "false", "created" : "1539012933411", "description" : "", "id" : 19, "isClaimed" : "false", "isFriend" : "false", "isTutorial" : "false", "name" : "", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 0 }, "simoleons" : { "amount" : 0 }, "simoleonsForFrontEnd" : { "amount" : 50000 }, "total_Residential" : { "amount" : 0 } }, "status" : "ACTIVE", "ticks" : 0, "type" : "CITY", "uid" : 1026, "updated" : "1539012933411" }, При сохранении меняются следующие параметры: (остальные параметры неизменны) Скрытый текст
Задача №1: Сравнить 2 файла. При обнаружении различий, необходимо в конечный файл внести последние изменения. Опираться необходимо на параметр "ticks" (т.е. чем свежее данные, тем больше этот параметр). Пояснение
Сейв с пк№1 Скрытый текст
{ "abandoned" : "false", "created" : "1539012933411", "creator" : { "avatarImage" : "Razor1911.jpg", "canChat" : true, "cities_count" : 0, "id" : 1911777, "isOnline" : "false", "lastLogin" : 0, "nucleusId" : 1911777, "screenName" : "Razor1911", "tutorialState" : 1 }, "creatorId" : 1911777, "creatorName" : "Razor1911", "description" : "", "id" : 21, "isClaimed" : "true", "isFriend" : "false", "isTutorial" : "false", "name" : "Утесы Йоркшира", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 50 }, "simoleons" : { "amount" : 48803 }, "simoleonsForFrontEnd" : { "amount" : 50000 }, "total_Residential" : { "amount" : 0 } }, "status" : "ACTIVE", "ticks" : 5, "type" : "CITY", "uid" : 1028, "updated" : "1539013256205" }, Сейв с пк№2 Скрытый текст
{ "abandoned" : "false", "created" : "1539012933411", "creator" : { "avatarImage" : "Razor1911.jpg", "canChat" : true, "cities_count" : 0, "id" : 1911777, "isOnline" : "false", "lastLogin" : 0, "nucleusId" : 1911777, "screenName" : "Razor1911", "tutorialState" : 1 }, "creatorId" : 1911777, "creatorName" : "Razor1911", "description" : "", "id" : 21, "isClaimed" : "true", "isFriend" : "false", "isTutorial" : "false", "name" : "Утесы Йоркшира", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 74 }, "simoleons" : { "amount" : 58434 }, "simoleonsForFrontEnd" : { "amount" : 56768 }, "total_Residential" : { "amount" : 1806 } }, "status" : "ACTIVE", "ticks" : 9963, "type" : "CITY", "uid" : 1028, "updated" : "1539022788943" }, Сравниваем "ticks". На пк№2 "ticks" больше. Соответственно в конечный файл берем "блок" с пк№2 Скрытый текст
{ "abandoned" : "false", "created" : "1539012933411", "creator" : { "avatarImage" : "Razor1911.jpg", "canChat" : true, "cities_count" : 0, "id" : 1911777, "isOnline" : "false", "lastLogin" : 0, "nucleusId" : 1911777, "screenName" : "Razor1911", "tutorialState" : 1 }, "creatorId" : 1911777, "creatorName" : "Razor1911", "description" : "", "id" : 21, "isClaimed" : "true", "isFriend" : "false", "isTutorial" : "false", "name" : "Утесы Йоркшира", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 74 }, "simoleons" : { "amount" : 58434 }, "simoleonsForFrontEnd" : { "amount" : 56768 }, "total_Residential" : { "amount" : 1806 } }, "status" : "ACTIVE", "ticks" : 9963, "type" : "CITY", "uid" : 1028, "updated" : "1539022788943" }, Задача №2 В конце файла есть такой код Скрытый текст
"name" : "Родная Обитель", "privacySetting" : "", "sandbox" : false, "sdid" : "4697", "template" : { "boxes" : [], "height" : 4, "key" : "249", "localizedName" : "Gallia", "map" : {}, "name" : "Gallia", "postcard" : "http://s3.amazonaws.com/sc-euwest1-prod-global/images/region_templates/missing_region_template.png", "priority_order" : 8, "status" : "ACTIVE", "width" : 4 }, "ticks" : 1033, "updated" : "1539023602943" } Эти данные не относятся к сохранению города, эти данные каждый раз перезаписываются (метаданные региона). Логика перезаписывания отлична от вышеописанной. Здесь меняются 3 параметра - "sdid","ticks","updated". Изменения производятся как в большую, так и в меньшую сторону. Для выбора окончательных данных, необходим последний сохраненный файл(т.е. опираемся на дату создания/изменения файла сохранения-какой файл сохранен позже, с того и брать данные). В примере:MetaData1-время сохранения 09.10.18 в 0:33;MetaData2-время сохранения 09.10.18 в 0:19. В конечный файл взять данные из MetaData1 Скрытый текст
"name" : "Родная Обитель", "privacySetting" : "", "sandbox" : false, "sdid" : "4697", "template" : { "boxes" : [], "height" : 4, "key" : "249", "localizedName" : "Gallia", "map" : {}, "name" : "Gallia", "postcard" : "http://s3.amazonaws.com/sc-euwest1-prod-global/images/region_templates/missing_region_template.png", "priority_order" : 8, "status" : "ACTIVE", "width" : 4 }, "ticks" : 1033, "updated" : "1539023602943" } Конечный файл прикреплен как MetaData.txt (в оригинале MetaData) MetaData (построчно)
{ "boxId" : 18, "boxes" : [ { "abandoned" : "false", "created" : "1539012933411", "description" : "", "id" : 19, "isClaimed" : "false", "isFriend" : "false", "isTutorial" : "false", "name" : "", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 0 }, "simoleons" : { "amount" : 0 }, "simoleonsForFrontEnd" : { "amount" : 50000 }, "total_Residential" : { "amount" : 0 } }, "status" : "ACTIVE", "ticks" : 0, "type" : "CITY", "uid" : 1026, "updated" : "1539012933411" }, { "abandoned" : "false", "created" : "1539012933411", "description" : "", "id" : 20, "isClaimed" : "false", "isFriend" : "false", "isTutorial" : "false", "name" : "", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 0 }, "simoleons" : { "amount" : 0 }, "simoleonsForFrontEnd" : { "amount" : 50000 }, "total_Residential" : { "amount" : 0 } }, "status" : "ACTIVE", "ticks" : 0, "type" : "CITY", "uid" : 1027, "updated" : "1539012933411" }, { "abandoned" : "false", "created" : "1539012933411", "creator" : { "avatarImage" : "Razor1911.jpg", "canChat" : true, "cities_count" : 0, "id" : 1911777, "isOnline" : "false", "lastLogin" : 0, "nucleusId" : 1911777, "screenName" : "Razor1911", "tutorialState" : 1 }, "creatorId" : 1911777, "creatorName" : "Razor1911", "description" : "", "id" : 21, "isClaimed" : "true", "isFriend" : "false", "isTutorial" : "false", "name" : "Утесы Йоркшира", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 74 }, "simoleons" : { "amount" : 58434 }, "simoleonsForFrontEnd" : { "amount" : 56768 }, "total_Residential" : { "amount" : 1806 } }, "status" : "ACTIVE", "ticks" : 9963, "type" : "CITY", "uid" : 1028, "updated" : "1539022788943" }, { "abandoned" : "false", "created" : "1539012933411", "creator" : { "avatarImage" : "Razor1911.jpg", "canChat" : true, "cities_count" : 0, "id" : 1911777, "isOnline" : "false", "lastLogin" : 0, "nucleusId" : 1911777, "screenName" : "Razor1911", "tutorialState" : 1 }, "creatorId" : 1911777, "creatorName" : "Razor1911", "description" : "", "id" : 22, "isClaimed" : "true", "isFriend" : "false", "isTutorial" : "false", "name" : "Нью Йорк", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 69 }, "simoleons" : { "amount" : 87609 }, "simoleonsForFrontEnd" : { "amount" : 82784 }, "total_Residential" : { "amount" : 8250 } }, "status" : "ACTIVE", "ticks" : 15560, "type" : "CITY", "uid" : 1029, "updated" : "1539023602943" }, { "abandoned" : "false", "created" : "1539012933411", "description" : "", "id" : 23, "isClaimed" : "false", "isFriend" : "false", "isTutorial" : "false", "name" : "", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 0 }, "simoleons" : { "amount" : 0 }, "simoleonsForFrontEnd" : { "amount" : 50000 }, "total_Residential" : { "amount" : 0 } }, "status" : "ACTIVE", "ticks" : 0, "type" : "CITY", "uid" : 1030, "updated" : "1539012933411" }, { "abandoned" : "false", "created" : "1539012933411", "description" : "", "id" : 24, "isClaimed" : "false", "isFriend" : "false", "isTutorial" : "false", "name" : "", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 0 }, "simoleons" : { "amount" : 0 }, "simoleonsForFrontEnd" : { "amount" : 50000 }, "total_Residential" : { "amount" : 0 } }, "status" : "ACTIVE", "ticks" : 0, "type" : "CITY", "uid" : 1031, "updated" : "1539012933411" }, { "abandoned" : "false", "created" : "1539012933411", "description" : "", "id" : 25, "isClaimed" : "false", "isFriend" : "false", "isTutorial" : "false", "name" : "", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 0 }, "simoleons" : { "amount" : 0 }, "simoleonsForFrontEnd" : { "amount" : 50000 }, "total_Residential" : { "amount" : 0 } }, "status" : "ACTIVE", "ticks" : 0, "type" : "CITY", "uid" : 1032, "updated" : "1539012933411" }, { "abandoned" : "false", "created" : "1539012933411", "description" : "", "id" : 26, "isClaimed" : "false", "isFriend" : "false", "isTutorial" : "false", "name" : "", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 0 }, "simoleons" : { "amount" : 0 }, "simoleonsForFrontEnd" : { "amount" : 50000 }, "total_Residential" : { "amount" : 0 } }, "status" : "ACTIVE", "ticks" : 0, "type" : "CITY", "uid" : 1033, "updated" : "1539012933411" }, { "abandoned" : "false", "created" : "1539012933411", "description" : "", "id" : 27, "isClaimed" : "false", "isFriend" : "false", "isTutorial" : "false", "name" : "", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 0 }, "simoleons" : { "amount" : 0 }, "simoleonsForFrontEnd" : { "amount" : 50000 }, "total_Residential" : { "amount" : 0 } }, "status" : "ACTIVE", "ticks" : 0, "type" : "CITY", "uid" : 1034, "updated" : "1539012933411" }, { "abandoned" : "false", "created" : "1539012933411", "description" : "", "id" : 28, "isClaimed" : "false", "isFriend" : "false", "isTutorial" : "false", "name" : "", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 0 }, "simoleons" : { "amount" : 0 }, "simoleonsForFrontEnd" : { "amount" : 50000 }, "total_Residential" : { "amount" : 0 } }, "status" : "ACTIVE", "ticks" : 0, "type" : "CITY", "uid" : 1035, "updated" : "1539012933411" }, { "abandoned" : "false", "created" : "1539012933411", "description" : "", "id" : 29, "isClaimed" : "false", "isFriend" : "false", "isTutorial" : "false", "name" : "", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 0 }, "simoleons" : { "amount" : 0 }, "simoleonsForFrontEnd" : { "amount" : 50000 }, "total_Residential" : { "amount" : 0 } }, "status" : "ACTIVE", "ticks" : 0, "type" : "CITY", "uid" : 1036, "updated" : "1539012933411" }, { "abandoned" : "false", "created" : "1539012933411", "description" : "", "id" : 30, "isClaimed" : "false", "isFriend" : "false", "isTutorial" : "false", "name" : "", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 0 }, "simoleons" : { "amount" : 0 }, "simoleonsForFrontEnd" : { "amount" : 50000 }, "total_Residential" : { "amount" : 0 } }, "status" : "ACTIVE", "ticks" : 0, "type" : "CITY", "uid" : 1037, "updated" : "1539012933411" }, { "abandoned" : "false", "created" : "1539012933411", "description" : "", "id" : 31, "isClaimed" : "false", "isFriend" : "false", "isTutorial" : "false", "name" : "", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 0 }, "simoleons" : { "amount" : 0 }, "simoleonsForFrontEnd" : { "amount" : 50000 }, "total_Residential" : { "amount" : 0 } }, "status" : "ACTIVE", "ticks" : 0, "type" : "CITY", "uid" : 1038, "updated" : "1539012933411" }, { "abandoned" : "false", "created" : "1539012933411", "description" : "", "id" : 32, "isClaimed" : "false", "isFriend" : "false", "isTutorial" : "false", "name" : "", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 0 }, "simoleons" : { "amount" : 0 }, "simoleonsForFrontEnd" : { "amount" : 50000 }, "total_Residential" : { "amount" : 0 } }, "status" : "ACTIVE", "ticks" : 0, "type" : "CITY", "uid" : 1039, "updated" : "1539012933411" }, { "abandoned" : "false", "created" : "1539012933411", "description" : "", "id" : 33, "isClaimed" : "false", "isFriend" : "false", "isTutorial" : "false", "name" : "", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 0 }, "simoleons" : { "amount" : 0 }, "simoleonsForFrontEnd" : { "amount" : 50000 }, "total_Residential" : { "amount" : 0 } }, "status" : "ACTIVE", "ticks" : 0, "type" : "CITY", "uid" : 1040, "updated" : "1539012933411" }, { "abandoned" : "false", "created" : "1539012933411", "description" : "", "id" : 34, "isClaimed" : "false", "isFriend" : "false", "isTutorial" : "false", "name" : "", "offensive" : "false", "regionTemplateName" : "Gallia", "resources" : { "mayor_Rating" : { "amount" : 0 }, "simoleons" : { "amount" : 0 }, "simoleonsForFrontEnd" : { "amount" : 50000 }, "total_Residential" : { "amount" : 0 } }, "status" : "ACTIVE", "ticks" : 0, "type" : "CITY", "uid" : 1041, "updated" : "1539012933411" } ], "created" : "1539012933411", "creator" : { "avatarImage" : "Razor1911.jpg", "canChat" : true, "cities_count" : 0, "id" : 1911777, "isOnline" : "false", "lastLogin" : 0, "nucleusId" : 1911777, "screenName" : "Razor1911", "tutorialState" : 1 }, "creatorId" : 1911777, "creatorName" : "Razor1911", "description" : "", "id" : 1, "map" : { "cities" : [ { "uid" : "1026", "x" : -6064, "y" : 6336, "z" : -712 }, { "uid" : "1027", "x" : -2320, "y" : 5216, "z" : -838.299987792968750 }, { "uid" : "1028", "x" : -5904, "y" : 2880, "z" : -742.90002441406250 }, { "uid" : "1029", "x" : -3856, "y" : 312, "z" : -770.40002441406250 }, { "uid" : "1030", "x" : -3584, "y" : -2736, "z" : -711.09997558593750 }, { "uid" : "1031", "x" : -1008, "y" : -4368, "z" : -710.799987792968750 }, { "uid" : "1032", "x" : -6000, "y" : -4992, "z" : -759 }, { "uid" : "1033", "x" : -3040, "y" : -6656, "z" : -710.799987792968750 }, { "uid" : "1034", "x" : 2064, "y" : -6864, "z" : -855.09997558593750 }, { "uid" : "1035", "x" : 4960, "y" : -5776, "z" : -710.799987792968750 }, { "uid" : "1036", "x" : 1520, "y" : -4000, "z" : -832.59997558593750 }, { "uid" : "1037", "x" : 4320, "y" : -2416, "z" : -853.90002441406250 }, { "uid" : "1038", "x" : 3760, "y" : 960, "z" : -836.799987792968750 }, { "uid" : "1039", "x" : 5888, "y" : 3408, "z" : -764 }, { "uid" : "1040", "x" : 1744, "y" : 3328, "z" : -702.50 }, { "uid" : "1041", "x" : 3184, "y" : 6384, "z" : -800.299987792968750 } ], "greatWorks" : [ { "name" : "Region_GreatWorks_Empty", "x" : -928, "y" : 2565 }, { "name" : "Region_GreatWorks_Empty", "x" : -992, "y" : -1835 }, { "name" : "Region_GreatWorks_Empty", "x" : 7024, "y" : -1451 }, { "name" : "Region_GreatWorks_Empty", "x" : 6222.100097656250, "y" : 6711.899902343750 } ] }, "name" : "Родная Обитель", "privacySetting" : "", "sandbox" : false, "sdid" : "4697", "template" : { "boxes" : [], "height" : 4, "key" : "249", "localizedName" : "Gallia", "map" : {}, "name" : "Gallia", "postcard" : "http://s3.amazonaws.com/sc-euwest1-prod-global/images/region_templates/missing_region_template.png", "priority_order" : 8, "status" : "ACTIVE", "width" : 4 }, "ticks" : 1033, "updated" : "1539023602943" } Всем заранее спасибо P.S. очень желательно все в bat файле, т.к. есть ещё "немного" кода для всех остальных операций |
|
Отправлено: 11:12, 10-10-2018 |
Ветеран Сообщения: 27449
|
Профиль | Отправить PM | Цитировать Цитата _Stomatolog:
|
|
Отправлено: 18:13, 10-10-2018 | #2 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Пользователь Сообщения: 87
|
Профиль | Отправить PM | Цитировать Для манипуляции с json средствами cli существует JQ.
https://stedolan.github.io/jq/ https://stedolan.github.io/jq/manual/ Там всё достаточно просто. Но я почти не работал с json и к сожалению помочь не смогу. |
Отправлено: 22:50, 10-10-2018 | #3 |
Новый участник Сообщения: 5
|
Профиль | Отправить PM | Цитировать За наводку-спасибо большое.
На выходных поизучаю что-то новенькое для себя. О результатах отпишусь. |
Отправлено: 20:21, 11-10-2018 | #4 |
Пользователь Сообщения: 87
|
Профиль | Отправить PM | Цитировать Цитата _Stomatolog:
Просмоторщики и редакторы https://www.mitec.cz/jsonv.html http://tomeko.net/software/JSONedit/testing.php https://www.rj-texted.se/ Удобнее всего проверять результат онлайн парсерами: https://www.google.de/search?&q=json+parser+online Удачи. |
||
Отправлено: 18:52, 12-10-2018 | #5 |
Ветеран Сообщения: 27449
|
Профиль | Отправить PM | Цитировать Patroklos, если выше предложенное Вами средство нормальное — ему не понадобятся ни редакторы, ни парсеры
![]() |
Отправлено: 21:12, 12-10-2018 | #6 |
![]() |
Участник сейчас на форуме |
![]() |
Участник вне форума |
![]() |
Автор темы |
![]() |
Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
2010 - Слияние документов | suniavx | Microsoft Office (Word, Excel, Outlook и т.д.) | 2 | 27-09-2016 11:08 | |
CMD/BAT - Слияние txt и вывод всех файлов в Unicode | ask2886 | Скриптовые языки администрирования Windows | 12 | 24-02-2016 16:59 | |
CMD/BAT - Слияние файлов CSV | niko_dovgiy | Скриптовые языки администрирования Windows | 1 | 08-12-2015 21:37 | |
CMD/BAT - Слияние содержимого txt файлов в один. | rvm.luma | Скриптовые языки администрирования Windows | 4 | 07-09-2013 15:11 | |
Разное - Слияние в Excel | olenyka | Microsoft Office (Word, Excel, Outlook и т.д.) | 1 | 09-06-2010 13:45 |
|