<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	
	xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>graywolf's lair &#187; Code snippets</title>
	<atom:link href="http://graywolf.org.ua/category/blog/it/snippets/feed/" rel="self" type="application/rss+xml" />
	<link>http://graywolf.org.ua</link>
	<description>Inhuman being's diary</description>
	<lastBuildDate>Mon, 08 Mar 2010 16:08:06 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Google JS API</title>
		<link>http://graywolf.org.ua/2009/10/22/google-js-api/</link>
		<comments>http://graywolf.org.ua/2009/10/22/google-js-api/#comments</comments>
		<pubDate>Thu, 22 Oct 2009 15:48:51 +0000</pubDate>
		<dc:creator>graywolf</dc:creator>
				<category><![CDATA[Code snippets]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[js]]></category>

		<guid isPermaLink="false">http://graywolf.org.ua/?p=1201</guid>
		<description><![CDATA[Ті, хто займаються Вебом, звісно, давно знають про цю фічу, тому я публікую це не стільки в розрахунку на когось, скільки на згадку собі, бо задовбався при створоенні кожного нового сайту шукати в шаблонах старих сайтів ці заповітні декілька рядків:

&#60;script type=&#34;text/javascript&#34; src=&#34;http://www.google.com/jsapi&#34;&#62;&#60;/script&#62;
&#60;script type=&#34;text/javascript&#34;&#62;
  google.load(&#34;jquery&#34;, &#34;1.3.2&#34;);
&#60;/script&#62;

Фрагмент вище дозволяє завантажувати потрібну версію jQuery прямо з Гугла [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://graywolf.org.ua/wp-content/uploads/2009/10/code_logo.png" alt="Google Code" title="Google Code" width="161" height="40" class="alignleft size-full wp-image-1204" style="border: 0;" />Ті, хто займаються Вебом, звісно, давно знають про цю фічу, тому я публікую це не стільки в розрахунку на когось, скільки на згадку собі, бо задовбався при створоенні кожного нового сайту шукати в шаблонах старих сайтів ці заповітні декілька рядків:</p>
<pre class="brush: xml;">
&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.google.com/jsapi&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
  google.load(&quot;jquery&quot;, &quot;1.3.2&quot;);
&lt;/script&gt;
</pre>
<p>Фрагмент вище дозволяє завантажувати потрібну версію <em>jQuery</em> прямо з Гугла і при виході нової версії не потрібно щось перезаливати на свій сайт &#8211; лише змінити в шаблоні заголовку сторінки номер версії і все готово.</p>
<p>Звісно ж таким чином можна завантажувати не лише <em>jQuer</em>y, а й декілька інших Javascript-фреймворків. На сторінці <a href="http://code.google.com/apis/ajaxlibs/documentation/">Google AJAX Libraries API</a> можна знайти всі бібліотеки та їх версії, що наразі підтримуються.</p>
<p>Більше того, таким чином можна також завантажувати Javascript&#8217;ові сервіси Гугла, наприклад такі як <a href="http://maps.google.com/">Google Maps</a>, але для того доведеться звісно ж при завантаженні <em>JSAPI</em> вказати <em>API Key</em>, який отримується <a href="http://code.google.com/apis/ajaxsearch/signup.html">тут</a> під конкретний домен. Тобто загальний вигляд підключення <em>Google Maps API</em> виглядатиме так:</p>
<pre class="brush: xml;">
&lt;script type=&quot;text/javascript&quot; src=&quot;http://www.google.com/jsapi?key=ABCDEFG&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
  google.load(&quot;maps&quot;, &quot;2&quot;);
&lt;/script&gt;
</pre>
<p>Детальніше про роботу з <em>JSAPI</em> можна знайти на сторінці <a href="http://code.google.com/intl/uk-UA/apis/ajax/documentation/">Google AJAX API</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://graywolf.org.ua/2009/10/22/google-js-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:thumbnail url="http://graywolf.org.ua/wp-content/uploads/2009/10/code_logo-150x40.png" />
		<media:content url="http://graywolf.org.ua/wp-content/uploads/2009/10/code_logo.png" medium="image">
			<media:title type="html">Google Code</media:title>
			<media:thumbnail url="http://graywolf.org.ua/wp-content/uploads/2009/10/code_logo-150x40.png" />
		</media:content>
	</item>
		<item>
		<title>Приклад використання Twitter REST API</title>
		<link>http://graywolf.org.ua/2009/05/13/twitter-rest-api/</link>
		<comments>http://graywolf.org.ua/2009/05/13/twitter-rest-api/#comments</comments>
		<pubDate>Wed, 13 May 2009 10:39:11 +0000</pubDate>
		<dc:creator>graywolf</dc:creator>
				<category><![CDATA[Code snippets]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[bit.ly]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[tricks]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://graywolf.org.ua/?p=1018</guid>
		<description><![CDATA[
Вчора вночі щось мене пробило і я до 2-ї ночі сидів писав одну штуку собі в допомогу, а сьогодні вранці, коли хотів вже залити виявилось, що це вже зробили до мене, причому найцікавіше, що виглядає все один в один як те, що зробив мну. Не розумію, правда, як я не знайшов його вчора &#8211; мабуть [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.python.org/"><img alt="" src="http://www.python.org/images/python-logo.gif" title="Python logo" class="alignleft" width="211" height="71" /></a>
<p>Вчора вночі щось мене пробило і я до 2-ї ночі сидів писав одну штуку собі в допомогу, а сьогодні вранці, коли хотів вже залити виявилось, що це <a href="http://twitter.com/lostfilmnews/">вже зробили до мене</a>, причому найцікавіше, що виглядає все один в один як те, що зробив мну. Не розумію, правда, як я не знайшов його вчора &#8211; мабуть вже заспаний був, але суть не втому. Щоб робота марно не пропадала поділюся парою коротких сніпетів на пітоні.</p>
<p><span id="more-1018"></span><br />
Перший &#8211; для скорочення URL за допомогою сервісу <a href="http://bit.ly/">bit.ly</a> (перед використанням там треба зареєструватись, щоб отримати API key):</p>
<pre class="brush: python;">import urllib, urllib2
import json # є лише Python 2.6 і старше

bitly_login = &quot;your bitly login&quot;
bitly_apikey = &quot;your API key&quot;

def ShortenURL(url):
  try:
    request = urllib2.urlopen(&quot;http://api.bit.ly/shorten?version=2.0.1&amp;longUrl=%s&amp;login=%s&amp;apiKey=%s&quot; % (url, bitly_login, bitly_apikey))
    result = json.loads(request.read())
    return result[&quot;results&quot;][url][&quot;shortUrl&quot;]
  except:
    return None
</pre>
<p>Другий &#8211; для публікації повідомлення в <a href="http://twitter.com">Twitter</a> (тут використовується несек&#8217;юрна Basic HTTP Authorization, бо з <a href="http://oauth.net/">oAuth</a> це було б набагато складніше, а мені вночі було ліньки возитись).</p>
<pre class="brush: python;">import urllib, urllib2
import base64

login = &quot;your twitter login&quot;
passwd = &quot;your twitter password&quot;

secret = base64.encodestring(&quot;%s:%s&quot; % (login, passwd))[:-1]

def Post(message):
  request = urllib2.Request(&quot;http://twitter.com/statuses/update.xml&quot;, urllib.urlencode({&quot;status&quot;: message}), {&quot;Authorization&quot;: &quot;Basic &quot; + secret})

  try:
    urllib2.urlopen(request)
    return message # returning message if it was successfully sent
  except:
    return None
</pre>
<p>Обожнюю python <img src='http://graywolf.org.ua/wp-includes/images/smilies/icon_rolleyes.gif' alt=':roll:' class='wp-smiley' />  </p>
]]></content:encoded>
			<wfw:commentRss>http://graywolf.org.ua/2009/05/13/twitter-rest-api/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:thumbnail url="http://www.python.org/images/python-logo.gif" />
		<media:content url="http://www.python.org/images/python-logo.gif" medium="image">
			<media:title type="html">Python logo</media:title>
		</media:content>
	</item>
		<item>
		<title>Найпростіша plugin-архітектура на python</title>
		<link>http://graywolf.org.ua/2007/12/20/%d0%bd%d0%b0%d0%b9%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%96%d1%88%d0%b0-plugin-%d0%b0%d1%80%d1%85%d1%96%d1%82%d0%b5%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%bd%d0%b0-python/</link>
		<comments>http://graywolf.org.ua/2007/12/20/%d0%bd%d0%b0%d0%b9%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%96%d1%88%d0%b0-plugin-%d0%b0%d1%80%d1%85%d1%96%d1%82%d0%b5%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%bd%d0%b0-python/#comments</comments>
		<pubDate>Thu, 20 Dec 2007 19:24:22 +0000</pubDate>
		<dc:creator>graywolf</dc:creator>
				<category><![CDATA[Code snippets]]></category>
		<category><![CDATA[itblog-ua]]></category>

		<guid isPermaLink="false">http://graywolf.org.ua/2007/12/20/%d0%bd%d0%b0%d0%b9%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%96%d1%88%d0%b0-plugin-%d0%b0%d1%80%d1%85%d1%96%d1%82%d0%b5%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%bd%d0%b0-python/</guid>
		<description><![CDATA[Так вже вийшло, що мені вдруге довелося писати модульну систему на пітоні. Причому вдруге довелося йти по одних і тих самих граблях, бо приклад минулої реалізації залишився на ноуті, який зараз лежить в сервісному центрі. Шлях нижче не являється оптимальним чи там найкращим, але головне, що він 100% робочий і задовольняє моїм потребам   [...]]]></description>
			<content:encoded><![CDATA[<p>Так вже вийшло, що мені вдруге довелося писати модульну систему на пітоні. Причому вдруге довелося йти по одних і тих самих граблях, бо приклад минулої реалізації залишився на ноуті, який зараз лежить в сервісному центрі. Шлях нижче не являється оптимальним чи там найкращим, але головне, що він 100% робочий і задовольняє моїм потребам <img src='http://graywolf.org.ua/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  А потреби полягають в тому, що кожен плагін представляє собою реалізацію класу з певним набором функцій та має засіб для інстанціювання об&#8217;єкту цього класу не знаючи його імені. Отож&#8230; <span id="more-181"></span></p>
<p>Для початку створимо приблизно наступну систему підкаталогів з файлами, а потім почнемо її наповнювати:</p>
<pre>+ / plugins
| |
| + / plugin1
| | |
| | - __init__.py
| |
| + / plugin2
| | |
| | - __init__.py
| |
| - __init__.py
|
- pluginmanager.py</pre>
<p>Як неважко здогадатись, модуль <em>plugingmanager.py</em> &#8211; буде відповідати за завантаження плагінів. Папка <em>plugins</em> міститиме власне плагіни (кожен з яких буде займати окремий каталог) та файл ініціалізації пакету &#8220;plugins&#8221; (файл <em>__init__.py</em>) &#8211; його можна лишити порожнім, оскільки надпакет <em>plugins</em> використовується лише для групування.</p>
<pre class="brush: python;">#!/usr/bin/python
import os

plugins = []

def LoadModule(module):
    # build package name
    packagename = &quot;plugins.&quot; + module
    # using built-in function __import__() to dynamically load modules; ensure that
    # directory containing &quot;plugins&quot; folder exists in python's sys.path list
    # if not, it can be specified by sys.path.append(path_to_plugins) command before calling __import__()
    mod = __import__(packagename, globals(), locals(), [])

    # if module import was successful
    if ( mod ):
        # try to get the plugin module itself
        components = packagename.split('.')
        for component in components[1:]:
            mod = getattr(mod, component)
        # add the instance of plugin-implemented class to the list
        plugins.append(mod.CreateInstance())

# dynamicaly load plugin packages
def LoadPlugins(pluginpath):
    # enum plugins directory
    for dir in os.listdir(pluginpath + &quot;\\plugins&quot;):
        # for each non-hidden file or directory
        if (dir[0] != &quot;_&quot;) and (dir.endswith (&quot;.py&quot;)):
            # try to load corresponding plugin
            LoadModule(dir)

LoadPlugins(&quot;.&quot;)
for plugin in plugins:
	plugin.Say(&quot;Joey&quot;)
</pre>
<p>Сподіваюсь, коментарі зрозумілі (хоч і англомовні <img src='http://graywolf.org.ua/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ). Отож, ми перебираємо папку з плагінами і для кожого файлу (тобто в нашому випадку каталогу) намагаємось імпортувати його по імені. В пітоні завдяки вищенаведеній структурі будується дерево пакетів. Тобто в нашому випадку у нас є пакет верхнього рівня <em>plugins</em>, який має два підпакети: <em>plugins.plugin1</em> та <em>plugins.plugin2</em>. Для імпорту використовується вбудована функція __import__(). Вона повертає клас модуля верхнього рівня (в нашому випадку &#8211; &#8220;plugins&#8221;), але оскільки нам потрібно дійти до пакета нижнього рівня ми &#8220;занурюємось&#8221; далі використовуючи рекурсивно функцію attrib. В нашому випадку, звісно, можна було зробити простіше, оскільки вкладеність тут має лише один рівень і назва пакету будується в цій же функції, але код я трохи ускладнив спеціально, щоб дати більш загальну та гнучку реалізацію завантаження пакетів чи модулів.</p>
<p>Отримавши клас модуля ми викликаємо його глобальну функцію <em>CreateInstance()</em>, що поверне нам екземпляр реалізованого в модулі класу.</p>
<p>Тепер розглянемо реалізацію власне плагінів. Для нескладних випадків ми можемо запихнути її прямо в опис пакету plugin1 &#8211; файл <em>__init__.py</em>:</p>
<pre class="brush: python;">#!/usr/bin/python

class Plugin1():
	def Say(self, name):
		print &quot;Hello, %s!&quot; % name

def CreateInstance():
	return Plugin1()</pre>
<p>По аналогії можна зробити і реалізацію plugin2. Тепер запустивши програму отримаємо наступне:</p>
<pre class="brush: python;">$ ./pluginmanager.py
Hello, Joey!
Konnichiwa, Joey!</pre>
<p>Набір відповідних плагінів можна тепер збільшувати просто додаючи по аналогії інші підкаталоги-пакети. Звісно, можна переробити це все з підтримкою модулів, а не пакетів (чи не лише пакетів), але мені все ж така структура подобається більше.</p>
]]></content:encoded>
			<wfw:commentRss>http://graywolf.org.ua/2007/12/20/%d0%bd%d0%b0%d0%b9%d0%bf%d1%80%d0%be%d1%81%d1%82%d1%96%d1%88%d0%b0-plugin-%d0%b0%d1%80%d1%85%d1%96%d1%82%d0%b5%d0%ba%d1%82%d1%83%d1%80%d0%b0-%d0%bd%d0%b0-python/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
	</item>
		<item>
		<title>Заміна URL для Live search в IE</title>
		<link>http://graywolf.org.ua/2007/08/30/%d0%b7%d0%b0%d0%bc%d1%96%d0%bd%d0%b0-url-%d0%b4%d0%bb%d1%8f-live-search-%d0%b2-ie/</link>
		<comments>http://graywolf.org.ua/2007/08/30/%d0%b7%d0%b0%d0%bc%d1%96%d0%bd%d0%b0-url-%d0%b4%d0%bb%d1%8f-live-search-%d0%b2-ie/#comments</comments>
		<pubDate>Thu, 30 Aug 2007 14:45:37 +0000</pubDate>
		<dc:creator>graywolf</dc:creator>
				<category><![CDATA[Code snippets]]></category>

		<guid isPermaLink="false">http://graywolf.org.ua/?p=54</guid>
		<description><![CDATA[Одразу маленька відмазка: те, що надалі описане мені потрібно було виключно по роботі. Сам я IE не користуюсь &#8211; лише Оперою та Файрфоксом   
Не дивлячись на те, що сабжева задача здається вельми і вельми тривіальною насправді все не атк просто. Мається на увазі URL, по якому переходить браузер, якщо ви введети якусь маячню [...]]]></description>
			<content:encoded><![CDATA[<p>Одразу маленька відмазка: те, що надалі описане мені потрібно було виключно по роботі. Сам я IE не користуюсь &#8211; лише Оперою та Файрфоксом <img src='http://graywolf.org.ua/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  </p>
<p>Не дивлячись на те, що сабжева задача здається вельми і вельми тривіальною насправді все не атк просто. Мається на увазі URL, по якому переходить браузер, якщо ви введети якусь маячню в <em>Location Bar</em> (напр. набір слів, або неіснуючий домен). Точніше велику проблему це становить для IE6. Для Internet Explorer 7 все вирішується просто &#8211; URL для закачки міняється правкою ключа реєстру:</p>
<pre class="brush: plain;">HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\SearchScopes\{0633EE93-D776-472f-A0FF-E1416B8B2E3A}\URL</pre>
<p>Міняємо прописаний там майкрософтівський Live search на щось типу:</p>
<pre class="brush: plain;">http://www.google.com.ua/search?hl=uk&amp;q=&lt;strong&gt;{searchTerms}&lt;/strong&gt;&amp;meta=</pre>
<p>де <em>{searchTerms}</em> &#8211; макрос, на місце якого підставляється введені в рядку браузера лексеми. І все ОК. А от в IE6 такого ключа нема. І там все робиться через дупу. <span id="more-54"></span>Саме цей романтичний шлях і буде далі описано&#8230;</p>
<p>Для визначення URL для підстановки в <em>Address bar</em> в разі, коли IE не може знайти протокол по якому потрібно працювати (ви не вказали його, а дреса не містить ніяких підказок, напр. у вигляді префікса &#8220;www.&#8221;) викликається COM-об&#8217;єкт, що реалізує інтерфейс <a href="http://msdn2.microsoft.com/en-us/library/ms631445.aspx">IURLSearchHook</a>. Цей інтерфейс має лише одну член-функцію: <a href="http://msdn2.microsoft.com/en-us/library/ms631448.aspx">Translate</a>. В комплекті з IE6 йде власна реалізація цього інтерфейсу, яка відкриває сторінку <em>auto.search.msn.com</em>. CLSID об&#8217;єкта, який відповідатиме за постачання URL прописано в ключі <em>HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\URLSearchHooks</em>. По замовучуванню використовується об&#8217;єкт з CLSID <em>{CFBFAE00-17A6-11D0-99CB-00C04FD64497}</em>. Для того, щоб встановити власний URL для пошуку за замовчуванням нам потрібно замінити його своєю реалізацію.</p>
<p>Для цього створюємо звичанйий проект ATL:</p>
<p><center><img src='http://graywolf.org.ua/wp-content/uploads/2007/08/ie-hook-1.jpg' alt='Customizing IE live search - Create ATL Project' /></center></p>
<p>Параметри залишаємо без змін. Далі в щойноствореному проекті через Class Wizard додаємо <em>ATL Simple Object</em> &#8211; клас, який і буде реалізацією інтерфейсу <a href="http://msdn2.microsoft.com/en-us/library/ms631445.aspx">IURLSearchHook</a>.</p>
<p><center><img src='http://graywolf.org.ua/wp-content/uploads/2007/08/ie-hook-2.jpg' alt='Customizing IE live search - Create ATL Simple Class' /></center></p>
<p>Даємо цьому класу якесь ім&#8217;я. Вкладку &#8220;Options&#8221; можна не чіпати і залишити все по дефолту.</p>
<p><center><img src='http://graywolf.org.ua/wp-content/uploads/2007/08/ie-hook-3.jpg' alt='Customizing IE live search - ATL Simple Class Wizard' /></center></p>
<p>Class Wizard зробив для нас практично всю брудну роботу і тепер можна, власне, дописувати необхідні дані.</p>
<p>Файл з описанням класу (в нашому прикладі Searcher.h) доводимо до наступного вигляду:</p>
<pre class="brush: cpp;">// Searcher.h : Declaration of the CSearcher

#pragma once
#include &quot;resource.h&quot;       // main symbols

#include &lt;..\PlatformSDK\include\comdef.h&gt;
#include &lt;shlobj.h&gt;

// ISearcher
[
    object,
    uuid(&quot;A548953B-21A1-490F-A189-0F9FD714BDE2&quot;),
    dual,	helpstring(&quot;ISearcher Interface&quot;),
    pointer_default(unique)
]
__interface ISearcher : IDispatch
{
};

// CSearcher
[
    coclass,
    threading(&quot;apartment&quot;),
    vi_progid(&quot;IESearchHook.Searcher&quot;),
    progid(&quot;IESearchHook.Searcher.1&quot;),
    version(1.0),
    uuid(&quot;94D618D6-E6E7-4EE9-B1B7-24C0B2327853&quot;),
    helpstring(&quot;Searcher Class&quot;)
]
class ATL_NO_VTABLE CSearcher :
    public ISearcher,
    public IURLSearchHook
{
public:
    CSearcher() {}

    DECLARE_PROTECT_FINAL_CONSTRUCT()

    BEGIN_COM_MAP(CSearcher)
        COM_INTERFACE_ENTRY(ISearcher)
        COM_INTERFACE_ENTRY(IDispatch)
        COM_INTERFACE_ENTRY(IURLSearchHook)
    END_COM_MAP()

    HRESULT FinalConstruct()
    {
        return S_OK;
    }

    void FinalRelease() {}

public:
    STDMETHODIMP Translate(LPWSTR lpwszSearchURL, DWORD cchBufferSize)
    {
        LPWSTR wszURL = new WCHAR[cchBufferSize];
        ::LoadStringW(_AtlBaseModule.GetModuleInstance(), IDS_URL404, wszURL, cchBufferSize);
        wcsncat(wszURL, lpwszSearchURL, cchBufferSize);

        ZeroMemory(lpwszSearchURL, wcslen(wszURL));
        wcsncpy( lpwszSearchURL, wszURL, cchBufferSize);
        delete [] wszURL;

        return S_OK;
    }
};
</pre>
<p>Далі створюємо ресурс в String table з ідентифікатором <em>IDS_URL404</em> і змістом типу: <em>http://www.google.com/search?q=</em> (це пошук по гуглю) і збираємо продукт. Реєстрацію COM-об&#8217;єкта Visual Studio зробить за нас, але для того, щоб зареєструвати цю dll-бібліотеку на іншому компі потрібно буде виконати команду:</p>
<pre class="brush: plain;">regsvr32 IESearchHook.dll</pre>
<p>До речі, по коду ще прошу звернути увагу на рядок:</p>
<pre class="brush: cpp;">#include &lt;..\PlatformSDK\include\comdef.h&gt;</pre>
<p>Справа в тому, що принаймні в Visual Studio .NET (2003) є два файли <em>comdef.h</em> і в одному з них не прописано GUID для <a href="http://msdn2.microsoft.com/en-us/library/ms631445.aspx">IURLSearchHook</a>. І тоді при компіляції в рядку:</p>
<pre class="brush: cpp;">        COM_INTERFACE_ENTRY(IURLSearchHook)</pre>
<p>може видаватись помилка типу:</p>
<pre class="brush: cpp;">d:\Work\Other\IESearchHook\Searcher.h(49) : error C2787: 'IURLSearchHook' : no GUID has been associated with this object</pre>
<p>Тому для того, щоб використовувати нормальний <em>comdef.h</em> пересвідчіться, що використовується саме той, який лежить в:</p>
<pre class="brush: plain;">PATH_TO_VISUAL_STUDIO\Vc7\PlatformSDK\Include\</pre>
<p>Ну і нарешті останній крок &#8211; це підстановка нашого COM-об&#8217;єкту замість експлорерівського. Для цього в ключі</p>
<pre class="brush: plain;">HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\URLSearchHooks</pre>
<p>видаляємо параметр, ім&#8217;я якого є CLSID поточного об&#8217;єкту, що видає рядок пошуку і створюємо параметр з іменем, рівним CLSID нашого об&#8217;єкту, обгонувши його в фігурні дужки. Для прикладу вище &#8211; це буде &#8220;{94D618D6-E6E7-4EE9-B1B7-24C0B2327853}&#8221;.</p>
<p>От і все. Запускаємо <em>Internet Explorer</em> і насолоджуємось пошуком в <em>Google</em> замість <em>Live Search</em> <img src='http://graywolf.org.ua/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  Цей спосіб випробувано для <em>Internet Explorer</em> версій 6 та 7. По ідеї має працювати починаючи з 4-го, але це не перевірялося.</p>
<p>Звісно, для реальної роботи функцію Translate треба буде дещо ускладнити, але то вже більш тривіальна справа.</p>
<p>За реалізацію цього завдання вчасно я мушу подякувати наявності наступних двох ресурсів:</p>
<ol>
<li><a href="http://answers.google.com/answers/threadview?id=305908">Google Answers: Change Autosearch URL in IE6</a>. Але спосіб описаний тут не зовсім працює <img src='http://graywolf.org.ua/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  Одна з помилок &#8211; це якраз описаний вище прикол з <em>comdef.h</em></li>
<li><a href="http://www.renpeicheng.com/html/2007-03/1653.html">Якийсь китайський ресурс</a>. Там добре, що була купа скрінів та багато коду і я інтуітивно здогадався в цій купі ієрогліфів в чому була лажа <img src='http://graywolf.org.ua/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://graywolf.org.ua/2007/08/30/%d0%b7%d0%b0%d0%bc%d1%96%d0%bd%d0%b0-url-%d0%b4%d0%bb%d1%8f-live-search-%d0%b2-ie/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
	
		<media:thumbnail url="http://graywolf.org.ua/wp-content/uploads/2007/08/ie-hook-1.jpg" />
		<media:content url="http://graywolf.org.ua/wp-content/uploads/2007/08/ie-hook-1.jpg" medium="image">
			<media:title type="html">Customizing IE live search - Create ATL Project</media:title>
		</media:content>
		<media:content url="http://graywolf.org.ua/wp-content/uploads/2007/08/ie-hook-2.jpg" medium="image">
			<media:title type="html">Customizing IE live search - Create ATL Simple Class</media:title>
		</media:content>
		<media:content url="http://graywolf.org.ua/wp-content/uploads/2007/08/ie-hook-3.jpg" medium="image">
			<media:title type="html">Customizing IE live search - ATL Simple Class Wizard</media:title>
		</media:content>
	</item>
		<item>
		<title>Доступ до Event&#8217;у, що створюється в сервісі</title>
		<link>http://graywolf.org.ua/2007/08/23/%d0%b4%d0%be%d1%81%d1%82%d1%83%d0%bf-%d0%b4%d0%be-event%d1%83-%d1%89%d0%be-%d1%81%d1%82%d0%b2%d0%be%d1%80%d1%8e%d1%94%d1%82%d1%8c%d1%81%d1%8f-%d0%b2-%d1%81%d0%b5%d1%80%d0%b2%d1%96%d1%81%d1%96/</link>
		<comments>http://graywolf.org.ua/2007/08/23/%d0%b4%d0%be%d1%81%d1%82%d1%83%d0%bf-%d0%b4%d0%be-event%d1%83-%d1%89%d0%be-%d1%81%d1%82%d0%b2%d0%be%d1%80%d1%8e%d1%94%d1%82%d1%8c%d1%81%d1%8f-%d0%b2-%d1%81%d0%b5%d1%80%d0%b2%d1%96%d1%81%d1%96/#comments</comments>
		<pubDate>Thu, 23 Aug 2007 16:49:03 +0000</pubDate>
		<dc:creator>graywolf</dc:creator>
				<category><![CDATA[Code snippets]]></category>

		<guid isPermaLink="false">http://graywolf.org.ua/?p=25</guid>
		<description><![CDATA[Сьогодні мав кількагодинний геморой з написанням сервісу. Точніше завдяки кодпроджекту сам сервіс написався на раз (стаття про те як написати сервіс [англ.]), а от взаємодія його з експлореровським BHO вилилась в здоровецьку проблему. А все через кляті права доступу до об&#8217;єктів ядра. Проблема, власне, була в тому, що Windows service який мну написав запускається по [...]]]></description>
			<content:encoded><![CDATA[<p>Сьогодні мав кількагодинний геморой з написанням сервісу. Точніше завдяки кодпроджекту сам сервіс написався на раз (<a href="http://www.codeproject.com/system/windows_nt_service.asp">стаття про те як написати сервіс [англ.]</a>), а от взаємодія його з експлореровським BHO вилилась в здоровецьку проблему. А все через кляті права доступу до об&#8217;єктів ядра. Проблема, власне, була в тому, що Windows service який мну написав запускається по дефолту як і всі інші сервіси &#8211; від користувача SYSTEM. І от з тим-то і халепа, бо права на доступ до об&#8217;єктів ядра, що створються в сервісі виявляються спартанськими і звичанйому смертному, чи то пак додатку запущенному користувачем його не відкрити. Була купа ідей як його зробити, але зрештою як завжди допоміг Гугль, який вивів мене спочатку <a href="http://discuss.joelonsoftware.com/default.asp?joel.3.226319.5">сюди</a>, а потім і <a href="http://www.delphikingdom.ru/asp/viewitem.asp?catalogid=1322">сюди</a>. В результаті і народилось рішення.</p>
<p><span id="more-25"></span><br />
Некрасиве, несек&#8217;юрне, але робоче:</p>
<pre class="brush: cpp;">SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor( &amp;sd, SECURITY_DESCRIPTOR_REVISION );
SetSecurityDescriptorDacl( &amp;sd, TRUE, NULL, FALSE );

SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = &amp;sd;
sa.bInheritHandle = false;

ATL::CEvent event;
event.Create( &amp;sa, 1, 0, c_eventName );</pre>
<p>В результаті маємо об&#8217;єкт Event з доступом для службового користувача &#8220;Everyone&#8221;. Отаке. Можна, звісно, позаморачуватись з токенами, видирати ім&#8217;я залогіненого користувача і виставляти доступ лише для нього, але то такий геморой&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://graywolf.org.ua/2007/08/23/%d0%b4%d0%be%d1%81%d1%82%d1%83%d0%bf-%d0%b4%d0%be-event%d1%83-%d1%89%d0%be-%d1%81%d1%82%d0%b2%d0%be%d1%80%d1%8e%d1%94%d1%82%d1%8c%d1%81%d1%8f-%d0%b2-%d1%81%d0%b5%d1%80%d0%b2%d1%96%d1%81%d1%96/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
	</item>
	</channel>
</rss>
