1. Теперь за форумную активность начисляются биткоины и другие криптоденьги. Подробнее.
    Скрыть объявление
  2. Появилась архивная версия форума arhiv.xaker.name, где собраны темы с 2007 по 2012 год.
    Скрыть объявление

Кодим билдер на C#

Тема в разделе "Статьи", создана пользователем Banality, 2 фев 2015.

  1. Banality
    Banality ID,DL,PASSPORT,CC photoshop Продвинутый
    Симпатии:
    85
    В этой статье я расскажу, как написать билдер своего софта на C#.
    Компилировать будем простейшую форму, у которой будет динамически меняться Caption (текст заголовка).

    Для компилирования используются Namespacы:
    • Microsoft.CSharp
    • System.CodeDom.Compiler

    В них содержатся необходимые нам инструменты, например такие, как CSharpCodeProvider. Эта штука позволяет компилировать нам код из строки с помощью метода CompileAssemblyFromSource(). Этим мы и воспользуемся.
    Хранить свой код мы будем в самом приложении, чтобы не раздавать сорцы. Так как C# — JIT-язык, то после создания билдера его надо хорошо закриптовать, инструментов для этого куча, в гугле все есть, защиту .NET я описывать в этой статье не буду.

    Итак, создаем проект WinForms. Так как у меня будет пустая форма, то ничего добавлять я не стану.
    Теперь важно: весь код необходимо перенести в один файл. Все классы, Program.cs, Form1.Designer.Cs и т.д.
    Это можно сделать простым копипастом и переносом using’ов вверх. Объединив все, я получил:

    PHP:
    using System;
    using System.Windows.Forms;
     
    namespace 
    builder
    {
        public 
    partial class Form1 Form
        
    {
            public 
    Form1()
            {
                
    InitializeComponent();
            }
        }
    }
     
    namespace 
    builder
    {
        
    partial class Form1
        
    {
            
    /// <summary>
            /// Требуется переменная конструктора.
            /// </summary>
            
    private System.ComponentModel.IContainer components null;
     
            
    /// <summary>
            /// Освободить все используемые ресурсы.
            /// </summary>
            /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
            
    protected override void Dispose(bool disposing)
            {
                if (
    disposing && (components != null))
                {
                    
    components.Dispose();
                }
                
    base.Dispose(disposing);
            }
     
            
    #region Код, автоматически созданный конструктором форм Windows
     
            /// <summary>
            /// Обязательный метод для поддержки конструктора - не изменяйте
            /// содержимое данного метода при помощи редактора кода.
            /// </summary>
            
    private void InitializeComponent()
            {
                
    this.SuspendLayout();
                
    // 
                // Form1
                // 
                
    this.AutoScaleDimensions = new System.Drawing.SizeF(6F13F);
                
    this.AutoScaleMode System.Windows.Forms.AutoScaleMode.Font;
                
    this.ClientSize = new System.Drawing.Size(292243);
                
    this.Name "Form1";
                
    this.Text "Form1";
                
    this.ResumeLayout(false);
     
            }
     
            
    #endregion
        
    }
    }
     
     
    namespace 
    builder
    {
        static class 
    Program
        
    {
            
    /// <summary>
            /// Главная точка входа для приложения.
            /// </summary>
            
    [STAThread]
            static 
    void Main()
            {
                
    Application.EnableVisualStyles();
                
    Application.SetCompatibleTextRenderingDefault(false);
                
    Application.Run(new Form1());
            }
        }
    }
    Сохраняем это в .txt файл, создаем новый проект — наш компилятор. В его ресурсы добавляем .txt файл.
    Меняем необходимый динамический текст на какой-нибудь другой, у меня это %_form_caption_%
    Т.е. в ресурсах строчку this.Text = "Form1"; надо поменять на this.Text = "%_form_caption_%";

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

    [​IMG]

    Теперь дизайним нашу форму как хотим, ставим textbox и button.
    Обработчик нажатия кнопки:

    PHP:
    private void Button1Click(object senderEventArgs e)
            {
                
    using (Stream stream Assembly.GetExecutingAssembly()
                                   .
    GetManifestResourceStream("builder.Resources.res.txt"))
                {
                    if (
    stream != null)
                        
    using (var reader = new StreamReader(stream))
                        {
                            
    string result reader.ReadToEnd().Replace("%_form_caption_%"textBox1.Text.Replace(""", "\""));
                            var 
    providerOptions = new Dictionary<stringstring>
                                                      {
                                                          {
    "CompilerVersion""v3.5"}
                                                      };
                            
    CompilerResults results;
                            
    using (var provider = new CSharpCodeProvider(providerOptions))
                            {
                                var 
    Params = new CompilerParameters OutputAssembly Directory.GetCurrentDirectory() + "/build.exe"GenerateExecutable trueCompilerOptions "/t:winexe" };
     
                                
    Params.ReferencedAssemblies.Add("System.Windows.Forms.dll");
                                
    Params.ReferencedAssemblies.Add("System.dll");
                                
    Params.ReferencedAssemblies.Add("System.Drawing.dll");
                                
    results provider.CompileAssemblyFromSource(Paramsresult);
                            }
     
                            if (
    results.Errors.Count == 0)
                            {
                                
    MessageBox.Show("Компиляция успешно завершена!""Compilation"MessageBoxButtons.OKMessageBoxIcon.Asterisk);
                            }
                            foreach (
    CompilerError compilerError in results.Errors)
                            {
                                
    MessageBox.Show(string.Format("Ошибка: {0}"compilerError.ErrorText));
                            }
                        }
                }
                }
    Давайте разберем этот код.
    Начнем со строчки:
    Она создает поток данных, в котором находится содержимое нашего файла с исходниками.
    Важно: builder — необходимо поменять на namespace нашего компилятора
    res.txt — на имя вашего ресурса (.txt файла).

    Далее:
    В этой строчке происходит формирование новых значений, замена статического %_form_caption_% на динамический textBox1.Text. Обратите внимание на Replace(""", "\"") — это экранирование кавычек. Если пользователь введет что-то, содержащее кавычки, например Hello, "user", то в новом исходнике он будет выглядеть как
    и это вызовет синтаксическую ошибку.

    Дальше идет копипаст с MSDN, его нет смысла объяснять. Обращу внимание только на следующие строчки:
    • CompilerOptions = "/t:winexe" — так как мы генерируем не консольное, а WinForms приложение, то необходимо указать это компилятору напрямую. В противном случае на программе из выхода мы получим консольное приложение, поверх которого запустится наше.
    • Params.ReferencedAssemblies.Add("System.Windows.Forms.dll");
      Params.ReferencedAssemblies.Add("System.dll");
      Params.ReferencedAssemblies.Add("System.Drawing.dll");
      — Все using’и необходимо добавлять только так, иначе при компиляции программа не сможет их найти

    Вот вообщем-то и все, остальное я думаю и так понятно.
    Результат:
    [​IMG]
    [​IMG]

    Скачать исходники проекта и компилированную версию:
    http://www.box.com/s/6buh0qj7bspka5jfljez

    Статья не моя. Взято с:
    http://www.bafoed.net/post/365/

    p.s
    От себя лично, давно когда я писал возник вопрос. Обратился к автору :
    - как добавить импорт юзер32.длл?
    я про билдер, ибо при компиляции дллимпорт будет нот фаунд. А автор этой статьи писал , что :
    – Все using’и необходимо добавлять только так, иначе при компиляции программа не сможет их найти
    Вот и вопрос как добавить юсинг для импорта?

    - Params.ReferencedAssemblies.Add("System.Runtime.InteropServices.dll");
    аналогично для каждого используемого using'а в билде.
     
    2 фев 2015
    2 пользователям это понравилось.

Поделиться этой страницей

Загрузка...