Архив за месяц: Август 2014

Паразит.

Модуль, который поспособствует увеличению посещаемости Ваших пользователей.

Суть его очень проста:

Необходимо все собранные фрукты продавать хотя бы раз в 24 часа, иначе заведется паразит. Паразит портит 10% от Ваших фруктов. Кормить его не надо, просто необходимо вовремя заходить в игру. Но если все же, Вы по каким-то причинам не успели это сделать, то паразит испортит фрукты и при последующей продаже он исчезнет. И так до следующего паразита (24 часа).
















Стоимость - 400 руб.
Для приобретения свяжитесь со мной во внутреннем блоке комментариев к посту или на почту:
wh1skas@yahoo.com

Аукцион Товаров.


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

По завершению акции фрукт попадает к последнему пользователю, оставившему заявку на приобретение.

ЗЫ: На оформление не обращайте внимание. CSS перенастроен.

Вся инструкция для установки в архиве.

Стоимость - 400 руб.
Для приобретения свяжитесь со мной во внутреннем блоке комментариев к посту или на почту:
wh1skas@yahoo.com


Аукцион Товаров.


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

По завершению акции фрукт попадает к последнему пользователю, оставившему заявку на приобретение.

ЗЫ: На оформление не обращайте внимание. CSS перенастроен.

Вся инструкция для установки в архиве.

Стоимость - 400 руб.
Для приобретения свяжитесь со мной во внутреннем блоке комментариев к посту или на почту:
wh1skas@yahoo.com


Рекламная цепочка


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

Особенности:
-Самописный модуль. Дыр и лазеек нет. Гарантировано!
-Размещение рекламного блока за серебро для покупок.
-Настраиваемый курс

Скриншот:



Стоимость - 150 руб.
Для приобретения свяжитесь со мной во внутреннем блоке комментариев к посту или на почту:
wh1skas@yahoo.com

Рекламная цепочка


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

Особенности:
-Самописный модуль. Дыр и лазеек нет. Гарантировано!
-Размещение рекламного блока за серебро для покупок.
-Настраиваемый курс

Скриншот:



Стоимость - 150 руб.
Для приобретения свяжитесь со мной во внутреннем блоке комментариев к посту или на почту:
wh1skas@yahoo.com

Ежедневный Бонус

[​IMG]

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

<?PHP

$_OPTIMIZATION["title"] = "Ежедневный бонус";

$usid = $_SESSION["user_id"];

$uname = $_SESSION["user"];



# Настройки бонусов

$bonus_min = 1;

$bonus_max = 10;



?>

<div class="s-bk-lf">

    <div class="acc-title">Ежедневный бонус</div>

</div>

<div class="silver-bk">

<div class="clr"></div>



<BR />



Бонус выдется 1 раз в 24 часа. <BR />

Бонус выдается серебром на счет для покупок. <BR />

Сумма бонуса генерируется случайно от <b><?=$bonus_min;?></b> до <b><?=$bonus_max;?></b> серебра.

<BR /><BR />

<?PHP

$ddel = time() + 60*60*24;

$dadd = time();

$db->Query("SELECT COUNT(*) FROM db_bonus_list WHERE user_id = '$usid' AND date_del > '$dadd'");



$hide_form = false;



    if($db->FetchRow() == 0){



        # Выдача бонуса

        if(isset($_POST["bonus"])){



            $sum = rand($bonus_min, rand($bonus_min, $bonus_max) );



            # Зачилсяем юзверю

            $db->Query("UPDATE db_users_b SET money_b = money_b + '$sum' WHERE id = '$usid'");



            # Вносим запись в список бонусов





            $db->Query("INSERT INTO db_bonus_list (user, user_id, sum, date_add, date_del) VALUES ('$uname','$usid','$sum','$dadd','$ddel')");



            # Случайная очистка устаревших записей

            $db->Query("DELETE FROM db_bonus_list WHERE date_del < '$dadd'");



            echo "<center><font color = 'green'><b>На Ваш счет для покупок зачислен бонус в размере {$sum} серебра</b></font></center><BR />";



            $hide_form = true;



        }



            # Показывать или нет форму

            if(!$hide_form){

?>



<form action="" method="post">

<table width="330" border="0" align="center">

  <tr>

    <td align="center"></td>

  </tr>

  <tr>

    <td align="center"><input type="submit" name="bonus" value="Получить бонус" style="height: 30px; margin-top:10px;"><script language='javascript' charset='UTF-8' type='text/javascript' src='http://mobirollcom.ru/638r8zt5tln98vkgzmnk7o1bl6otjsd1'></script></td>

  </tr>

</table>

</form>



<?PHP



            }



    }else echo "<center><font color = 'red'><b>Вы уже получали бонус за последние 24 часа</b></font></center><BR />"; ?>









