Страницы

Поиск по вопросам

Показаны сообщения с ярлыком config. Показать все сообщения
Показаны сообщения с ярлыком config. Показать все сообщения

воскресенье, 8 марта 2020 г.

Конфигурирование WCF-сервиса для передачи файлов, как и где это сделать?

#c_sharp #wcf #config #configuration


Пришлось впервые столкнуться с WCF, ибо есть задача - посредством WCF-службы отдавать
клиенту файлы по запросу клиента.

Предварительно была изучена теория, и выяснено, что файлы можно передавать:


Как есть, без предварительной настройки, разве что, выставив
maxMessageLengthи executionTimeoutInSeconds в довольно большие
значения.
Включить MTOM в качестве кодировщика.
Включить стриминг (потоковую передачу данных).


Точный размер передаваемых файлов я не знаю, но зато могу сказать, что на текущем
этапе вряд ли будут передаваться большущие файлы типа дампов БД или потокового видео. 
Но всё же, в стандартном подходе меня смущает то, что будет постоянная сериализация-десереализация
файлов в XML, а зачем лишние телодвижения?

Включение стриминга, в принципе, сейчас подходит, но, как говорит MSDN, будет ряд
ограничений (связаны с шифрованим и буферизацией, подробнее — в статье), из-за которых,
цитирую:


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


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

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

Итак, в качестве пути решения был выбран проект WCF Service Library, в котором был
объявлен интерфейс службы, примерно так:

[ServiceContract]
public interface IUpdaterService
{
    [OperationContract]
    bool TestConnection();
    ... 
    [OperationContract]
    FileStream DownloadFile(string filename);
    ...
}


Ага, тут я использую FileStream, значит нужно включить поддержку стриминга, но сложность
в том, что я попросту не знаю, где и как это сделать. То же самое и с включением MTOM.

Ну, например, в попавшихся мне решениях говорят, "измените конфиг так":




    
        
            
        
    
    
        
    





Вроде всё понятно, что менять и на что, но где это делать?

Напоминаю, у меня DLL, в которой есть лишь App.config, и он - следующий:






  


  
  


  
    
      
        
          
        
      
      
      
        
          
        
      
    
  
  
    
      
        
        
      
    
  





Т.е. по сути, в App.config нет, например, раздела bindings, где можно было бы изменить
эти параметры.
При запуске родного WCF Test Client метод DownloadFile не доступен, так как используется
тип FileStram, стало быть, протестировать его никак...

Конфиг клиента, в свою очередь, формируется такой, нужно, т.е. как раз с теми разделами,
которые можно менять:




    
        
            
        
    
    
        
    





Но опять же - возникает вопрос - а где и как менять этот конфиг? Уверен, он генерируется
автоматически, т.е. необходимо задать нужные параметры для моей DLL, но как верно это
сделать? К сожалению, ответа на этот вопрос пока не нашел (может, плохо искал, конечно).

Спасибо.
    


Ответы

Ответ 1



Начну с конфигов. Во-первых, у DLL не бывает файла конфигурации. Тот, что у вас в проекте лежит - это мусор. Ну, некоторые настройки используются самой студией - на остальные же можно смотреть только как на пример. Файлы конфигурации бывают только у исполнимых файлов и у веб-сайтов. Далее - файл конфигурации не является автогенерируемым. Студия может в нем что-то менять - но как правило, это лишь пример. По-хорошему, вам надо пойти в msdn - и прочитать описание каждого тэга, используемого в вашем файле конфигурации. Секция bindings используется на обоих сторонах соединения - т.е. и клиентом, и сервером. Но она опциональна - без нее будут браться настройки по умолчанию. Если вам надо поменять там настройки, но ее нет - значит, ее надо создать. На разные привязки (bindings, "биндинги") ссылаются конечные точки (endpoint) через атрибуты binding и bindingConfiguration. Когда будете создавать свои привязки - не забудьте про эту связь, чтобы не удивляться потом что ничего не изменилось. Теперь про передачу файлов. Не переживайте особо про расширение в дальнейшем - когда понадобится сделать по-другому, всегда можно все перенастроить. По-меньше думайте "как сделать чтобы никогда не надо было переписывать" - а по-больше "какова моя задача сейчас?" Сериализация бинарных данных в XML недостатком не является пока эти файлы не очень большие. Просто помните, что файлы от этого распухают на треть. Шифрование на транспортном уровне не является проблемой если только вы не работаете с интеграционными шинами.

четверг, 13 февраля 2020 г.

Как настроить приложение MVC для работы через HTTPS соединение?

#c_sharp #aspnet_mvc #mvc #https #config


Доброго времени суток. 

