воскресенье, мая 15, 2011

Sharepoint 2010 и русские имена столбов списков

Если вы сталкивались с написанием CAML запросов для Sharepoint 2010 то знаете, что обращение к столбцам с русскими именами достаточно затруднительно т.к. если столбец создавался изначально с русским именем то его внутреннее имя будте представленно закодированным значением. Например если вы назвали свой столбец "Столбец" то его внутренним именем будет : _x0421__x0442__x043e__x043b__x0431__x0435__x0446_.
Я часто сталкиваюсь с такой белибердой и выяснил что это на самом деле HEX значение Unicode символов окруженные и _ . Вооружившись этим знанием я написал две функции для преобразования строки туда и обратно:

public static class NameConverter
    {
        /// <summary>
        /// Расшифровать имя из внутреннего представления
        /// </summary>
        /// <param name="val">Закодированое имя</param>
        /// <returns>Расшифрованое значение</returns>
        public static string DecodeName(string val)
        {
            val = val.Replace("ows", "");
            if (!val.Contains("_x")) return val;

            var sb = new StringBuilder();
            val = val.Replace("_", "");
            var parts = val.Split(new[] { 'x' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string part in parts)
            {
                int v = int.Parse(part, NumberStyles.HexNumber);
                var c = (char)v;
                sb.Append(c);
            }
            return sb.ToString();
        }
        /// <summary>
        /// Закодировать русскую строку
        /// </summary>
        /// <param name="name">Имя для кодирования</param>
        /// <returns>Закодированое значение</returns>
        public static string EncodeName(string name)
        {
            var sb = new StringBuilder();
            for (int i = 0; i < name.Length; i++)
            {
                sb.AppendFormat("_x{0:x4}_", (int)name[i]);
            }
            return sb.ToString();
        }
    }

суббота, апреля 30, 2011

Удаление элементов из SPList через ProcessBatchData

Всем разработчикам Sharepoint 2010 (да и вообще любой версии Sharepoint или MOSS) известна ситуация с медленной работой объектной модели и большом времени поиска\модификации через нее.
Так вот мне однажды пришлось писать систему массового удаления данных из разных списков сайта под управлением Sharepoint 2010. Решения через SPListItem.Delete(), SPList.Items.DeleteItem(idx) и даже SPList.Items.DeleteItemById(itemId) давали жуткие показатели времени работы (удаление 100 элементов за 60000(!)-120000(!) секунд). И тут я вспомнил про волшебную возможность SPWeb.ProcessBatchData которая позволяет выполнять CAML запросы напрямую, минуя слой объектной модели.( Забегая вперед скажу что такое решение мне дало производительность в районе ~650сек на 5000 записей.)
Что-ж покопав документацию на сайте Microsoft (http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spweb.processbatchdata.aspx) я подумал что все тривиально и создал свое первое решение. Радостно посапывая я ткнул в кнопочку деплой и запустил свой код. Как ни странно код рухнул. Не буду описывать процесс поиска ошибки и сразу скажу: Разбивайте свои запросы на пачки! Не больше 180 запросов в одном теге . Лично я разбиваю свои запросы в пачки по 100.
Поправив код и сделав разбиение на пачки я запустил все снова. Как и ожидалось пепелац не взлетел. А я поимел совершенно смутившую меня ошибку ArgumentException. Тут надо отметить удивительную абсолютную невразумительности сообщений Sharepoint об ошибках.
Вот к примеру как выглядел мой Expcetion
Exception type: ArgumentException
[Message] = "0x80070057"
[ParamName] = ""
[Data] = "System.Collections.ListDictionaryInternal"
[TargetSite] = "Void GetListItemDataWithCallback2(Microsoft.SharePoint.Library.IListItemSqlClient, System.String, System.String, System.String, System.String, Microsoft.SharePoint.Library.SAFEARRAYFLAGS, Microsoft.SharePoint.Library.ISP2DSafeArrayWriter, Microsoft.SharePoint.Library.ISPDataCallback, Microsoft.SharePoint.Library.ISPDataCallback, Microsoft.SharePoint.Library.ISPDataCallback, Microsoft.SharePoint.Library.ISPDataCallback, Microsoft.SharePoint.Library.ISPDataCallback, Boolean ByRef)"
[StackTrace] = "   в Microsoft.SharePoint.Library.SPRequestInternalClass.GetListItemDataWithCallback2(IListItemSqlClient pSqlClient, String bstrUrl, String bstrListName, String bstrViewName, String bstrViewXml, SAFEARRAYFLAGS fSafeArrayFlags, ISP2DSafeArrayWriter pSACallback, ISPDataCallback pPagingCallback, ISPDataCallback pPagingPrevCallback, ISPDataCallback pFilterLinkCallback, ISPDataCallback pSchemaCallback, ISPDataCallback pRowCountCallback, Boolean& pbMaximalView)
   в Microsoft.SharePoint.Library.SPRequest.GetListItemDataWithCallback2(IListItemSqlClient pSqlClient, String bstrUrl, String bstrListName, String bstrViewName, String bstrViewXml, SAFEARRAYFLAGS fSafeArrayFlags, ISP2DSafeArrayWriter pSACallback, ISPDataCallback pPagingCallback, ISPDataCallback pPagingPrevCallback, ISPDataCallback pFilterLinkCallback, ISPDataCallback pSchemaCallback, ISPDataCallback pRowCountCallback, Boolean& pbMaximalView)
   в Microsoft.SharePoint.SPListItemCollection.EnsureListItemsData()
   в Microsoft.SharePoint.SPListItemCollection.GetEnumerator()
   в MRR.DVIZ.Workflows.ClearFormsWorkflow.ClearFormsWorkflow.FindRunning(Object sender, EventArgs e)
   в System.Workflow.ComponentModel.Activity.RaiseEvent(DependencyProperty dependencyEvent, Object sender, EventArgs e)
   в System.Workflow.Activities.CodeActivity.Execute(ActivityExecutionContext executionContext)
   в System.Workflow.ComponentModel.ActivityExecutor`1.Execute(T activity, ActivityExecutionContext executionContext)
   в System.Workflow.ComponentModel.ActivityExecutor`1.Execute(Activity activity, ActivityExecutionContext executionContext)
   в System.Workflow.ComponentModel.ActivityExecutorOperation.Run(IWorkflowCoreRuntime workflowCoreRuntime)
   в System.Workflow.Runtime.Scheduler.Run()"
[HelpLink] = ""
[Source] = ""
Поиски google ничего вразумительного не дали. Правда у меня зародилось смутное сомнение в том что я что-то не так делаю с форматом CAML запроса. Я даже не могу сказать что мена натолкнуло на эту мысль, интуиция если только.
Не буду рассказывать свои танцы вокруг подбора нового формата. скажу лишь что:
<Batch OnError="Continue">

<SetList>b15da36c-6ed8-4fe1-bbcc-89a1996c1dbe</SetList>
<Method ID="1" Cmd="Delete"><Field Name="ID">638</Field></Method>
<Method ID="2" Cmd="Delete"><Field Name="ID">639</Field></Method>
<Method ID="3" Cmd="Delete"><Field Name="ID">648</Field></Method>
<Method ID="4" Cmd="Delete"><Field Name="ID">649</Field></Method>
<Method ID="5" Cmd="Delete"><Field Name="ID">650</Field></Method>
<Method ID="6" Cmd="Delete"><Field Name="ID">651</Field></Method>
<Method ID="7" Cmd="Delete"><Field Name="ID">652</Field></Method>
<Method ID="8" Cmd="Delete"><Field Name="ID">653</Field></Method>
<Method ID="9" Cmd="Delete"><Field Name="ID">654</Field></Method>
<Method ID="10" Cmd="Delete"><Field Name="ID">655</Field></Method>
<Method ID="11" Cmd="Delete"><Field Name="ID">656</Field></Method>
<Method ID="12" Cmd="Delete"><Field Name="ID">657</Field></Method>

</Batch>
не красиво но не правильно. Надо:
<?xml version="1.0" encoding="UTF-8"?>

<Batch OnError="Return">
<Method ID="1,Del"><SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">20</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="2,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">21</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="3,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">22</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="4,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">23</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="5,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">24</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="6,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">25</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="7,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">26</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="8,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">27</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="9,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">28</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="10,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">29</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="11,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">30</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="12,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">31</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>

</Batch>
Код создающий такую структуру и выполняющие его в пачках (listMods - IEnumerable с ИД строк для уделания):
List<string> listBatch = new List();

StringBuilder batch = new StringBuilder();
StringBuilder log = new StringBuilder();

if (!string.IsNullOrEmpty(listTitle) && listMods != null && listMods.Count > 0)
{
    log.AppendFormat("Очистка списка {0}. Удалеине {1} элементов.", listTitle, listMods.Count);
    batch.AppendLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
    batch.AppendLine("<Batch OnError=\"Return\">");
    int batchSize = 0;
    foreach (int toDelete in listMods)
    {
        batchSize++;
        batch.AppendFormat(
            "<Method ID=\"{0},Del\"> {2} <SetVar Name=\"ID\">{1}</SetVar><SetVar Name=\"Cmd\">Delete</SetVar></Method>",
            batchSize, toDelete,
            string.Format("<SetList Scope=\"Request\">{0}</SetList>",
                            queryRoot.Lists[listTitle].ID))
            .AppendLine();

        if (batchSize >= 100)
        {
            batch.AppendLine("</Batch>");
            listBatch.Add(batch.ToString());
            batchSize = 0;

            batch = new StringBuilder(batch.Capacity);
            batch.AppendLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            batch.AppendLine("<Batch OnError=\"Return\">");
        }
    }
    batch.AppendLine("</Batch>");
    listBatch.Add(batch.ToString());


    foreach (string cmd in listBatch)
    {
        try
        {
            log.Append("Исполнение запроса :").AppendLine().Append(cmd).AppendLine();
            string cmd1 = cmd;
            SPSite siteColl = currentSite;
            SPWeb site = currentWeb;
            SPSecurity.RunWithElevatedPrivileges(delegate()
                                                        {
                                                            using (
                                                                SPSite ElevatedsiteColl =
                                                                    new SPSite(siteColl.ID))
                                                            {
                                                                using (
                                                                    SPWeb ElevatedWeb =
                                                                        ElevatedsiteColl.OpenWeb(
                                                                            site.ID))
                                                                {
                                                                    ElevatedWeb.ProcessBatchData(cmd1);
                                                                }
                                                            }
                                                        });                                
        }
        catch (Exception e)
        {
            var ex = new ApplicationException("Ошибка при исполнении комманды: " + cmd, e);
            throw ex;
        }
    }
}

среда, апреля 20, 2011

Chrome\Firefox + Silverlight + CSS Styles

Если вы на своей странице используете silverlight и попытаетесь изменить значение атрибута стиля position то Chrome\Firefox заново создадут и загрузят ваше приложение.
Обойти это не получилось.

четверг, апреля 07, 2011

Настройка приложения Sharepoint 2010 для авторизации форм (FBA) с хранением данных в SQLServer

Для настройки приложения Sharepoint 2010 для работы с авторизацией форм FBA (forms based authentication) важно знать что приложение должно быть настроено для работы через Claims Based Authentication.

Самый простой вариант - при создании приложения указать Claims based [Авторизация на утверждениях] (по умолчанию приложение создается в режиме Basic authentication).
Если-же у вас уже имеется приложение для которого надо включить FBA вам придется конвертировать приложение. Сложного в этом ничего нет, но стоит помнить что конвертация НЕОБРАТИМА. 
Для конвертации приложения из Basic в Claims based вам необходимо открыть Powershell для Sharepoint 2010 с правами администратора и там выполнить команды:

$app=Get-SPWebApplication("http://site") 
$app.UseClaimsAuthentication = 1 
$app.Update() 
$app.ProvisionGlobally()

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


c:\Windows\Microsoft.NET\Framework64\v2.0.50727\aspnet_regsql.exe

В своем случае я указал имя БД SharepointAuthDB, и учетные данные пользователя от которого у меня работает Sharepoint для простоты настройки администратором домена/сервера, а так-же из-за стойкой неприязни к хранению имени пользователя и пароля доступа в строке подключения.  Для создания строки подключения нам надо запомнить имя сервера, имя БД, и способ авторизации пользователя.

Далее открываем Управление службами IIS и в настройках сервера  нажимаем на ConnectionStrings(Строки подключения) и там нажимаем на "Создать". В открывшемся диалоге вводим имя сервера,имя БД (SharepointAuthDB в моем случае) и способ авторизации пользователя которые вы указывали в мастере регистрации. Так-же необходимо проверить что данный пользователь имеет права dbo и public на базу с пользователями. Так-же вам надо указать имя строки подключения (я указал SqlAuthConnection) и запомнить его.

Далее нам необходимо модифицировать 3 файла web.config

  1. Web.config от приложения Sharepoint которые вы настраиваете для авторизации форм Обычно он расположен по адресу: C:\inetpub\wwwroot\wss\VirtualDirectories\80 (можно посмотреть в настройках узла)

        <roleManager defaultProvider="c" enabled="true" cacheRolesInCookie="false">
          <providers>
            <add name="c" type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthRoleProvider, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
            <add connectionStringName="SharepointAuthDB" applicationName="/" description="Stores and retrieves roles from SQL Server" name="FBARole" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
          </providers>
        </roleManager>
        <membership defaultProvider="i">
          <providers>
            <add name="i" type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthMembershipProvider, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
            <add connectionStringName="SharepointAuthDB" passwordAttemptWindow="5" enablePasswordRetrieval="false" enablePasswordReset="false" requiresQuestionAndAnswer="true" applicationName="/" requiresUniqueEmail="true" passwordFormat="Hashed" description="Stores and Retrieves membership data from SQL Server" name="FBA" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
          </providers>
        </membership>
  2. Файл web.config от SharePoint Central Administration Обычно он расположен по адресу: C:\inetpub\wwwroot\wss\VirtualDirectories\26719 (можно посмотреть в настройках узла)
    В этом файле после тега </SafeControls> добавить секцию
    <PeoplePickerWildcards>
    <clear />
    <add key="AspNetSqlMembershipProvider" value="%" />
    <add key="FBA" value="%" />
    <add key="LdapMembershipProvider" value="*"/>
    <add key="LdapRoleManager" value="*"/>
    </PeoplePickerWildcards>

    и перед тегом </system.web> добавить секцию:
    <roleManager defaultProvider="AspNetWindowsTokenRoleProvider" enabled="true" cacheRolesInCookie="false">
    <providers>
    <add connectionStringName="SharepointAuthDB" applicationName="/" description="Stores and retrieves roles from SQL Server" name="FBARole" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </providers>
    </roleManager>
    <membership defaultProvider="FBA">
    <providers>
    <add connectionStringName="SharepointAuthDB" passwordAttemptWindow="5" enablePasswordRetrieval="false" enablePasswordReset="false" requiresQuestionAndAnswer="true" applicationName="/" requiresUniqueEmail="true" passwordFormat="Hashed" description="Stores and Retrieves membership data from SQL Server" name="FBA" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </providers>
    </membership>


  3. Файл web.config от Sharepoint Security Token Service (STS)Обычно он расположен по адресу: C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\WebServices\SecurityToken В этот файл необходимо добавить секцию:


    <system.web>

    <roleManager defaultProvider="c" enabled="true" cacheRolesInCookie="false">

    <providers>

    <add name="c" type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthRoleProvider, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />

    <add connectionStringName="SharepointAuthDB" applicationName="/" description="Stores and retrieves roles from SQL Server" name="FBARole" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />

    </providers>

    </roleManager>



    <membership defaultProvider="i">
    <providers>
    <add name="i" type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthMembershipProvider, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
    <add connectionStringName="SharepointAuthDB" passwordAttemptWindow="5" enablePasswordRetrieval="false" enablePasswordReset="false" requiresQuestionAndAnswer="true" applicationName="/" requiresUniqueEmail="true" passwordFormat="Hashed" description="Stores and Retrieves membership data from SQL Server" name="FBA" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </providers>
    </membership>
    </system.web>
Далее необходимо открыть приложение Sharepoint Central Administration  и нам в настройках приложения нажать "Поставщики проверки безопасности", выбрать необходимую зону и в настройках зоны включить галочку "Разрешить проверку подлинности на основе форм (FBA)".

Далее в поле "Имя поставщика контроля членства в ASP.NET" (membership provider) задать FBA , а в поле "Имя поставщика контроля членства в ASP.NET" (role provider) задать FBARole (если вы не меняли имя поставщиков в XML а указали как я написал). А так-же проверить что разрешен анонимный доступ (для обеспечения работоспособности сервиcов Sharepoint)

Нам осталось совсем немного. Для проверки корректности работы авторизации форм надо создать пользователей в базе данных. (ВНИМАНИЕ из-за особенностей настройки Membreship

Providers для Sharepoint 2010 управлять пользователями через стандартную оснастку IIS не получится, я могу посоветовать написать свой менеджер пользователей или воспользоваться программой MembershipSeeder)

Теперь осталось перезапустить IIS. Зайдти в Sharepoint Central Admin и в настройках приложения задать политику доступа для пользователей FBA.


Обрушение потолка в "Москва сити"


Сегодня 7 апреля 2010 гола приблизительно в 09:10 утра произошло обрушение потолка вестибюля выхода со станции метро "Выставочная". В данном вестибюле так-же расположен вход в открывшийся две недели назад торговый цента Амфи Сити Молл расположенный на территории бизнес комплекса Москва-Сити. Во время обрушения в вестибюле станции было достаточно много людей, лишь по счастливой случайности никто не пострадал. Из дырки образовавшейся на месте пролома тут-же начала теч вода (лужу отчетливо видно на фотографиях).




среда, апреля 06, 2011

Sharepoint 2010 и исключение file not found exception

Маленький совет: Если вы пишите приложение использующее объектную модель Sharepoint и при попытке открыть сайт как в примере:
using(SPSite sirte=new SPSite("http://site"){
......
}
И получаете исключение File not fount exception хотя сайт в браузере открывается - проверьте две вещи:

  1. Build platform для проекта должен быть .NET Framework 3.5
  2. Проект обязательно собираться для x64 платформы

суббота, октября 23, 2010

Где жить в командировке.

Часто бывает так: еще вчера вы работали в офисе и нечего не предвещало изменений. Но вот к вам подходит ваш начальник и говорит, что, завтра вы срочно выезжаете командировку. И вот вы уже загружены решением вопросов связанных с этой бизнес-поездкой. И главным вопросом является "Где жить?".
По своему опыту знаю - ваш начальник будет рад если вы предложите ему хороший вариант проживания. Как оказалось даже элитные квартиры посуточно будут стоить вам дешевле чем отели и гостиницы. А уж наличие холодильника и кухни в длительной поездке является весомым преимуществом. Как показала практика, на те деньги что запрашивает у вас отель за сутки можно снять и квартиру, и машину, и все-равно выйдет дешевле.
Удачных вам поездок.

Современные интерьеры домов - крайне полезный ресурс по дизайну интерьеров домов и квартир.

суббота, октября 16, 2010

Экономия

Тут начал заниматься построением профиля расходов своей семьи - ибо понял что денег уходит много и не понятно куда. Начал все траты выписывать в отдельной программе, которую сам по случаю и написал. Теперь вот ищу нетривиальные способы сэкономить.
Вот первое место на которое я обратил внимание: интернет магазин китайских телефонов - место где можно найти iPhone за 5000руб.
Рекомендую почитать подборку интересных статей
Прогнозы на спорт для любителей тотализатора

пятница, октября 15, 2010

Классическая мягкая мебель как часть интерьера

Мягкая мебель присутствует во всех местах которые мы воспринимаем как комфортные – рестораны, клубы, в конце концов, дом. Данная мысль пришла мастерам еще в начале средних веков – когда зарождались понятия «комфорт» и «классика». С тех пор многое изменилось, но видение комфортной мебели как предмета создающего основное восприятие интерьера сохранилось и в наше время. Классическая мягкая мебель проверенных временем брендов создает комфортное восприятие пространства, в котором она установлена. Этот проверенный временем тезис работает как для дома, так и для офисных помещений. Не забывайте, что впечатление у клиента создается в первый момент пребывания в вашем офисе. Классическая мягкая мебель создает впечатления уверенности в будущем, устойчивости традиций и гармонии в намерениях.

Всем кто хочет увеличить свою конкурентоспособность советую Скачать ГОСТы бесплатно.
Бюджетный и люксовый отдых в Анапе. полная информация на сайте : http://anapa-w.ru

Производство и сертификация

Сегодня я хочу поговорить о сертификации. Итак вы развернули свое производство (будь то производственный конвейер или маленькое домашнее производство). и начали предлагать свой товар на реализацию в розничных точках. Первое что вы обнаружите: все стали просить сертификаты на товар\продукцию. Это повышает гарантии со стороны поставщика и магазина по отношению к покупателю. И, как оказалось, это касается и товаров подлежащих добровольной сертификации. Таким образом сертификация продукции становится вашей целью на пути успешных продаж товара. А как только заходит речь о сертификации продукции становится необходимым соблюдать ГОСТы. Скачать ГОСТы бесплатно можно тут.
Если у вас возникли вопросы про комплексный ремонт квартир советую посетить сайт http://www.nivona.ru

четверг, октября 14, 2010

Life-Radio - Интерактивная интернет радиостация

Этот пост своего хайтек блога я хотел-бы посвятить очень качественному ресурсу найденному мною на просторах "великой всемирной помойки". Это радиостанция http://life-radio.ru/. Суть такая-же как и у обычной радиостанции, но с доступом через интернет. Очень порадовала возможность слушай эфир прям с главной страницы. Да и дизайн плеера встроенного в страницу очень приятно порадовал. Нагрузка на канал - вполне терпимая. Качество звука 128.
Еще из особенностей стоит отметить постоянный контакт со слушателями (вы можете связаться с дижеями и через асю и через скайп).
Еще раз повторю что сайт очень приятно порадовал.

Для тек кому понадобилось что-то из софта советую покопать сборник "лучшие программы". И ведь правда "лучшие", а главное БЕСПЛАТНЫЕ!!
Виагра - возможности и желания совпадают. Держи потенцию под контролем.

вторник, октября 12, 2010

Красивые обои на рабочий стол

Сегодня наткнулся на сайт с обоями для рабочего стола http://www.wallon.ru/ . На нем вы найдете огромное количество замечательных картинок - фонов на рабочий стол. Удобные галереи и главное есть возможность скачать картинку для разных разрешений экранов.
Нашел хорошее место где купить пластиковые формы для мыла российского производства.

Вечное ссылочное этап 2

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

  1. Вы публикуете ссылку на мой блог (на главную или любую из внутренних страниц)
  2. Пишите тут комментарий с ссылкой на ту страницу где размещена ссылки и на какую страницу вы хотите иметь ссылку с моего блога.
  3. Я пишу обзор на ваш сайт и дописываю в это сообщение как постовый ссылку. (это сделано для удобства контроля)
Каждый этап этой акции будет включать в себя 20-30 ссылок. Спешите успеть в новый набор. ;-)

Тем кому наскучил разговор о деньгах советую почитать цикл статей История автомобилей. Я нашел для себя много интересного

понедельник, октября 11, 2010

Полезности для Твиттерян

Сегодняшний пост своего хай тек блога я посвящу очень интересному сайту Universal Info.
Конкретно меня покорил раздел http://universall.info/twitter.php - тут собрано огромное количество информации посвященной Твитеру, его использованию и монетизации. Если вы решили что ваша социальная жизнь онлайн должна приносить доход - советую скачать размещенную на этом сайте книгу. Более подробной подборки информации по теме заработка в Твиттере я еще не видел. Однозначно МАСТ ХЕВ!
Новые автомобили в Волгограде для отправляющихся в путешествие или резидентов =)
Тем-же кто уже является счастливым обладателем немецкой машины советую посмотреть цена на запчасти Фольксваген . Там и по запчастям для Ауди тоже есть информация.