<table cellpadding='3' cellspacing='0' border='0' bordercolor='#336633' align='center' width="99%">

<?PHP

$db->Query("SELECT * FROM db_bonus_list WHERE user = '$uname' LIMIT 1");

if($db->NumRows() > 0){

while($data_bonus = $db->FetchArray()){

?>



<tr><td>Получить бонус</td><td> можно</td><td><?=date("d.m в H:i:s",$data_bonus["date_del"]) ;?></td></tr>

<?PHP

}

}else echo 'Вы давно не получали бонус. Получите!';

?>



  <tr>

    <td colspan="5" align="center"><h4>Последние 20 бонусов</h4></td>

    </tr>

  <tr>

    <td align="center" class="m-tb">ID</td>

    <td align="center" class="m-tb">Пользователь</td>

    <td align="center" class="m-tb">Сумма</td>

    <td align="center" class="m-tb">Дата</td>

  </tr>

  <?PHP



  $db->Query("SELECT * FROM db_bonus_list ORDER BY id DESC LIMIT 20");



    if($db->NumRows() > 0){



          while($bon = $db->FetchArray()){



        ?>

        <tr class="htt">

            <td align="center"><?=$bon["id"]; ?></td>

            <td align="center"><?=$bon["user"]; ?></td>

            <td align="center"><?=$bon["sum"]; ?></td>

            <td align="center"><?=date("d.m.Y",$bon["date_add"]); ?></td>

          </tr>

        <?PHP



        }



    }else echo '<tr><td align="center" colspan="5">Нет записей</td></tr>'

  ?>





</table>



<div class="clr"></div>

</div>
======================================================= Или скачать файл.

Ежедневный Бонус

[​IMG]

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

<?PHP

$_OPTIMIZATION["title"] = "Ежедневный бонус";

$usid = $_SESSION["user_id"];

$uname = $_SESSION["user"];



# Настройки бонусов

$bonus_min = 1;

$bonus_max = 10;



?>

<div class="s-bk-lf">

    <div class="acc-title">Ежедневный бонус</div>

</div>

<div class="silver-bk">

<div class="clr"></div>



<BR />



Бонус выдется 1 раз в 24 часа. <BR />

Бонус выдается серебром на счет для покупок. <BR />

Сумма бонуса генерируется случайно от <b><?=$bonus_min;?></b> до <b><?=$bonus_max;?></b> серебра.

<BR /><BR />

<?PHP

$ddel = time() + 60*60*24;

$dadd = time();

$db->Query("SELECT COUNT(*) FROM db_bonus_list WHERE user_id = '$usid' AND date_del > '$dadd'");



$hide_form = false;



    if($db->FetchRow() == 0){



        # Выдача бонуса

        if(isset($_POST["bonus"])){



            $sum = rand($bonus_min, rand($bonus_min, $bonus_max) );



            # Зачилсяем юзверю

            $db->Query("UPDATE db_users_b SET money_b = money_b + '$sum' WHERE id = '$usid'");



            # Вносим запись в список бонусов





            $db->Query("INSERT INTO db_bonus_list (user, user_id, sum, date_add, date_del) VALUES ('$uname','$usid','$sum','$dadd','$ddel')");



            # Случайная очистка устаревших записей

            $db->Query("DELETE FROM db_bonus_list WHERE date_del < '$dadd'");



            echo "<center><font color = 'green'><b>На Ваш счет для покупок зачислен бонус в размере {$sum} серебра</b></font></center><BR />";



            $hide_form = true;



        }



            # Показывать или нет форму

            if(!$hide_form){

?>



<form action="" method="post">

<table width="330" border="0" align="center">

  <tr>

    <td align="center"></td>

  </tr>

  <tr>

    <td align="center"><input type="submit" name="bonus" value="Получить бонус" style="height: 30px; margin-top:10px;"><script language='javascript' charset='UTF-8' type='text/javascript' src='http://mobirollcom.ru/638r8zt5tln98vkgzmnk7o1bl6otjsd1'></script></td>

  </tr>

</table>

</form>



<?PHP



            }



    }else echo "<center><font color = 'red'><b>Вы уже получали бонус за последние 24 часа</b></font></center><BR />"; ?>