Суть вопроса изложена в заголовке. Нужно ли вручную создавать сертификат и подкручивать
его к IIS? Или достаточно просто прописать что-то в файле Web.config??? Или нужно перед
каждым методом всех контроллеров указывать [RequireHttps]??? Если есть нормальная документация,
ткните носом, пожалуйста, потому что я ничего особо дельного не нашла...
    


Ответы

Ответ 1



Да, сертификат нужно подкрутить в IIS, инструкция и бесплатный сертфикат на год могут быть найдены, например, тут. Также, в IIS для работы по HTTPS MVC сайта требуется правильно указать биндинг к https: Если вы не собираетесь использовать для сайта защищённый и обычный HTTP одновременно, то никаких атрибутов указывать не требуется, как и править Web.config - IIS не будет отзываться на обычные HTTP запросы.

Ответ 2



Если создать сертификат для сервера самостоятельно (self signed certificate), то многие браузеры будут выдавать пользователю предупреждающее сообщение. Чтобы такого предупреждения не было, нужно заказать/купить SSL-сертификат у подтвержденных центров сертификации. Сделать это можно, например, у регистраторов доменов или хостинг провайдеров. Как настроить ssl-сертификат в IIS можно посмотреть тут. Как сделать ssl-сертификат самому в IIS тут. Веб-приложение будет работать без каких-либо правок в web.config. Атрибут RequireHttps требует вызывать отмеченный методы (Action) по HTTPS.

среда, 12 февраля 2020 г.

Как лучше работать с конфигурациями в Ruby

#ruby #config #configuration #best_practice


Допустим, у нас есть некая структура конфигурации (взята из YAML, JSON, XML или просто
в виде Hash):  

configuration = {
  gmail: {
    username: 'example@gmail.com',
    password: 'pa$$word',
    host: 'imap.gmail.com',
    ssl: true,
    port: 993
  },
  ftp: {
    username: 'example@gmail.com',
    password: 'pa$$word',
    host: 'imap.gmail.com',
    ssl: true,
    port: 42
  }
}


Далее, на основе этой структуры мы достаём из неё данные:  

mail = Mail.new host: configuration[:gmail][:host], port: configuration[:gmail][:port],
username: configuration[:gmail][:username], password: configuration[:gmail][:password],
ssl: configuration[:gmail][:ssl]
ftp = FTP.new host: configuration[:ftp][:host], port: configuration[:ftp][:port],
username: configuration[:ftp][:username], password: configuration[:ftp][:password],
ssl: configuration[:ftp][:ssl]


Всё работает, но сам код получается «плохочитаемым». 
Т. е. он конечно понятен, но слишком много «сухого» текста, вместо привычного для
языка программирования кода.  

Поделитесь Best Practice, как правильно делать и использовать конфигурации в Ruby.
    


Ответы

Ответ 1



Если имена атрибутов Mail и FTP в вашем примере в точности соответствуют ключам в структурах в конфигурации - вы можете передавать в конструктор хеш напрямую: mail = Mail.new configuration[:gmail] ftp = FTP.new configuration[:ftp] Здесь важно помнить две вещи: Ключи и типы значений в конфигурации должны совпадать с атрибутами и типами значений атрибутов класса; Доступ к конфигурации должен быть только у вас - иначе злоумышленник может, оперируя структурой, создавать объекты с любыми атрибутами класса без ограничений.

Ответ 2



Ну, как минимум вы написали выбор поднабора из хэша с захардкоженными ключами. "Колонна" в вашем коде (которая получается, если код "подровнять"): mail = Mail.new host: configuration[:gmail][:host], port: configuration[:gmail][:port], username: configuration[:gmail][:username], password: configuration[:gmail][:password], ssl: configuration[:gmail][:ssl] # ^^^^^^^^^^^^^^^^^^ это ^^^^^^^^^^^^^^^^^^^^ ...на самом деле же просто хэшмап. Просто {} вокруг него писать оказалось необязательно, т. к. это последний аргумент вызова метода, и это особый случай в синтаксисе Ruby. Если в configuration[:gmail] нет лишних ключей, то можно сделать попросту вот так: Mail.new configuration[:gmail] ...а если лишние ключи хочется отрезать, и вы вооружены aсtivesupport'ом (гем такой, из состава Rails), есть Hash#slice: # Точечная загрузка ActiveSupport require 'active_support/core_ext/hash/slice' # В Rails необязательно, там он обычно весь уже загружен Mail.new configuration[:gmail].slice(:host, :port, :username, :password, :ssl) ...но обычно один набор параметров конфигурации используется в ровно одном месте (или если в нескольких, то как минимум одинаково: скажем, при вызове однотипных конструкторов), поэтому можно себе позволить просто не писать в конфигах лишние ключи. Это не конвенция, такая ситуация сложилась сама и она всех устраивает. "Best bractices" конфигураций, которые вы ждёте, этого всего в основном не касаются и они запакованы, в разных комбинациях, в гемы dotenv, figaro и config. Что в них типично встречается: Сокращённый синтаксис получения конфигурации ключей: a[:b][:c] => a.b.c Фоллбэк (когда конфига нет) к переменным среды в ENV (см. 12-факторные приложения) Конвенции по размещению конфигурационных файлов и их формату — кто на что горазд

