Metrika

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

20 июля 2011 г.

C#: как запустить приложение из кода

Для того, что бы запустить приложение из кода, существует класс System.Diagnostics.Process.
Я запускал консольное приложение через WEB-страницу. То, что консольное приложение выводит в стандартный вывод надо было собирать в лог-файл. Весь код страницы приводить не буду, приведу только ту часть, которая запускает приложение и пишет лог:

private string path_log = "C:\\parser\\"; // Папка, где лежат логи парсера
private string path_ex = "C:\\parser\\log\\"; // Папка, где лежит экзешник парсера
private string file_name = "log.txt"; // Лог-файл
private System.IO.StreamWriter sw_log = null;
private System.Diagnostics.Process parser = null;

private void StartParser()
{
        parser = new Process();
        parser.StartInfo.FileName = path_ex + "parser.exe";
        parser.StartInfo.UseShellExecute = false;
        // Указываем, что будем хватать стандартный вывод
        parser.StartInfo.RedirectStandardOutput = true;
        // А так же кодировку, в которой данные выходят в стандартный вывод
        parser.StartInfo.StandardOutputEncoding = System.Text.Encoding.UTF8;
        parser.StartInfo.CreateNoWindow = true;
        parser.StartInfo.WorkingDirectory = path_ex;
        // ВАЖНОЕ СВОЙСТВО!! Без него не будет срабатывать событие parser.Exited
        parser.EnableRaisingEvents = true;
        // Событие, которое срабатывает, когда в стандартный вывод поступает инфа
        parser.OutputDataReceived += new DataReceivedEventHandler(parser_OutputDataReceived);
        parser.Exited += new EventHandler(parser_Exited);
        // ПУСК!
        parser.Start();

        sw_log = new System.IO.StreamWriter(path_log + "\\" + file_name + ".txt");
        // Говорим, что пора ловить данные из стандартного вывода
        parser.BeginOutputReadLine();
        // Возвращаю ID процесса      
        log_content.InnerHtml = string.Format("Parser process ID: {0}", parser.Id);
}

// Пишем стандартный вывод процесса в лог-файл. 
// Я сделал, что бы файл после каждой строчки флашился, мне просто так надо было, не принципиально
private void parser_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
        if (!String.IsNullOrEmpty(e.Data))
        {
            sw_log.WriteLine(e.Data);
            sw_log.Flush();
        }
}

// Закрыаем все и освобождаем
private void parser_Exited(object sender, EventArgs e)
{
        parser.Close();
        parser.Dispose();

        sw_log.Close();
        sw_log.Dispose();
}

В общем все. Из возможно полезного в классе Process есть метод WaitForExit() - который будет ждать, когда запускаемый процесс завершит работу. Так же как стандартный вывод можно ловить инфу из вывода ошибки, для этого есть событие ErrorDataReceived и метод BeginErrorReadLine. Так же там много всякой отладочной инфы по процессу. Подробности тут: http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx.

23 июня 2011 г.

C#: как получить символ по коду UTF-8

Мне нужно было из строки удалить символ, который имел код UTF-8 8232. Думал получить по коду переменную типа string и с помощью метода Replace заменить на пустую строку.
Что бы получить строку по коду, можно воспользоваться методом:
System.Text.Encoding.UTF8.GetString
Метод принимает массив byte[], соответственно код 8232 нельзя туда подсунуть, т.к. он больше максимального байта. Я подумал, может, если я разобью этот код на два байта, то все получиться, т.е. сделал так:
string str = System.Text.Encoding.UTF8.GetString(new byte[] { 0x20, 0x28 }, 0, 2);
Но в итоге, в переменной str оказывалось значение " (". Совсем не то, что нужно.
Погуглив нашел решение, надо взять не код в таблице символов, а строку, в которую кодируется этот символ в URL. В моем случае - это строка %E2%80%A8 и выполнить следующий метод:
string str = Uri.UnescapeDataString("%E2%80%A8");
Тогда в str окажется необходимый символ. И далее можно с ним работать строковыми методами.

18 марта 2011 г.

Взаимодействие с OLAP кубами (SSAS 2008) на C#

Работу с данными рассматривать не буду, потому что сам еще не пробовал.
Для того, что бы работать с кубами из кода необходимо скачать библиотеку ADOMD.NET. Забирать надо ADOMD.NET.msi. Установить ее. Далее, в VS добавить ее в проект (на иконке проекта тыкаем правой кнопкой и выбираем Add Reference...). Я работал на VS 2010 и после установки библиотеки я ее не нашел на вкладке .NET окна Add Reference, поэтому пошел на вкладку Browse и добавил ее руками. Выбирать надо вот этот файл C:\Program Files\Microsoft.NET\Adomd.NET\80\Microsoft.AnalysisServices.AdomdClient.dll.
Классы, необходимые для соединения к кубам и отправки им команд, находятся в пространстве имен Microsoft.AnalysisServices.AdomdClient.
Соединиться с БД (имеется в виду БД кубов) и выполнить команду можно следующим образом:

            AdomdConnection cnn = null;
            try
            {
                cnn = new AdomdConnection("Provider=MSOLAP;  DataSource=server_ip_or_name;Initial Catalog=db_name");
                cnn.Open();

                AdomdCommand cmd = cnn.CreateCommand();
                cmd.CommandType = System.Data.CommandType.Text;
                cmd.CommandText = command;

                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                 // Обработка ошибки
            }
            finally
            {
                cnn.Close();
            }