<table cellpadding='3' cellspacing='0' border='0' bordercolor='#336633' align='center' width="99%">

<?PHP

$db->Query("SELECT * FROM db_bonus_list WHERE user = '$uname' LIMIT 1");

if($db->NumRows() > 0){

while($data_bonus = $db->FetchArray()){

?>



<tr><td>Получить бонус</td><td> можно</td><td><?=date("d.m в H:i:s",$data_bonus["date_del"]) ;?></td></tr>

<?PHP

}

}else echo 'Вы давно не получали бонус. Получите!';

?>



  <tr>

    <td colspan="5" align="center"><h4>Последние 20 бонусов</h4></td>

    </tr>

  <tr>

    <td align="center" class="m-tb">ID</td>

    <td align="center" class="m-tb">Пользователь</td>

    <td align="center" class="m-tb">Сумма</td>

    <td align="center" class="m-tb">Дата</td>

  </tr>

  <?PHP



  $db->Query("SELECT * FROM db_bonus_list ORDER BY id DESC LIMIT 20");



    if($db->NumRows() > 0){



          while($bon = $db->FetchArray()){



        ?>

        <tr class="htt">

            <td align="center"><?=$bon["id"]; ?></td>

            <td align="center"><?=$bon["user"]; ?></td>

            <td align="center"><?=$bon["sum"]; ?></td>

            <td align="center"><?=date("d.m.Y",$bon["date_add"]); ?></td>

          </tr>

        <?PHP



        }



    }else echo '<tr><td align="center" colspan="5">Нет записей</td></tr>'

  ?>





</table>



<div class="clr"></div>

</div>
======================================================= Или скачать файл.

Подсветка синтаксиса в blogger


При публикации на страницах блога программного кода, возникает вопрос его красивого, и главное, доступного, оформления.

Пост о том, как в blogger добавить возможность подсвечивать синтаксис для кодов php, sql, html и xml.

Как установить:




Заходим в настройки, выбираем вкладку "Дизайн"  и "Изменить HTML". далее в окне редактора шаблона, после тега <title><data:blog.pageTitle/></title> пишем следующее:

<link href='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shCore.css' rel='stylesheet' type='text/css'/>

<link href='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shThemeDefault.css' rel='stylesheet' type='text/css'/>

<script src='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shCore.js' type='text/javascript'/>

<!-- add brushes here -->

<script type='text/javascript'>

  SyntaxHighlighter.config.bloggerMode = true;

  SyntaxHighlighter.all();

</script>


После комментария "add brushes here," добавляем скрипты для обработки тех языков, подсветку которых мы хотим использовать. В следующем примере будет использована подсветка для Javascript, SQL, XML/HTML, and PHP:

<script src='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shBrushJScript.js' type='text/javascript'/>

<script src='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shBrushPhp.js' type='text/javascript'/>

<script src='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shBrushSql.js' type='text/javascript'/>

<script src='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shBrushXml.js' type='text/javascript'/>

Осталось только сохранить изменения шаблона и приступать к использованию. Для того чтобы скрипт автоматически "раскрашивал" и размечал код, его необходимо разместить в теги <pre class="brush:[язык подсветки]">. Например, для подсветки блока с SQL-запросом:

<pre class="brush:sql">

SELECT *

FROM users

WHERE user_id = 1212;

</pre>

Подсветка синтаксиса в blogger


При публикации на страницах блога программного кода, возникает вопрос его красивого, и главное, доступного, оформления.

Пост о том, как в blogger добавить возможность подсвечивать синтаксис для кодов php, sql, html и xml.

Как установить:




Заходим в настройки, выбираем вкладку "Дизайн"  и "Изменить HTML". далее в окне редактора шаблона, после тега <title><data:blog.pageTitle/></title> пишем следующее:

<link href='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shCore.css' rel='stylesheet' type='text/css'/>

<link href='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shThemeDefault.css' rel='stylesheet' type='text/css'/>

<script src='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shCore.js' type='text/javascript'/>