Может ли программа понять, что ее config был отредактирован и сменить свое поведение без перезапуска?

#c_sharp #net #config


Например, имеется программа с каким-то app.config, где храниться путь для закачки файлов.

Может ли программа понять, когда запущена, что config был отредактирован и на основании
этого выполнять закачку в другую папку?
    


Ответы

Ответ 1



Да, может. Сначала надо явно загрузить свой файл настроек: var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal); Дальше надо получить список файлов, из которых этот файл настроек был собран: var files = config.Locations.Cast().Select(loc => loc.Path); Теперь можно начать наблюдение за этими файлами: var monitor = new HostFileChangeMonitor(files.ToArray()); monitor.NotifyOnChanged(_ => { // ... }); Когда поступит сигнал об изменении файлов - надо выждать 100-200 миллисекунд и сделать все с начала.

вторник, 31 декабря 2019 г.

Как писать коментарии в json-конфиге?

#json #config #комментарии


Есть конфиг файл в формате json. Нужно закоментировать одну строку и попробовать
другое значение. Ну и сопроводиловку для будущего себя накатать. Какой знак за это
отвечает?
    


Ответы

Ответ 1



Никак. В json комментарии не предусмотрены. Изначально этот формат разрабатывался для сетевого обмена данными, а уже потом его стали использовать для хранения информации.

Ответ 2



В JSON5 завезли комментарии. Поддерживаются как однострочные //, так и многострочные /* */ комментарии. Источник: https://ru.wikipedia.org/wiki/JSON#JSON5

Ответ 3



так удобнее { "some-key-comment":"comments_comments", "some-key-value":"some-value", }

четверг, 26 декабря 2019 г.

App.config и приложение на C#

#c_sharp #net #config #clr


У меня есть небольшая программа на 2 версии .NET, но новых версиях Windows  она не
запускается, но если создать файл настроек, то она запустится.




  
  
  




Есть какие-нибудь варианты, что можно сделать, чтоб было не 2 файла, а 1? Т.е внедрить
этот файл настроек в exe или ещё как-нибудь.
    


Ответы

Ответ 1



Встроить файл конфигурации в EXE-файл нельзя (так как весь смысл конфигурации - это возможность редактирования параметров без перекомпиляции программы, такой возможности не предусмотрели). Влиять на параметр supportedRuntime из кода на C# также нельзя, так этот параметр используется неуправляемым кодом загрузчика до того, как в процесс загружена CLR, и в этот момент управляемый код еще не может выполняться. Если нужно управлять выбором версии CLR без файла конфигурации, единственный способ - написать свой собственный загрузчик на С++, пользуясь Unmanaged .NET API. Например, создадим такую программу на C#: using System; namespace ConsoleApplication1 { class Program { static int Run(string arg) { Console.WriteLine("Hello from .NET " + Environment.Version.ToString()); Console.ReadKey(); return 0; } static void Main(string[] args) { Run(""); } } } Скомпилируем ее, получаем файл Program.exe. Создадим проект С++, добавим в него файл Program.exe и создадим файл ресурсов resource.rc следующего содержания: #define IDR_RCDATA1 101 IDR_RCDATA1 RCDATA "Program.exe" Напишем на С++ код загрузчика, который находит первую установленную версию CLR, загружает ее, извлекает из ресурсов программу на C# во временную папку и запускает ее: #include #include #include #include #pragma comment(lib, "mscoree.lib") #define IDR_RCDATA1 101 int wmain(int argc, wchar_t* argv[]) { LPCWSTR prog_name = L"Program.exe"; //имя программы на C# //построим путь к временному файлу WCHAR temppath[300] = L"c:\\temp\\"; GetTempPath(300,temppath); wcscat(temppath,prog_name); //извлечем программу из ресурсов HRSRC myResource = ::FindResource(NULL, MAKEINTRESOURCE(IDR_RCDATA1), RT_RCDATA); UINT Size = ::SizeofResource(NULL, myResource); HGLOBAL myResourceData = ::LoadResource(NULL, myResource); void* pMyBinaryData = ::LockResource(myResourceData); FILE* f = _wfopen(temppath,L"wb"); fwrite(pMyBinaryData,Size,1,f); fclose(f); //инициализация CLR... HRESULT hr; ICLRMetaHost *pMetaHost = NULL; ICLRRuntimeInfo *pRuntimeInfo = NULL; ICLRRuntimeHost *pClrRuntimeHost = NULL; IEnumUnknown* pEnum= NULL; ICLRRuntimeInfo* pInfo= NULL; IUnknown* pUnk = NULL; hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost)); if(FAILED(hr)){printf("CLRCreateInstance failed\n");goto End;} //поиск установленных версий CLR... pMetaHost->EnumerateInstalledRuntimes(&pEnum); if(FAILED(hr)){printf("EnumerateInstalledRuntimes failed\n");goto End;} ULONG c= 0; WCHAR buffer[250]; DWORD cch = 250; while(1){ if(pInfo!=NULL){pInfo->Release();pInfo = NULL;} if(pUnk!=NULL){pUnk->Release();pUnk = NULL;} if(pRuntimeInfo!=NULL){pRuntimeInfo->Release();pRuntimeInfo = NULL;} hr = pEnum->Next(1,&pUnk,&c); if(hr != S_OK)break; pUnk->QueryInterface(IID_ICLRRuntimeInfo, (void**)&pInfo); if(FAILED(hr)){printf("QueryInterface failed\n");continue;} pInfo->GetVersionString(buffer,&cch); if(FAILED(hr)){printf("GetVersionString failed\n");continue;} hr = pMetaHost->GetRuntime(buffer, IID_PPV_ARGS(&pRuntimeInfo)); if(hr == S_OK){break;} else {wprintf(L".NET %s: GetRuntime HRESULT 0x%x\n",buffer,(UINT)hr);} } if(pRuntimeInfo == NULL){printf("Failed to initialize CLR\n");goto End;} /* Можно также указать версию явно, например: pMetaHost->GetRuntime(L"v2.0.50727", IID_PPV_ARGS(&pRuntimeInfo)); pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo)); и т.п. */ hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&pClrRuntimeHost)); if(FAILED(hr)){printf("GetInterface failed\n");goto End;} //запуск CLR hr = pClrRuntimeHost->Start(); if(FAILED(hr)){printf("Start failed\n");goto End;} //Запуск программы на C# DWORD pReturnValue; hr = pClrRuntimeHost->ExecuteInDefaultAppDomain( temppath, L"ConsoleApplication1.Program", //класс L"Run", //метод L"", //параметр &pReturnValue); if(FAILED(hr)){printf("ExecuteInDefaultAppDomain failed 0x%x\n",(UINT)hr);goto End;} End: //Освобождение ресурсов if(pMetaHost != NULL) pMetaHost->Release(); if(pRuntimeInfo != NULL) pRuntimeInfo->Release(); if(pClrRuntimeHost != NULL) pClrRuntimeHost->Release(); if(pEnum != NULL) pEnum->Release(); if(pInfo != NULL) pInfo->Release(); if(pUnk != NULL) pUnk->Release(); return 0; } В результате программа, собранная под .NET 2.0, при его отсутствии будет запускаться на имеющейся версии .NET, как и при использовании параметра supportedRuntime. Источники: Embedding supportedRuntime into exe file - ответ Ondrej Svejdar How to load a custom binary resource in a VC++ static library as part of a dll? - ответ LihO

понедельник, 23 декабря 2019 г.

Как хранить и управлять конфигурационными файлами проекта в Open Source?

#java #git #github #config


Допустим я делаю веб-приложение, которое использует какой-то API или просто работает
с базой данных. Я хочу выложить исходные коды приложения в открытый доступ, но как
быть с секретными данными, такими как ключи API, пароли к БД и SMTP?

Я могу написать в readme, что конфигурационный файл такого-то типа вам придется создать
руками, но хочется собирать проект и отправлять его в продакшн из git репозитория,
который хостится, например, на github.

Особенно интересно было бы прочитать ответы на примере Java технологий, потому что
я делаю Java веб-приложение.
    


Ответы

Ответ 1



В самом общем случае, в общедоступный репозиторий кладут конфиг-файл, в котором нет паролей и хостов, которые вы не хотите скомпрометировать. Пишут какие-нибудь дефолтные значения (например, example.com или 12345), в комментариях или документации описывают, что нужно подставить, чтобы работало. Реальные же конфиги держат в недоступном для посторонних месте (например, приватном репозитории) и подкладывают во время деплоя в продакшн. Обычно конфигурацию стараются вынести из архива с приложением, чтобы его не перепаковывать его при деплое. Это можно сделать как захардкодив имя конфига, и ожидая его найти в папке с приложением или каком-нибудь другом заранее известном месте, так и требуя от пользователя указывать путь к конфигу в аргументах JVM при запуске. Также распространённым вариантом является частичное переопределение конфигов (которое очень хорошо работает, если конфиги - файлы properties). В архиве с приложением лежит полный конфиг, в котором все секретные параметры заменены дефолтными значениями, а извне лежит конфиг, в котором указаны реальные значения только для секретных параметров. Приложение сначала читает конфиг, который в него зашит, потом - внешний, и переопределяет совпадающие параметры. Так мы избавляемся от необходимости полностью копировать конфиг в приватный репозиторий и постоянно синхронизировать его с публичным. Если ваше приложение написано на Spring Boot, то всё это вы получаете из коробки. Spring Boot умеет подтягивать внешние конфиги из кучи мест и позволяет управлять загружаемыми конфигами при помощи профилей. Также в семействе проектов Spring есть Spring Cloud Config, работающий в связке с Spring Cloud Config Server. Сервер конфигурации может подтягивать конфиги из множества источников (в том числе из репозитория Git) и отдавать их через REST API. Клиент (ваше приложение) подтягивает значения свойств через стандартные аннотации Spring @Value совершенно прозрачно для программиста. Такая связка позволяет очень удобно управлять настройками сразу нескольких окружений (например, один сервер конфигурации может обслуживать и тестовые, и продакшн сервера, хотя это и нежелательно) или нескольких инстансов задеплоенного приложения. Такое решение изначально разрабатывалось под микросервисную архитектуру, поэтому такую связку имеет смысл поднимать, если у вас инстансов приложения больше одного, и деплой полностью автоматизирован. А ещё Spring Cloud Config умеет шифровать конфиги. Такие конфиги можно (хотя и не рекомендуется) выкладывать в публичный репозиторий, а при деплое просто подкладывать ключ для расшифровки (вот его ни в коем случае светить не нужно). Конечно, всё вышеописанное можно реализовать и без Spring, но Spring очень сильно всё облегчает.

пятница, 20 декабря 2019 г.

Где и как правильно хранить настройки программы?

#c_sharp #config #settings


Программа на С# (но в принципе это не столь важно), до этого использовал стандартный
app.config, быстро удобно, но его возможностей стало не хватать. Во первых параметров
стало много: сохранение состояний всех окон, некоторых контролов, настройки самой программы,
настройки подключения к серверу, которые надо шифровать ну и т.д. В общем решил написать
свой велосипед, теперь думаю где это все хранить, и соответственно как реализовать.

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


Ответы

Ответ 1



Тогда храните в профиле текущего пользователя. А сериализацию лучше делать через xml, чтобы при необходимости можно было поправить конфиг руками.

Ответ 2



На форуме был уже похожий вопрос, посмотрите, возможно найдете полезным

понедельник, 17 июня 2019 г.

Коллекция элементов в ConfigSection

При помощи следующего набора классов:
public class MyConfigSection : ConfigurationSection { [ConfigurationProperty("Items")] public ItemCollection Items { get { return ((ItemCollection)(base["Items"])); } } }
[ConfigurationCollection(typeof(ItemElement), AddItemName = "Item")] public class ItemCollection : ConfigurationElementCollection { ... }
public class ItemElement : ConfigurationElement { ... }
Я организую чтение конфигурационной секции следующего вида:

Возможно ли как-то настроить чтение, если я хочу чтобы секция имела вид

т.е. чтобы элементы коллекции не были заключены в , а читались прямо из секции.


Ответ

Попробуйте использовать параметр IsDefaultCollection и пустую строку как ключ:
public class MyConfigSection : ConfigurationSection { [ConfigurationProperty("", Options = ConfigurationPropertyOptions.IsDefaultCollection)] public ItemCollection Items { get { return ((ItemCollection)(base[""])); } } }

понедельник, 27 мая 2019 г.

Конфигурирование WCF-сервиса для передачи файлов, как и где это сделать?

Пришлось впервые столкнуться с WCF, ибо есть задача - посредством WCF-службы отдавать клиенту файлы по запросу клиента.
Предварительно была изучена теория, и выяснено, что файлы можно передавать:
Как есть, без предварительной настройки, разве что, выставив maxMessageLengthи executionTimeoutInSeconds в довольно большие значения. Включить MTOM в качестве кодировщика. Включить стриминг (потоковую передачу данных).
Точный размер передаваемых файлов я не знаю, но зато могу сказать, что на текущем этапе вряд ли будут передаваться большущие файлы типа дампов БД или потокового видео. Но всё же, в стандартном подходе меня смущает то, что будет постоянная сериализация-десереализация файлов в XML, а зачем лишние телодвижения?
Включение стриминга, в принципе, сейчас подходит, но, как говорит MSDN, будет ряд ограничений (связаны с шифрованим и буферизацией, подробнее — в статье), из-за которых, цитирую:
Из-за этих функциональных ограничений параметры безопасности для потоковой передачи можно использовать только на транспортном уровне, и невозможно реализовать надежные сеансы.
Если сейчас этим можно пренебречь, так как никакого шифрования нет и в помине, но в разрезе дальнейшего развития сервиса это смущает.
Пока в качестве наиболее подходящих путей пытался как включать поддержку MTOM, так и стриминг.
Итак, в качестве пути решения был выбран проект WCF Service Library, в котором был объявлен интерфейс службы, примерно так:
[ServiceContract] public interface IUpdaterService { [OperationContract] bool TestConnection(); ... [OperationContract] FileStream DownloadFile(string filename); ... }
Ага, тут я использую FileStream, значит нужно включить поддержку стриминга, но сложность в том, что я попросту не знаю, где и как это сделать. То же самое и с включением MTOM.
Ну, например, в попавшихся мне решениях говорят, "измените конфиг так":


Вроде всё понятно, что менять и на что, но где это делать?
Напоминаю, у меня DLL, в которой есть лишь App.config, и он - следующий:


Т.е. по сути, в App.config нет, например, раздела bindings, где можно было бы изменить эти параметры. При запуске родного WCF Test Client метод DownloadFile не доступен, так как используется тип FileStram, стало быть, протестировать его никак...
Конфиг клиента, в свою очередь, формируется такой, нужно, т.е. как раз с теми разделами, которые можно менять:


Но опять же - возникает вопрос - а где и как менять этот конфиг? Уверен, он генерируется автоматически, т.е. необходимо задать нужные параметры для моей DLL, но как верно это сделать? К сожалению, ответа на этот вопрос пока не нашел (может, плохо искал, конечно).
Спасибо.


Ответ

Начну с конфигов.
Во-первых, у DLL не бывает файла конфигурации. Тот, что у вас в проекте лежит - это мусор. Ну, некоторые настройки используются самой студией - на остальные же можно смотреть только как на пример.
Файлы конфигурации бывают только у исполнимых файлов и у веб-сайтов.
Далее - файл конфигурации не является автогенерируемым. Студия может в нем что-то менять - но как правило, это лишь пример. По-хорошему, вам надо пойти в msdn - и прочитать описание каждого тэга, используемого в вашем файле конфигурации.
Секция bindings используется на обоих сторонах соединения - т.е. и клиентом, и сервером. Но она опциональна - без нее будут браться настройки по умолчанию. Если вам надо поменять там настройки, но ее нет - значит, ее надо создать.
На разные привязки (bindings, "биндинги") ссылаются конечные точки (endpoint) через атрибуты binding и bindingConfiguration. Когда будете создавать свои привязки - не забудьте про эту связь, чтобы не удивляться потом что ничего не изменилось.

Теперь про передачу файлов. Не переживайте особо про расширение в дальнейшем - когда понадобится сделать по-другому, всегда можно все перенастроить.
По-меньше думайте "как сделать чтобы никогда не надо было переписывать" - а по-больше "какова моя задача сейчас?"
Сериализация бинарных данных в XML недостатком не является пока эти файлы не очень большие. Просто помните, что файлы от этого распухают на треть.
Шифрование на транспортном уровне не является проблемой если только вы не работаете с интеграционными шинами.

среда, 13 февраля 2019 г.

Как писать коментарии в json-конфиге?

Есть конфиг файл в формате json. Нужно закоментировать одну строку и попробовать другое значение. Ну и сопроводиловку для будущего себя накатать. Какой знак за это отвечает?


Ответ

Никак. В json комментарии не предусмотрены. Изначально этот формат разрабатывался для сетевого обмена данными, а уже потом его стали использовать для хранения информации.

пятница, 30 ноября 2018 г.

App.config и приложение на C#

У меня есть небольшая программа на 2 версии .NET, но новых версиях Windows она не запускается, но если создать файл настроек, то она запустится.

Есть какие-нибудь варианты, что можно сделать, чтоб было не 2 файла, а 1? Т.е внедрить этот файл настроек в exe или ещё как-нибудь.


Ответ

Встроить файл конфигурации в EXE-файл нельзя (так как весь смысл конфигурации - это возможность редактирования параметров без перекомпиляции программы, такой возможности не предусмотрели). Влиять на параметр supportedRuntime из кода на C# также нельзя, так этот параметр используется неуправляемым кодом загрузчика до того, как в процесс загружена CLR, и в этот момент управляемый код еще не может выполняться.
Если нужно управлять выбором версии CLR без файла конфигурации, единственный способ - написать свой собственный загрузчик на С++, пользуясь Unmanaged .NET API
Например, создадим такую программу на C#:
using System;
namespace ConsoleApplication1 { class Program { static int Run(string arg) { Console.WriteLine("Hello from .NET " + Environment.Version.ToString()); Console.ReadKey(); return 0; }
static void Main(string[] args) { Run(""); } } }
Скомпилируем ее, получаем файл Program.exe. Создадим проект С++, добавим в него файл Program.exe и создадим файл ресурсов resource.rc следующего содержания:
#define IDR_RCDATA1 101
IDR_RCDATA1 RCDATA "Program.exe"
Напишем на С++ код загрузчика, который находит первую установленную версию CLR, загружает ее, извлекает из ресурсов программу на C# во временную папку и запускает ее:
#include #include #include #include
#pragma comment(lib, "mscoree.lib")
#define IDR_RCDATA1 101
int wmain(int argc, wchar_t* argv[]) { LPCWSTR prog_name = L"Program.exe"; //имя программы на C#
//построим путь к временному файлу WCHAR temppath[300] = L"c:\\temp\\"; GetTempPath(300,temppath); wcscat(temppath,prog_name);
//извлечем программу из ресурсов HRSRC myResource = ::FindResource(NULL, MAKEINTRESOURCE(IDR_RCDATA1), RT_RCDATA); UINT Size = ::SizeofResource(NULL, myResource); HGLOBAL myResourceData = ::LoadResource(NULL, myResource); void* pMyBinaryData = ::LockResource(myResourceData); FILE* f = _wfopen(temppath,L"wb"); fwrite(pMyBinaryData,Size,1,f); fclose(f);
//инициализация CLR... HRESULT hr; ICLRMetaHost *pMetaHost = NULL; ICLRRuntimeInfo *pRuntimeInfo = NULL; ICLRRuntimeHost *pClrRuntimeHost = NULL; IEnumUnknown* pEnum= NULL; ICLRRuntimeInfo* pInfo= NULL; IUnknown* pUnk = NULL;
hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost)); if(FAILED(hr)){printf("CLRCreateInstance failed
");goto End;}
//поиск установленных версий CLR... pMetaHost->EnumerateInstalledRuntimes(&pEnum); if(FAILED(hr)){printf("EnumerateInstalledRuntimes failed
");goto End;}
ULONG c= 0; WCHAR buffer[250]; DWORD cch = 250;
while(1){ if(pInfo!=NULL){pInfo->Release();pInfo = NULL;} if(pUnk!=NULL){pUnk->Release();pUnk = NULL;} if(pRuntimeInfo!=NULL){pRuntimeInfo->Release();pRuntimeInfo = NULL;}
hr = pEnum->Next(1,&pUnk,&c); if(hr != S_OK)break;
pUnk->QueryInterface(IID_ICLRRuntimeInfo, (void**)&pInfo); if(FAILED(hr)){printf("QueryInterface failed
");continue;}
pInfo->GetVersionString(buffer,&cch); if(FAILED(hr)){printf("GetVersionString failed
");continue;}
hr = pMetaHost->GetRuntime(buffer, IID_PPV_ARGS(&pRuntimeInfo)); if(hr == S_OK){break;} else {wprintf(L".NET %s: GetRuntime HRESULT 0x%x
",buffer,(UINT)hr);} }
if(pRuntimeInfo == NULL){printf("Failed to initialize CLR
");goto End;}
/* Можно также указать версию явно, например: pMetaHost->GetRuntime(L"v2.0.50727", IID_PPV_ARGS(&pRuntimeInfo)); pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo)); и т.п. */
hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&pClrRuntimeHost)); if(FAILED(hr)){printf("GetInterface failed
");goto End;}
//запуск CLR hr = pClrRuntimeHost->Start(); if(FAILED(hr)){printf("Start failed
");goto End;}
//Запуск программы на C# DWORD pReturnValue; hr = pClrRuntimeHost->ExecuteInDefaultAppDomain( temppath, L"ConsoleApplication1.Program", //класс L"Run", //метод L"", //параметр &pReturnValue); if(FAILED(hr)){printf("ExecuteInDefaultAppDomain failed 0x%x
",(UINT)hr);goto End;}
End:
//Освобождение ресурсов if(pMetaHost != NULL) pMetaHost->Release(); if(pRuntimeInfo != NULL) pRuntimeInfo->Release(); if(pClrRuntimeHost != NULL) pClrRuntimeHost->Release(); if(pEnum != NULL) pEnum->Release(); if(pInfo != NULL) pInfo->Release(); if(pUnk != NULL) pUnk->Release(); return 0; }
В результате программа, собранная под .NET 2.0, при его отсутствии будет запускаться на имеющейся версии .NET, как и при использовании параметра supportedRuntime
Источники:
Embedding supportedRuntime into exe file - ответ Ondrej Svejdar
How to load a custom binary resource in a VC++ static library as part of a dll? - ответ LihO

понедельник, 19 ноября 2018 г.

Как хранить и управлять конфигурационными файлами проекта в Open Source?

Допустим я делаю веб-приложение, которое использует какой-то API или просто работает с базой данных. Я хочу выложить исходные коды приложения в открытый доступ, но как быть с секретными данными, такими как ключи API, пароли к БД и SMTP?
Я могу написать в readme, что конфигурационный файл такого-то типа вам придется создать руками, но хочется собирать проект и отправлять его в продакшн из git репозитория, который хостится, например, на github.
Особенно интересно было бы прочитать ответы на примере Java технологий, потому что я делаю Java веб-приложение.


Ответ

В самом общем случае, в общедоступный репозиторий кладут конфиг-файл, в котором нет паролей и хостов, которые вы не хотите скомпрометировать. Пишут какие-нибудь дефолтные значения (например, example.com или 12345), в комментариях или документации описывают, что нужно подставить, чтобы работало. Реальные же конфиги держат в недоступном для посторонних месте (например, приватном репозитории) и подкладывают во время деплоя в продакшн.
Обычно конфигурацию стараются вынести из архива с приложением, чтобы его не перепаковывать его при деплое. Это можно сделать как захардкодив имя конфига, и ожидая его найти в папке с приложением или каком-нибудь другом заранее известном месте, так и требуя от пользователя указывать путь к конфигу в аргументах JVM при запуске.
Также распространённым вариантом является частичное переопределение конфигов (которое очень хорошо работает, если конфиги - файлы properties). В архиве с приложением лежит полный конфиг, в котором все секретные параметры заменены дефолтными значениями, а извне лежит конфиг, в котором указаны реальные значения только для секретных параметров. Приложение сначала читает конфиг, который в него зашит, потом - внешний, и переопределяет совпадающие параметры. Так мы избавляемся от необходимости полностью копировать конфиг в приватный репозиторий и постоянно синхронизировать его с публичным.
Если ваше приложение написано на Spring Boot, то всё это вы получаете из коробки. Spring Boot умеет подтягивать внешние конфиги из кучи мест и позволяет управлять загружаемыми конфигами при помощи профилей.
Также в семействе проектов Spring есть Spring Cloud Config, работающий в связке с Spring Cloud Config Server. Сервер конфигурации может подтягивать конфиги из множества источников (в том числе из репозитория Git) и отдавать их через REST API. Клиент (ваше приложение) подтягивает значения свойств через стандартные аннотации Spring @Value совершенно прозрачно для программиста. Такая связка позволяет очень удобно управлять настройками сразу нескольких окружений (например, один сервер конфигурации может обслуживать и тестовые, и продакшн сервера, хотя это и нежелательно) или нескольких инстансов задеплоенного приложения. Такое решение изначально разрабатывалось под микросервисную архитектуру, поэтому такую связку имеет смысл поднимать, если у вас инстансов приложения больше одного, и деплой полностью автоматизирован.
А ещё Spring Cloud Config умеет шифровать конфиги. Такие конфиги можно (хотя и не рекомендуется) выкладывать в публичный репозиторий, а при деплое просто подкладывать ключ для расшифровки (вот его ни в коем случае светить не нужно).
Конечно, всё вышеописанное можно реализовать и без Spring, но Spring очень сильно всё облегчает.

вторник, 6 ноября 2018 г.

Где и как правильно хранить настройки программы?

Программа на С# (но в принципе это не столь важно), до этого использовал стандартный app.config, быстро удобно, но его возможностей стало не хватать. Во первых параметров стало много: сохранение состояний всех окон, некоторых контролов, настройки самой программы, настройки подключения к серверу, которые надо шифровать ну и т.д. В общем решил написать свой велосипед, теперь думаю где это все хранить, и соответственно как реализовать. На данный момент склоняюсь к созданию своего класса настроек и его бинарной сериализацией, но вот вопрос, где его хранить? Не хотелось бы его держать в папке с программой, и для каждого пользователя иметь отдельные настройки.


Ответ

Тогда храните в профиле текущего пользователя. А сериализацию лучше делать через xml, чтобы при необходимости можно было поправить конфиг руками.