Подарки

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

Для тех кто хочет подарить мыло ручной работы - формы для мыла. Хороший ассортимент
А в подарок для себя вы можете глянуть на фото знаменитых девушек. Я разрешаю =)

понедельник, октября 04, 2010

Лучшая Trance музыка в MP3.

Я давно являюсь поклонником Tracne музыки. Гонял на опены еще когда Тимур Мамедов только начинал свое дело и aeroboard еще жив был. С тех пор времени много утекло выбрать что качать стало очень сложно. Для тех кто озадачен поиском трансовой музыки советую ресурс - "Лучшая Trance музыка в MP3." . Много хороших треков и биографий диджеев. Вобщем маст-хев для всех любителей транса! Have a nice trip!

А вот Новый альбом Король и шут для тех кто не любит транс но любит "потяжелее" и по "забористее" ;-)

среда, сентября 22, 2010

Видео наблюдение. Системы безопасности.

В современном хай тек мире главным гаджетом любого уважающего себя человека является система безопасности своей собственной квартиры. И правда в наше время есть огромное количество шпионских и противо-шпионских гаджетов, и почему-бы их не применить для защиты квартиры. Именно так подумали ребята из компании "Юникс" и сощдали уникальную по своим параметрам современную систему безопасности, включающую в себя видео наблюдение, биометрию и пожарную охрану. Все компоненты системы являются опциональными что позволяет создавать системы безопасности для конкретного клиента. Установка видеонаблюдения так-же является опциональной для каждого клиента.
Для тех кому хочется поднять немного денег советую узнать как заработать на блоге. Это бывает очень прибыльно.