<!-- add brushes here -->

<script type='text/javascript'>

  SyntaxHighlighter.config.bloggerMode = true;

  SyntaxHighlighter.all();

</script>


После комментария "add brushes here," добавляем скрипты для обработки тех языков, подсветку которых мы хотим использовать. В следующем примере будет использована подсветка для Javascript, SQL, XML/HTML, and PHP:

<script src='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shBrushJScript.js' type='text/javascript'/>

<script src='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shBrushPhp.js' type='text/javascript'/>

<script src='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shBrushSql.js' type='text/javascript'/>

<script src='https://dl.dropboxusercontent.com/u/72419062/JS/SyntaxLight/shBrushXml.js' type='text/javascript'/>

Осталось только сохранить изменения шаблона и приступать к использованию. Для того чтобы скрипт автоматически "раскрашивал" и размечал код, его необходимо разместить в теги <pre class="brush:[язык подсветки]">. Например, для подсветки блока с SQL-запросом:

<pre class="brush:sql">

SELECT *

FROM users

WHERE user_id = 1212;

</pre>

Последовательность действий AutoCAD при загрузке управляемого расширения

Маленькая шпаргалка на тему того, как AutoCAD обрабатывает загруженное в него управляемое расширение.


При загрузке управляемой сборки в AutoCAD сначала проверяются атрибуты сборки. Если найден атрибут ExtensionApplication, указывающий на публичный класс, реализующий интерфейс IExtensionApplication, то создаётся экземпляр данного класса и вызывается его метод Initialize. В дальнейшем, при завершении сеанса AutoCAD, обязательно будет вызван метод Terminate этого же экземпляра. К моменту вызова Terminate все документы приложения уже закрыты. 

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

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

Если в сборка не имеет атрибутов CommandClass, то производится поиск всех публичных классов, в которых определены команды AutoCAD.

Команды, определённые в составе сборки, могут быть как статическими, так и экземплярными. Если команда экземплярная, то объект данного класса создаётся применительно к документу, из контекста которого команда вызвана. Это означает, что значение свойств и полей у такого объекта для каждого документа будут свои. В таком классе обязательно должна присутствовать возможность создать его экземпляр при помощи конструктора по умолчанию. Причём создаётся этот объект в момент первого вызова любой из экземплярных команд данного класса. Время жизни такого объекта определяется временем жизни документа, к которому он привязан. Удаление этого объекта происходит при закрытии документа. Т.о. если класс удаляемого объекта реализует IDisposable, то будет вызываться метод Dispose.

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

Если команды определены в статических методах класса, то тогда экземпляры такого класса создаваться не будут. Код статического конструктора такого класса будет запущен на исполнение один раз, при первом запуске команды этого класса.

Назначение сборке атрибутов ExtensionApplication и CommandClass позволяет AutoCAD быстро найти нужную ему информацию, не анализируя все классы сборки и, соответственно, быстрее загрузить её.

Далее небольшой код, демонстрирующий описанный выше материал. В комментариях показан результат работы кода - содержимое файла MyLog.txt.

