вторник, 21 сентября 2010 г.

Актуальный анекдот из "Age of Turbulence"

Читая увлекательную книгу "Age of Turbulence" Алана Гринспана наткнулся на анекдот, который автору рассказал президент Рейган. Не могу удержаться от "перепоста":

"Леонид Брежнев принимает парад войск на красной площади. Мимо него проходят все советские войска. Вначале идут блестящие батальоны элитной пехоты, все солдаты как на подбор. Далее едут грозные танки и артиллерия. Провозят ядерное оружие, демонстрирущее всю мощь великой державы... А самоей последней вдруг проходит группа каких-то мужичков, явно гражданских - плохо выбритых, в помятой одежде, шагающих в разнобой и очень сильно не соответствующих моменту.

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

P.s. вот здесь этот анекдот приведен на английском.

Update а вот видео в тему:
Reagan tells Soviet jokes,
Reagan tells Soviet jokes, pt .2, President Reagan - his humor and wit

пятница, 10 сентября 2010 г.

Критические секции с таймаутом в Delphi

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

Стандартные критические сеации таймауты не поддерживают - секции с таймаутом нужно реализовывать самостоятельно. На RSDN есть отличная статья на эту тему - Критические секции. В ней приведен вариант реализации критических секций с таймаутом (см. листинг 14). Код дан на С++. Я портировал этот код на Delphi и, на его основе, реализовал класс TCriticalSectionDbg. Этот класс можно использовать при отладке вместо TCriticalSection (замену удобно проводить с помощью директив условной компиляции). Выкладываю исходные коды. Если вы обнаружите в них ошибку, пожалуйста сообщите о ней в комментариях, буду очень признателен.

К исходникам TCriticalSectionDbg приложен тестовый проект на Delphi 2010, демонстрирующий блокировку потоков, а так же аналогичный С++-ный проект (можно сравнивать результаты работы функций построчно). Мне этот проект потребовался при портировании вызова функции InterlockedCompareExchangePointer, который в Delphi оказался несколько, гм.. нетривиален.

Скачать исходные коды TCriticalSectionDbg.

четверг, 9 сентября 2010 г.

Открытие валютного расчетного счета индивидуальным предпринимателем

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

Для открытия расчетного счета требуются нотариально заверенные копии следующих документов: свидетельство о регистрации ИП, ИНН, информационное письмо органа государственной статистики об учете в ЕГРПО, выписка из ЕГРИП. При открытии двух счетов (рублевого и валютного) с меня потребовали один пакет документов.

Вы открыли два счета - рублевый и валютный. Теперь у вас есть три счета: расчетный рублевый счет, текущий валютный счет и транзитный валютный счет.