Рекламные буклеты. Где сделать.

Тут недавно пришел мой старый друг и попросил помочь ему раскрутить его магазинчик.
Ну создать буклеты, банеры и прочее я ему помог. А вот печатать у себя дома рекламную продукцию - по моему абсолютная бредятина. Вот и встал вопрос - где печатать. Искали по нету долго. И вот нашли очень качественную оперативную полиграфию http://copyking.ru . Там можно заказать не только печать фото или буклетов, но также и флаеры, календари, пакеты и визитки.
Вызов Деда-мороза на дом, может организовать и тренники в детсаду на новый год. Счастья вам ;-)
Заодно рекомендую узнать про происхождение деда мороза. Вполне забавная легенда.

Винная комната. Традиция. Надежность. Стиль.

Каждый из мужчин когда-нибудь мечтал о том как он будет сидеть за своим рабочим столом в своем кабинете, у себя в особняке и во время важной встречи произнесет "Не хотели-бы вы отведать вина из моего винного погреба?".
Если задуматься то окажется, что, и места вполне достойна стать целью, и не так уж и много услий требуется. Начать присматривать винные стеллажи советую со стеллажей фирмы Howard Miller. Качественная , стильная мебель для винной комнаты в традиционном исполнении.
Для тех кто уже задумал серьезный ремонт советую узнать про оформление перепланировки у высококлассных специалистов риелторской компании "Диамант"