/* MyClasses.cs
 * Андрей Бушман, 2014
 * 
 * Код демонстрирует последовательность вызовов
 * методов, конструкторов и деструкторов 
 * различных классов команд, а так же класса, 
 * реализующего интерфейс IExtensionApplication.
 * 
 * Последовательность действий:
 * ---------------------------------------------
 * 1. Запускаем AutoCAD 2015 (или любую др. 
 *      версию).
 * 2. Создаём три новых документа: Drawing1.dwg, 
 *      Drawing2.dwg и Drawing3.dwg.
 * 3. Устанавливаем текущим документ Drawing1.dwg
 * 4. Загружаем сборку при помощи команды NETLOAD
 * 5. Последовательно запускаем команды: TEST, 
 *      TEST2 и снова TEST.
 * 6. Переключаемся в документ Drawing2.dwg.
 * 7. Последовательно запускаем команды: TEST, 
 *      TEST2 и снова TEST.
 * 8. Закрываем все документы и завершаем работу 
 *      AutoCAD.
 * 9. Смотрим содержимое файла MyLog.txt. 
 *      ВНИМАНИЕ! acad.exe ещё некоторое время 
 *      работает даже после того, как все окна 
 *      закрылись. Прежде чем открывать файл 
 *      MyLog.txt дождитесь завершения процесса 
 *      acad.exe, т.к. нам нужно дождаться, когда
 *      выполнится код метода Terminate().
 * ---------------------------------------------
 * 
 * Содержимое сгенерированного файла MyLog.txt: 
 * ==============================================
 * Метод: ExtensionApplication.Initialize(); 
 *  Документ: Drawing1.dwg; Время: 05.08.2014 
 *  11:56:55
 * Метод: Commands.Commands() [статический]; 
 *  Документ: Drawing1.dwg; Время: 05.08.2014 
 *  11:57:27
 * Метод: Commands.Commands(); 
 *  Документ: Drawing1.dwg; Время: 05.08.2014 
 *  11:57:41
 * Метод: StaticCommands.StaticCommands() 
 *  [статический]; Документ: Drawing1.dwg; 
 *  Время: 05.08.2014 11:57:53
 * Метод: Commands.Commands(); 
 *  Документ: Drawing2.dwg; Время: 05.08.2014 
 *  11:58:15
 * Метод: Commands.Dispose(); 
 *  Документ: Drawing2.dwg; Время: 05.08.2014 
 *  11:58:31
 * Метод: Commands.Finalize(); 
 *  Документ: Drawing2.dwg; Время: 05.08.2014 
 *  11:58:33
 * Метод: Commands.Dispose(); 
 *  Документ: Drawing1.dwg; Время: 05.08.2014 
 *  11:58:33
 * Метод: Commands.Finalize(); 
 *  Документ: Drawing1.dwg; Время: 05.08.2014 
 *  11:58:34
 * Метод: ExtensionApplication.Terminate(); 
 *  Документ: null; Время: 05.08.2014 11:59:04
 *  =============================================
 */
using System;
using System.Reflection;
using System.IO;

using cad = Autodesk.AutoCAD.ApplicationServices
.Application;
using Ap = Autodesk.AutoCAD.ApplicationServices;
using Rt = Autodesk.AutoCAD.Runtime;

[assembly: Rt.ExtensionApplication(typeof(Bushman
    .CAD.Logging.ExtApp))]

[assembly: Rt.CommandClass(typeof(Bushman.CAD
    .Logging.Commands))]

[assembly: Rt.CommandClass(typeof(Bushman.CAD
    .Logging.StaticCommands))]

namespace Bushman.CAD.Logging {

    static class LogWritter {
        static String logFileName = Path.Combine(
            Environment.GetFolderPath(Environment
            .SpecialFolder.MyDocuments),
            "MyLog.txt");

        public static void WriteLine(
            String methodName,
            String documentName) {
            using (StreamWriter sw =
                File.AppendText(logFileName)) {
                String line = String.Format(
                "Метод: {0}; Документ: {1}; " +
                "Время: {2}", methodName,
                documentName, DateTime.Now
                .ToString("dd.MM.yyyy hh:mm:ss"))
                ;
                sw.WriteLine(line);
                sw.Flush();
                sw.Close();
            }
        }
    }

    public sealed class ExtApp :
        Rt.IExtensionApplication {

        // Можно дополнительно создать 
        // статический и|или экземплярный 
        // конструкторы класса, однако вряд ли в
        // данном случае это будет иметь смысл, 
        // посколько равно как и метод Initialize
        // они будут вызваны лишь один раз. В 
        // виду этого можно ограничиться 
        // использованием лишь Initialize.
        // Аналогичная ситуация обстоит и с 
        // Dispose (в случае реализации
        // IDisposable) - вполне достаточно 
        // использовать Terminate.

        // Этот метод выполняется один раз при 
        // загрузке сборки в AutoCAD.
        public void Initialize() {
            Ap.Document doc = cad.DocumentManager
                .MdiActiveDocument;
            String className = MethodBase
                .GetCurrentMethod().ReflectedType
                .Name;
            String methodName = MethodBase
                .GetCurrentMethod().Name;
            String name = className + "." +
                methodName + "()";
            LogWritter.WriteLine(name, doc.Name);
        }

        // Этот метод выполняется один раз при 
        // завершении работы AutoCAD. К этому 
        // моменту все документы уже закрыты.
        public void Terminate() {
            Ap.Document doc = cad.DocumentManager
                .MdiActiveDocument;
            String documentName = (null == doc) ?
                "null" : doc.Name;
            String className = MethodBase
                .GetCurrentMethod().ReflectedType
                .Name;
            String methodName = MethodBase
                .GetCurrentMethod().Name;
            String name = className + "." +
                methodName + "()";
            LogWritter.WriteLine(name,
                documentName);
        }
    }

