none
Вариация кода под разные сборки(конфигурации) RRS feed

  • Вопрос

  • Приветствую.

    Хотелось бы узнать - можно ли варьировать код для разных сборок(конфигураций).

    Допустим есть несколько конечных пользователей и для каждого необходимо сделать определённую привязку моей программы. Т.е. своего рода система защиты от копирования. Сейчас приходится делать это вручную - менять код и компилировать *.ехе под одного клиента, потом менять код и компилировать под другого.

    В идеале представляется что-то следующее:

    [Configuration:Client1]
    void work()
    {
      // Client One Code
    }
    [Configuration:Client2]
    void work()
    {
      // Client TwoCode
    }
    
    

    Либо, может быть, есть другие способы решения задачи?

     

    Любые советы, ссылки или просто направления в какую сторону "копать" - приветствуются.

    16 июля 2011 г. 16:51

Ответы

  • UPD: Судя по всему для С# это не подходит. Либо я не понял как это использовать.

    Это взято из справочника по C# =) Так что это просто Вы не поняли как этим пользоваться =)

    Попробую пояснить.

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

    Вот пример кода:

     

    #define CompanyA
    //#define CompanyB
     
    using System;
     
    namespace ConsoleApplication2
    {
        class Program
        {
            static void Main(string[] args)
            {
                #if CompanyA
                    Console.WriteLine("this is CompanyA cofiguration");    
                #endif
     
                #if CompanyB
                    Console.WriteLine("this is CompanyB cofiguration");
                #endif
     
                Console.Read();
            }
        }
    }
    

    В данном случае откомпилируется тока области, помеченные как CompanyA. Если необходимо откомпилировать области помеченные как CompanyB, необходимо закомментировать определение #define CompanyA и разкомментировать #define CompanyB.

    Если необходимо применить имя условия в рамках всего проекта, то в свойствах проекта укажите имя области:

     


    [My blog] [My E-mail]
    • Предложено в качестве ответа Abolmasov Dmitry 17 июля 2011 г. 17:59
    • Помечено в качестве ответа Abolmasov Dmitry 20 июля 2011 г. 11:52
    17 июля 2011 г. 10:28
  • Добавьте в проект через мастер файл конфигурации - App.cofig по умолчанию называется.

    Вот пример файла конфигурации:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <connectionStrings>
        <add name="Connection string" 
             connectionString="Data Source=(local)\SQLEXPRESS;
                                Initial Catalog=ProfItLabsTestJob;
                                User ID=HrAdmin;Password=HrAdmin"/>
        <add name="Connection string DBF" 
             connectionString="Driver={Driver do Microsoft dBase (*.dbf)};
                              collatingsequence=ASCII;
                              defaultdir=C:\Кладр\BASE;
                              deleted=0;
                              driverid=533;
                              fil=dBase 5.0;
                              maxbuffersize=2048;
                              maxscanrows=8;
                              pagetimeout=5;
                              safetransactions=0;
                              statistics=0;
                              threads=3;
                              uid=admin;
                              usercommitsync=Yes"/>
      </connectionStrings>
      <appSettings>
        <add key="Kladr path" value="C:\Кладр\BASE\KLADR.DBF"/>
        <add key="Street path" value="C:\Кладр\BASE\STREET.DBF"/>
      </appSettings>
    </configuration>

     

    Чтобы вытащить из него строку подключения к БД, необходимо написать след строчку кода:

    ConfigurationManager.ConnectionStrings["Connection string"].ConnectionString
    

     

    Чтобы вытащить параметр приложения, необходимо написать следующую строчку кода:

    ConfigurationManager.AppSettings["Kladr path"].ToString()
    

     

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

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


    [My blog] [My E-mail]
    • Предложено в качестве ответа Abolmasov Dmitry 18 июля 2011 г. 6:11
    • Помечено в качестве ответа Abolmasov Dmitry 20 июля 2011 г. 11:52
    18 июля 2011 г. 0:58