Как я писал выше, я не пробовал еще работать с данными кубов из кода, но таким кодом точно можно отпроцессить куб, разбить меру на партиции и т.п. Соответствующая команда в формате XMLA подставляется вместо переменной command. Опять же, я пока не разбирался можно ли туда передать MDX и как работать с ответом.
Небольшой хинт: для того, что б написать команду к кубу для какой-либо операции, не обязательно напрягать голову, т.к. в Management Studio можно сгенерить скрипт команды. Например, что бы сгенерить команду для процессинга куба необходимо на кубе тыкнуть правой кнопкой, далее Porcess и в открывшемся окне нажать кнопку Script, она будет вверху. Скрипт сгенериться в новое окно запроса. Так же можно сгенерить скрипт для команды Merge для партиций меры. Так же, для элементов куба можно сгенерить команды CREATE, ALTER и DELETE. У кубов, партиций и измерений есть пункт в меню Script cube as, Script partition as, Script dimension as.

3 февраля 2011 г.

Изменение доменного имени сайта

Для того, что бы корректно (с точки зрания поисковых машин) перенести сайт с одного доменного имени на другое, нужно настроить переадреcацию с помощью кода перенаправления HTTP 301 (Moved Permanently). В заголовке ответа Location указывается, куда была перенесена страница.

В C# код выглядит вот так: 
string location = "new_name";
Response.Clear();
Response.StatusCode = 301;
Response.AddHeader("Location", location);
Response.End();
Код нужно вставить в Global.asax в метод  Application_BeginRequest.

Причем, если написать вот так:
Response.Headers["Location"] = location;
То будет возникать исключение: This operation requires IIS integrated pipeline mode

В своей статье Редирект 301 (Moved Permanently) в IIS 7 я более подробно описываю способы редиректа в IIS 7. 




27 января 2011 г.

Доступ к MySQL через SSH-туннель в .NET

Как то мне очень надо было реализовать такую возможность, вот нашел статью: Access MySQL Through SSH Tunnel in a Windows .NET Application, к сожалению ссылка перестала работать, поэтому пришлось поискать в своем старом коде.

Я его давно не запускал, но, думаю, он направит в нужном направлении. Для работы нужна библиотека: http://www.tamirgal.com/blog/page/SharpSSH.aspx , там можно качнуть ее в исходниках или в бинарниках. Ссылки в глаза не бросаются, поэтому даю тут ссылку на бинарник: SharpSSH-1.1.1.13.bin.zip

Далее привожу код консольного приложения, которое соединяется с MySQL через SSH-тунель:
 
using System;
using System.Collections.Generic;
using System.Text;

using Tamir.SharpSsh.jsch;
using MySql.Data.MySqlClient;

namespace TestSSHTunnel
{
    class Program
    {
        static void Main(string[] args)
        {
            Session session;
         MySqlConnection conn = null;

            try
      {
       //Create a new JSch instance
       JSch jsch = new JSch();//Create a new SSH session
                string host = "u196.ssh.masterhost.ru"; //url
       string user = "ssh_user"; //ssh username
       string pass = "ssh_pswd"; //ssh password
       int sshPort = 22; //ssh port
                int rPort = 3306;
                int lPort = 3306; 

                session = jsch.getSession(user, host, sshPort);
       session.setHost(host);
       session.setPassword(pass);
       UserInfo ui = new MyUserInfo();
       session.setUserInfo(ui);
       session.connect();
     
       // Set port forwarding on the opened session
                session.setPortForwardingL(lPort, "u196.mysql.masterhost.ru", rPort);
                
       if (session.isConnected())
       {
        try
        {
                        string dbhost = "localhost";
                        string dbuser = "db_user";
                        string dbpass = "db_pswd";
                        string dbdatabase = "db_name";
         string connStr = String.Format("server={0};user id={1}; password={2}; database={3}; pooling=false",
          dbhost, dbuser, dbpass, dbdatabase);
     
         // Create a MySql Connection
         conn = new MySqlConnection(connStr);
         conn.Open();
         conn.ChangeDatabase(dbdatabase);
        }
        catch (Exception ex)
        {
         Console.WriteLine(ex.Message);
         session.disconnect();
        }
        finally
        {
         conn.Close();
        }
       }
      }
      catch (Exception ex)
      {
       Console.WriteLine(ex.Message);
      }
        }
    }

    public class MyUserInfo : UserInfo
    {
        /// 
        /// Holds the user password
        /// 
        private String passwd;

        /// 
        /// Returns the user password
        /// 
        public String getPassword() { return passwd; }

        /// 
        /// Prompt the user for a Yes/No input
        /// 
        /// 
        /// 
        public bool promptYesNo(String str)
        {
            return true;
        }

        /// 
        /// Returns the user passphrase (passwd for the private key file)
        /// 
        /// 
        public String getPassphrase() { return null; }

        /// 
        /// Prompt the user for a passphrase (passwd for the private key file)
        /// 
        /// 
        /// 
        public bool promptPassphrase(String message) { return true; }
        
        /// 
        /// Prompt the user for a password
        /// 
        /// 
        /// 
        public bool promptPassword(String message) { return true; }

        /// 
        /// Shows a message to the user
        /// 
        /// 
        public void showMessage(String message) { }

    }
}

Еще тогда, когда мне нужно было решить эту проблему, я нашел библиотеку http://granados.sourceforge.net/ , но по каким-то причинам от нее отказался. Тут http://social.msdn.microsoft.com/Forums/en-US/e554ebc5-7b74-415f-8ac8-d5dc3dcaf1c5/looking-for-granados-ssh-example?forum=netfxnetcom вроде бы описывается как с ней работать.