Первое что нужно сделать - уведомить об открытии счета налоговую, пенсионный фонд (ПФ) и фонд социального страхования (ФСС) (Update: ФСС нужно уведомлять только если у вас есть наемные работники). Сделать это нужно в течении 7 дней (см. пункт 3 статьи 28 Федерального закона от 24.07.2009 #212-ФЗ и пункт 2 статьи 23 Налогового кодекса РФ). Соответственно, нужно составить по три уведомления для каждого счета, каждое в двух экземплярах. Т.е. у вас должно быть 2 * 3 * 2 = 12 уведомлений. Один экземпляр вы отдаете, другой оставляете себе. Кстати: 7 дней - это семь рабочих дней. Дата открытия счета указана в справке, которую вам выдают в банке.

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

Уведомления для ФСС РФ и ПФ РФ лежат в интернете: форма уведомления для ФСС РФ и форма уведомления ПФ РФ.

Внимание: в уведомлении об открытии валютного счета указывается номер текущего валютного счета (не транзитного!). И еще: если у вас есть печать, то не забывайте ставить ее на уведомлениях.

Следующий шаг - заключение договора с заказчиком. В нашем случае, со стороны банка к договору предъявлялись следующие требования: договор составляется на двух языках (в две колонки: слева на русском, справа на английском), из договора должна быть понятна максимальная сумма, которая может быть получена в рамках договора и максимальные сроки выполнения.

Мы успешно применили прием, описанный в указанной выше статье - "Если оплата планируется периодически, а делать акты о выполненных работах каждый раз нет желания, то нужно добавить [ключевую] фразу".

В нашем случае "ключевая" фраза прозвучала так:Заказчик перечисляет Исполнителю по настоящему Договору ежемесячный аванс на расчетный счет Исполнителя на основании выставленного счета в размере, определенном Сторонами на основании отчета Исполнителя о количестве затраченные часов на разработку Программного обеспечения. Окончательный расчет по Техническому заданию Заказчиком производится на расчетный счет Исполнителя, на основании счетов выставленных Исполнителем, в срок не позднее 15 (пятнадцати) календарных дней с момента подписания Сторонами Акта приема-передачи по данному Техническому заданию.

То же самое на английском: The Customer transfers Executor monthly advance payment according to the present agreement and invoice, in which the actual amount is based on Executors report and the amount of hours the Executor spent developing the Software. Final payment according to Technical Specification is done by the Customer to the bank account o the Executor according to the Executor's invoices not later than after 15 (fifteen) calendar days from the date on signing Acceptance Act by the parties.

Встал вопрос - как обменяться подписанными договорами с заказчиком. Ответ нашелся в другой статье с хабра - Как организовать работу с заказчиками из других городов?. Сделали по предложенной методике (копирую из оригинала почти дословно):
  • В нижний колонтитул договора вставляем подписи обеих сторон. Распечатываем и подписываем каждую страницу договора, на последнюю ставим свою печать.
  • Отправляем скан договора по емейлу заказчику.
  • Заказчик подписывает копию на каждой странице, на последней ставит свою печать и отправляем обратно вам.
  • Вы распечатываете полученный документ и на каждой странице в произвольном месте ставите свою печать, подпись и пишите «Копия верна»
Процедуру можно еще упростить, получив сканы подписи клиента и отсканировав свою подпись. В нижние колонтитулы вставляются обе подписи, договор распечатывается, далее на каждой странице пишется "копия верна" и ставится подпись. Все. Банк такая копия договора устроила.

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

Про паспорт сделки, оформление счета и нюансы получения оплаты напишу в следующий раз.

Update: см. Расчетный счет ИП. Паспорт сделки и процесс получения денег от зарубежного заказчика.

Полезны статьи на хабре
Опыт регистрации ИП для ведения бизнеса связанного с ИТ. Как всегда, много полезного в комментариях.

Тонкости при работе с иностранным заказчиком

Почему ИТшнику стоит стать ИПшником и почему не стоит регистрировать ООО

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

вторник, 7 сентября 2010 г.

svchost.exe грузит CPU на 100% при запуске Windows 7

Приятель обратился с проблемой - при запуске Windows 7 процессор в течении 5-10 минут загружен на 100%. Системе около года. Раньше все было нормально, а последние 2-3 месяца начались проблемы. Понятно, что что-то установил (или что-то авто-установилось) - но что именно?

Поискал в интернете - сообщений на эту тему масса, но четкого ответа - почему так происходит - нет. Одним помогает обновление видеодрайвера, другим - чистка куллера, третьим - замена USB портов, четвертым - выключение брандмауэра, отключение протокола IP6, чистка host-файла. Многим помогает установка/отмена обновлений Windows. Но какое именно обновление нужно откатить в нашем случае я так и не разобрался.

В safe mode проблема не воспроизвелась, так что вариант железячных проблем мы отмели. Обновление драйверов на видеокарте не помогло. Host файл был чист. Отключение брандмауэра роли не сыграло. С помощью Autoruns почистил автозагрузку от всякого барахла - загрузка компьютера в целом слегка ускорилась, но на время запуска svchost, естественно, это не повлияло. Process Explorer показал, что в рамках проблемных процессов svchost сидят, в основном, различные сетевые службы (но не только).

Сделал следующее: стал отключать службы пачками, перезагружать компьютер и смотреть, исчезла ли проблема. В какой-то момент загрузка снизилась до 80 секунд. Для данного (далеко не нового) компьютера - это нормально. Стал включать одну за одной отключенные службы и нашел двух виновников длительной загрузки:
  • Вспомогательная служба IP
  • Модули ключей IPsec для обмена ключами в Интернете и протокола IP с проверкой
    подлинности
Если их включить, время загрузки увеличивалось сразу с 80 до 300 секунд. Пришлось выключить на время эти службы. Будем ждать, пока их подлатают.

Update: Вот здесь даны инструкции по настройке служб под Windows 7 - какие службы и когда можно отключить.

Update2: Хорошая статья на Хабре, где объясняется что такое IP6 и IPsec.

четверг, 17 сентября 2009 г.

Ошибка 1053. Сервисы на Windows 7

Наткнулся недавно на любопытный баг. Переносил группу проектов с Delphi 2007 на Delphi 2010. С параллельным переходом на Windows 7. Да, знаю, нельзя менять сразу все, но.. так получилось :)

Проекты - группа сервисов. Баг выразился следующим образом. Запускаю любой (один!) сервис - все в порядке. Пытаюсь запустить любой второй - вылетает ошибка "Error 1053: The service did not respond to the start or control request in a timely fashion". Самое неприятное - ошибка вылетает немедленно, сразу при запуске сервиса. Все попытки поставить в ServiceStart Sleep(пара минут) и следом бряк ничего не дали - ошибка вылетает раньше, до того, как выполнится ServiceStart.

Правда, один сервис работал корректно и никак не мешал запуску других сервисов. Сравнил - выяснил, что все проблемные сервисы использовали Indy. Точнее, класс TIdHTTPServer. А тот сервис, что работал корректно, этот класс не использовал и с Indy никак связан не был. Поискал в интернете - нашел описание подобной проблемы на форуме Embarcadero. Правда, решения там не оказалось.

Проблема решилась на следующий день на удивление просто. Создал новый сервис. Визард написал следующий код в файле проекта:

begin
// Windows 2003 Server requires StartServiceCtrlDispatcher to be
// called before CoRegisterClassObject, which can be called indirectly
// by Application.Initialize. TServiceApplication.DelayInitialize allows
// Application.Initialize to be called from TService.Main (after
// StartServiceCtrlDispatcher has been called).
//
// Delayed initialization of the Application object may affect
// events which then occur prior to initialization, such as
// TService.OnCreate. It is only recommended if the ServiceApplication
// registers a class object with OLE and is intended for use with
// Windows 2003 Server.
//
// Application.DelayInitialize := True;
//
if not Application.DelayInitialize or Application.Installing then
Application.Initialize;
Application.CreateForm(TService1, Service1);
Application.Run;
end.
Проверил - все нерабочие сервисы отложенную инициализацию не использовали. Заменил "Application.Initialize;" на

Application.DelayInitialize := True;
if not Application.DelayInitialize or Application.Installing then begin
Application.Initialize;
end;
и все заработало.