Все ответы

  • Добрый день!

    "Копать" надо в сторону директив препроцессора C#. А именно в сторону условий компиляции кода.


    [My blog] [My E-mail]
    • Помечено в качестве ответа Alexandr Mo 17 июля 2011 г. 1:57
    • Снята пометка об ответе Alexandr Mo 17 июля 2011 г. 5:27
    16 июля 2011 г. 23:55
  • Благодарствую.

    UPD: Судя по всему для С# это не подходит. Либо я не понял как это использовать.

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

    17 июля 2011 г. 1:58
  • UPD: Судя по всему для С# это не подходит. Либо я не понял как это использовать.

    Это взято из справочника по C# =) Так что это просто Вы не поняли как этим пользоваться =)

    Попробую пояснить.

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

    Вот пример кода:

     

    #define CompanyA
    //#define CompanyB
     
    using System;
     
    namespace ConsoleApplication2
    {
        class Program
        {
            static void Main(string[] args)
            {
                #if CompanyA
                    Console.WriteLine("this is CompanyA cofiguration");    
                #endif
     
                #if CompanyB
                    Console.WriteLine("this is CompanyB cofiguration");
                #endif
     
                Console.Read();
            }
        }
    }
    

    В данном случае откомпилируется тока области, помеченные как CompanyA. Если необходимо откомпилировать области помеченные как CompanyB, необходимо закомментировать определение #define CompanyA и разкомментировать #define CompanyB.

    Если необходимо применить имя условия в рамках всего проекта, то в свойствах проекта укажите имя области:

     


    [My blog] [My E-mail]
    • Предложено в качестве ответа Abolmasov Dmitry 17 июля 2011 г. 17:59
    • Помечено в качестве ответа Abolmasov Dmitry 20 июля 2011 г. 11:52
    17 июля 2011 г. 10:28
  • Как именно не подходит? Вот вам пример:

    #define test1
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication1
    { 
      class Program
      {
        static void Main(string[] args)
        {
    #if test1
          Console.WriteLine("hello from test 1");
    #elif test2
          Console.WriteLine("hello from test 2");
    #elif test3
          Console.WriteLine("hello from test 3");
    #else
          Console.WriteLine("hello from else");
    #endif
        }
      }
    }
    
    

    Но, не лучше ли будет использовать файлы конфигурации и инициализировать в соответствии с ними необходимые переменные?


    Для связи [mail]
    17 июля 2011 г. 10:29
  • UPD: Судя по всему для С# это не подходит. Либо я не понял как это использовать.

    Это взято из справочника по C# =) Так что это просто Вы не поняли как этим пользоваться =)


    #define CompanyA
    //#define CompanyB
     
    using System;
     
    namespace ConsoleApplication2
    {
        class Program
        {
            static void Main(string[] args)
            {
                #if CompanyA
                    Console.WriteLine("this is CompanyA cofiguration");    
                #endif
     
                #if CompanyB
                    Console.WriteLine("this is CompanyB cofiguration");
                #endif
     
                Console.Read();
            }
        }
    }
    

    Именно так я и понял. Но тут скорее Я не совсем внятно изъяснил свою задачу.

    Есть к примеру код:
    void Main()
    {
      MessageBox.Show("Hello " + name);
    }

    Так вот. переменная name должна содержать имя клиента (того для кого предназначена программа). Клиентов, скажем, человек 50+. Появляется потребность в модернизации кода (улучшение/исправление/добавление и т.д.). Используя предпроцессорные механизмы мне прийдётся переписывать код, по крайней мере #define 50+ раз.

    На данный момент я подошёл к решению вопроса с некоторой "извращённость": Сам проект компилирую как библиотеку и в решение добавляю простой ВинФорм проект который уже, подставляя свои данные запускает основной проект на выполнение. И таких "запускаторов" наделал по количеству клиентов, просто копируя и подменяя нужные данные. На выходе компилируется N'ое количество *.ехе файлов с одной общей *.dll.

    17 июля 2011 г. 19:06
  • Но, не лучше ли будет использовать файлы конфигурации и инициализировать в соответствии с ними необходимые переменные?


    А вот тут, если можно, поподробнее. =)

    Заранее извиняюсь - я самоучка.

    17 июля 2011 г. 19:16
  • Добавьте в проект через мастер файл конфигурации - App.cofig по умолчанию называется.

    Вот пример файла конфигурации:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <connectionStrings>
        <add name="Connection string" 
             connectionString="Data Source=(local)\SQLEXPRESS;
                                Initial Catalog=ProfItLabsTestJob;
                                User ID=HrAdmin;Password=HrAdmin"/>
        <add name="Connection string DBF" 
             connectionString="Driver={Driver do Microsoft dBase (*.dbf)};
                              collatingsequence=ASCII;
                              defaultdir=C:\Кладр\BASE;
                              deleted=0;
                              driverid=533;
                              fil=dBase 5.0;
                              maxbuffersize=2048;
                              maxscanrows=8;
                              pagetimeout=5;
                              safetransactions=0;
                              statistics=0;
                              threads=3;
                              uid=admin;
                              usercommitsync=Yes"/>
      </connectionStrings>
      <appSettings>
        <add key="Kladr path" value="C:\Кладр\BASE\KLADR.DBF"/>
        <add key="Street path" value="C:\Кладр\BASE\STREET.DBF"/>
      </appSettings>
    </configuration>

     

    Чтобы вытащить из него строку подключения к БД, необходимо написать след строчку кода:

    ConfigurationManager.ConnectionStrings["Connection string"].ConnectionString
    

     

    Чтобы вытащить параметр приложения, необходимо написать следующую строчку кода:

    ConfigurationManager.AppSettings["Kladr path"].ToString()
    

     

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

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


    [My blog] [My E-mail]
    • Предложено в качестве ответа Abolmasov Dmitry 18 июля 2011 г. 6:11
    • Помечено в качестве ответа Abolmasov Dmitry 20 июля 2011 г. 11:52
    18 июля 2011 г. 0:58
  • Я рассматривал схожий вариант (сопутствующий файл с индивидуальными данными). Но "индивидуальность" приложения именно в его системе защиты. Т.е. каждая версия привязывается к конкретному пользователю по HardwareID. И в таком случае подмена App.conf может привести к обходу защиты.

    Вот почему я стремлюсь всё впихнуть в один файл. Вполне возможно наивно пологая что так будет сложнее обойти защиту.

    18 июля 2011 г. 14:03
  • Все программы под платформу .NET компилируются в MSIL-код, который вскрывается одним щелчком мыши. И все что находится внутри, впринципе без проблем изучается со всеми вытекающими последствиями.

    Не парьте себе мозг. Кому надо взломают все и достанут все что надо.

    Существуют специальные программы для запутывания внутренностей. Но они не все эффективны. А те что еще эффективны стоят тысячи дол.

    -----------------

    Кстати, выше я написал, что:

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

    Это значит, что файл конфигурации встраивается в исполняемый файл. Но как я написал тока что, все это легко взламывается.


    [My blog] [My E-mail]
    18 июля 2011 г. 14:09
  • В плане защиты кода от декомпиляции и т.п. есть множество наработанных методов. Начиная от самого кода, и до специальных программ. Да и это, собственно, не текущий вопрос.
    18 июля 2011 г. 15:53
  • Платформа .NET - это не компилируемый классичискими методами код. Код, написанный под эту платформу не есть бинарный файл. Это файл, содержащий MSIL-инструкции виртуальной машине .NET. А это значит что он легко открываем без хитроумных приспособлений. Ряд утилит устанавливается вместе с .NET Framework. Как показывает практика, защищают не сами сборки, а алгоритмы, которые находятся внутри них. Саму сборку не зашифровать.
    Речь об этом шла тут и тут.
    В вашем случае достаточным будет просто встраивание файла конфигурации в файл сборки.

    [My blog] [My E-mail]
    18 июля 2011 г. 16:59