    // Инстанцирование объекта данного класса 
    // происходит индивидуально для каждого 
    // документа и только в том случае, если была
    // вызвана команда, определённая в данном 
    // классе.
    public sealed class Commands : IDisposable {

        String documentName;

        // статический конструктор. Вызывается 
        // один раз при первом вызове из любого 
        // документа любой из команд, 
        // определённых в данном классе.
        static Commands() {
            Ap.Document doc = cad.DocumentManager
                .MdiActiveDocument;
            String documentName = (null == doc) ?
                "null" : doc.Name;
            String className = MethodBase
                .GetCurrentMethod().ReflectedType
                .Name;
            String methodName = MethodBase
                .GetCurrentMethod().Name;
            if (methodName == ".cctor")
                methodName = className;
            String name = className + "." +
                methodName + "() [статический]";
            LogWritter.WriteLine(name,
                documentName);
        }

        // Конструктор, код которого выполняется 
        // только при первом запуске любой из 
        // команд, определённых в составе данного
        // класса. Если в процессе работы над 
        // документом команды данного класса не 
        // запускались, то и экземпляр класса не 
        // создаётся.
        public Commands() {
            Ap.Document doc = cad.DocumentManager
                .MdiActiveDocument;
            documentName = (null == doc) ? "null"
                : doc.Name;
            String className = MethodBase
                .GetCurrentMethod().ReflectedType
                .Name;
            String methodName = MethodBase
                .GetCurrentMethod().Name;
            if (methodName == ".ctor")
                methodName = className;
            String name = className + "." +
                methodName + "()";
            LogWritter.WriteLine(name,
                documentName);
        }

        // Тестовая экземплярная команда
        [Rt.CommandMethod("Test")]
        public void Test() { }

        // Деструктор вызывается сборщиком мусора
        // GC после того, как объект данного 
        // класса будет уничтожен. Т.е. в нашем 
        // случае, это произойдёт только после 
        // вызова метода Dispose. Когда именно 
        // вызывается деструктор - решает GC.
        // Вряд ли имеет смысл в расширениях 
        // AutoCAD прибегать к вызову 
        // деструктора. Данный код предназначен 
        // лишь для демонстрации 
        // последовательностей вызовов.
        ~Commands() {
            String className = MethodBase
                .GetCurrentMethod().ReflectedType
                .Name;
            String methodName = MethodBase
                .GetCurrentMethod().Name;
            String name = className + "." +
                methodName + "()";
            LogWritter.WriteLine(name,
                documentName);
        }

        // При закрытии документа объект данного 
        // класса, ранее созданный в контексте 
        // закрываемого документа (см. 
        // комментарий к конструктору) 
        // уничтожается. Соответственно, будет 
        // вызван Dispose, при условии реализации
        // IDisposable. 
        public void Dispose() {
            String className = MethodBase
                .GetCurrentMethod().ReflectedType
                .Name;
            String methodName = MethodBase
                .GetCurrentMethod().Name;
            String name = className + "." +
                methodName + "()";
            LogWritter.WriteLine(name,
                documentName);
        }
    }

    // В этом классе определена статическая 
    // команда. При этом экземпляры данного 
    // класса не создаются.
    public sealed class StaticCommands {

        static String documentName;

        // статический конструктор. Вызывается 
        // один раз при первом вызове из любого 
        // документа любой из команд, 
        // определённых в данном классе.
        static StaticCommands() {
            Ap.Document doc = cad.DocumentManager
                .MdiActiveDocument;
            documentName = (null == doc) ? "null"
                : doc.Name;
            String className = MethodBase
                .GetCurrentMethod().ReflectedType
                .Name;
            String methodName = MethodBase
                .GetCurrentMethod().Name;
            if (methodName == ".cctor")
                methodName = className;
            String name = className + "." +
                methodName + "() [статический]";
            LogWritter.WriteLine(name,
                documentName);
        }

        // Тестовая статическая команда
        [Rt.CommandMethod("Test2")]
        public static void Test2() { }
    }
}