<?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/"
	>

<channel>
	<title>Martin&#039;s Blog &#187; ATL</title>
	<atom:link href="http://blog.m-ri.de/index.php/category/programmieren/atl/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.m-ri.de</link>
	<description>Gesammeltes aus dem Leben eines &#34;normalen&#34; Programmierers... :-)</description>
	<lastBuildDate>Sat, 04 Feb 2012 12:07:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Für was ist der Makro %(PreprocessorDefinitions) gut ?</title>
		<link>http://blog.m-ri.de/index.php/2011/10/16/fur-was-ist-der-makro-preprocessordefinitions-gut/</link>
		<comments>http://blog.m-ri.de/index.php/2011/10/16/fur-was-ist-der-makro-preprocessordefinitions-gut/#comments</comments>
		<pubDate>Sun, 16 Oct 2011 17:54:35 +0000</pubDate>
		<dc:creator>Martin Richter</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[CRT]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[VS 2008]]></category>
		<category><![CDATA[VS 2010]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Compiler]]></category>
		<category><![CDATA[VS-2008]]></category>
		<category><![CDATA[VS-2010]]></category>

		<guid isPermaLink="false">http://blog.m-ri.de/?p=903</guid>
		<description><![CDATA[In den C++ Compilereinstellungen finden sich ein vorgegebener Makro %(PreprocessorDefinitions) in den C++ Präprozessor Definitionen. Die Verwendung dieses Makros ist nicht ganz offensichtlich. Dieser Makro sollten in jedem Fall nicht entfernt werden, denn Sie dienen der Übernahme einiger Einstellungen aus der General-Seite für die C++ Projekte. Zum Beispiel werden die Einstellungen für Unicode und MBCS über [...]]]></description>
			<content:encoded><![CDATA[<p>In den C++ Compilereinstellungen finden sich ein vorgegebener Makro <em>%(PreprocessorDefinitions)</em> in den C++ Präprozessor Definitionen. Die Verwendung dieses Makros ist nicht ganz offensichtlich.</p>
<p>Dieser Makro sollten in jedem Fall nicht entfernt werden, denn Sie dienen der Übernahme einiger Einstellungen aus der <em>General</em>-Seite für die C++ Projekte. Zum Beispiel werden die Einstellungen für Unicode und MBCS über den Makro <em>%(PreprocessorDefinitions)</em> in die allgemeinen Compiler-Einstellungen übernommen (die entsprechenden Defines sind <em>_UNICODE; UNICODE; _MBCS </em>).<br />
Erzeugt man eine DLL wird zusätzlich <em>_WINDLL</em> gesetzt.<br />
Setzt man ATL Optionen in der General Seite wird auch über die <em>%(PreprocessorDefinitions) _ATLDLL</em> bzw. <em>_ATL_STATIC_REGISTRY</em> gesetzt oder zurückgesetzt.<br />
Gleiches gilt, wenn die <em>MFC</em> als shared DLL verwendet wird. In diesem Fall wird der Define <em>_AFXDLL</em> zusätzlich gesetzt.</p>
<p>Löscht man also <em>%(PreprocessorDefinitions)</em> dann werden alle diese Einstellungen nicht mehr  korrekt übernommen.</p>
<p>Anmerkung:<br />
Bei dem Linker Makro <em>%(AdditionalDependencies) </em>habe ich eine ähnliche Verwendung vermutet, konnte aber keine direkte Beziehung zur Seite General herstellen.</p>
<p>Obwohl es auch hier Einflüsse auf die Linkereinstellungen gibt bei Änderungen in den <em>General</em>-Einstellungen. Werden allerdings die MFC als zusätzliche Bibliothek ausgewählt werden die Standard-LIBs aus dem SDK komplett entfernt. Hier gibt die MFC Bibliothek selbst vor in welchen zusätzlichen Libs, des SDK gesucht werden soll über #pragma comment(lib,..).</p>
<hr /><small>Copyright &copy; 2010 Martin Richter<br />Dieser Feed ist nur für den persönlichen, nicht gewerblichen Gebrauch bestimmt. Eine Verwendung dieses Feeds bzw. der hier veröffentlichten Beiträge auf anderen Webseiten bedarf der ausdrücklichen Genehmigung des Autors.<br />(Digital Fingerprint: bdafe67664ea5aacaab71f8c0a581adf)</small>]]></content:encoded>
			<wfw:commentRss>http://blog.m-ri.de/index.php/2011/10/16/fur-was-ist-der-makro-preprocessordefinitions-gut/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OLE DB für den SQL Server wird es nur noch bis zur Version mit dem Codenamen &#8220;Denali&#8221;</title>
		<link>http://blog.m-ri.de/index.php/2011/10/09/ole-db-fur-den-sql-server-wird-es-nur-noch-bis-zur-version-mit-dem-codenamen-denali/</link>
		<comments>http://blog.m-ri.de/index.php/2011/10/09/ole-db-fur-den-sql-server-wird-es-nur-noch-bis-zur-version-mit-dem-codenamen-denali/#comments</comments>
		<pubDate>Sun, 09 Oct 2011 17:38:15 +0000</pubDate>
		<dc:creator>Martin Richter</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[MS-SQL. SQL]]></category>

		<guid isPermaLink="false">http://blog.m-ri.de/?p=901</guid>
		<description><![CDATA[Es ist erstaunlich von wie viel Technologie, sich Microsoft aktuell verabschiedet, oder Wege einschlägt, die manchen (zumindest mich) wirklich überraschen. Oder vielleicht überrascht es auch nicht, weil man gerade mit der Unberechenbarkeit der Branche rechnen muss! OLE DB war vor Jahren die Technologie und jedem Entwickler wurde geraten von ODBC auf OLE DB umzusteigen, oder zumindest [...]]]></description>
			<content:encoded><![CDATA[<p>Es ist erstaunlich von wie viel Technologie, sich <em>Microsoft</em> aktuell verabschiedet, oder Wege einschlägt, die manchen (zumindest mich) wirklich überraschen. Oder vielleicht überrascht es auch nicht, weil man gerade mit der Unberechenbarkeit der Branche rechnen muss!</p>
<p><em>OLE DB</em> war vor Jahren die Technologie und jedem Entwickler wurde geraten von <em>ODBC</em> auf <em>OLE DB</em> umzusteigen, oder zumindest bei neuen Projekten <em>OLE DB</em> den Vorzug zu geben. Die höhere Performance und die größere Flexibilität haben bei weitem, die etwas komplexere Technik aufgewogen. Und Dank der guten <em>ATL</em> Client-Klassen war <em>OLE DB</em> auch zu handhaben.</p>
<p>Nun ist Schluß damit! Der nächste SQL-Server mit dem Codenamen <em>Denali</em> wird die letzte Version sein, die <em>OLE DB</em> unterstützen wird, so ist hier zu lesen:<br />
<a href="http://blogs.msdn.com/b/sqlnativeclient/archive/2011/08/29/microsoft-is-aligning-with-odbc-for-native-relational-data-access.aspx?CommentPosted=true#commentmessage">http://blogs.msdn.com/b/sqlnativeclient/archive/2011/08/29/microsoft-is-aligning-with-odbc-for-native-relational-data-access.aspx</a></p>
<p>Liest man die Kommentare aufmerksam, dann scheint es daran zu liegen, dass <em>Microsoft</em> Probleme hat, <em>OLE DB</em> in der <em>Cloud</em> vernünftig zum laufen zu bekommen. Microsoft macht es sich scheinbar einfach und schießt eine ganze Technologie ab, die mal als &#8220;die Technik&#8221; eingeführt wurde.<br />
D.h. eine langsamere Technik wird nun der Standard werden.<br />
Für mich wieder mal eine Entscheidung, die sich mir in keiner Weise erklärt.</p>
<p>Ich verfolge die Diskussion um den <em>MS-SQL</em> Server nicht permanent und so ist mir dieser Artikel erst jetzt untergekommen.</p>
<p>Mehr Infos auch in diesem Thread, der eine kleine FAQ enthält:<br />
<a href="http://social.technet.microsoft.com/Forums/en/sqldataaccess/thread/e696d0ac-f8e2-4b19-8a08-7a357d3d780f">http://social.technet.microsoft.com/Forums/en/sqldataaccess/thread/e696d0ac-f8e2-4b19-8a08-7a357d3d780f</a></p>
<p>Heftig finde ich die Antwort auf Frage 6, die einem auch kaum Hoffnung macht mit einem älteren Client evtl. noch auf den neuen Server zugreifen zu können:</p>
<blockquote><p><strong>Question6:</strong> If I have an OLE DB application that I write for Denali, will it be supported on a post Denali version of SQL Server that is released during the life of Denali?</p>
<p><strong>Answer:</strong> No, in fact we may explicitly block the OLE DB applications on post-Denali versions of SQL Server. It is recommended that you plan your migration soon to ODBC, if you want to start using newer versions of SQL Server as soon as they release.</p></blockquote>
<p>PS: Wie erkläre ich wohl meinen Kunden, die auf einmal 10%-30% langsamere Datenzugriffe haben werden, gerade wenn es größere Datenmengen geht ?  Werden die mir glauben, wenn ich sage: Microsoft will es so?  <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<hr /><small>Copyright &copy; 2010 Martin Richter<br />Dieser Feed ist nur für den persönlichen, nicht gewerblichen Gebrauch bestimmt. Eine Verwendung dieses Feeds bzw. der hier veröffentlichten Beiträge auf anderen Webseiten bedarf der ausdrücklichen Genehmigung des Autors.<br />(Digital Fingerprint: bdafe67664ea5aacaab71f8c0a581adf)</small>]]></content:encoded>
			<wfw:commentRss>http://blog.m-ri.de/index.php/2011/10/09/ole-db-fur-den-sql-server-wird-es-nur-noch-bis-zur-version-mit-dem-codenamen-denali/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>VS-Tipps &amp; Tricks: MFC/ATL Tracing selektiv ein und ausschalten</title>
		<link>http://blog.m-ri.de/index.php/2010/09/10/vs-tipps-tricks-mfcatl-tracing-selektiv-ein-und-ausschalten/</link>
		<comments>http://blog.m-ri.de/index.php/2010/09/10/vs-tipps-tricks-mfcatl-tracing-selektiv-ein-und-ausschalten/#comments</comments>
		<pubDate>Fri, 10 Sep 2010 16:41:44 +0000</pubDate>
		<dc:creator>Martin Richter</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[Debuggen]]></category>
		<category><![CDATA[VS-Tipps&Tricks]]></category>

		<guid isPermaLink="false">http://blog.m-ri.de/?p=654</guid>
		<description><![CDATA[In ATL und MFC steckt ein ziemlich ausgeklügelter Trace-Mechanismus. Wenn man sich das MFC &#8211; ATL Trace Tool ansieht kann man zu allen möglichen Kategorien Informationen in Debug Fenster ausgeben lassen. Alleine die MFC hat 14 verschiedene Trace Kategorien. Darunter besonders interessante wie CommandRouting, AppMsg und WinMsg. Die ATL hat weitere 27 Kategorien. Es lohnt sich [...]]]></description>
			<content:encoded><![CDATA[<p>In <em>ATL</em> und <em>MFC</em> steckt ein ziemlich ausgeklügelter Trace-Mechanismus. Wenn man sich das <strong><em>MFC &#8211; ATL Trace Tool</em> </strong>ansieht kann man zu allen möglichen Kategorien Informationen in Debug Fenster ausgeben lassen.<br />
Alleine die <em>MFC</em> hat 14 verschiedene Trace Kategorien. Darunter besonders interessante wie <em>CommandRouting</em>, <em>AppMsg</em> und <em>WinMsg</em>. Die <em>ATL</em> hat weitere 27 Kategorien.<br />
Es lohnt sich mal einen Blick in dieses Tool und die entsprechenden Ausgaben zu machen. Es gehört zu den oft unbekannten netten Helferlein, die leider mangels Bekanntheit selten benutzt werden.</p>
<p>Um Fehler zu finden und einzugrenzen, sind mir jedoch oft eher zu viele Ausgaben vorhanden, als zu wenige. Zudem finde ich es manchmal unhandlich mit dem Trace-Tool die Nachrichten ab einem bestimmten Moment einzuschalten und wieder auszuschalten.<br />
Ich habe eine kleine Hilfsklasse gebaut,mit der man in jedem Szenario, jederzeit zu einem bestimmten Moment das Tracing im Code ein- und automatisch wieder ausschalten kann.</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> CDebugEnableTraceForCategory
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
  CDebugEnableTraceForCategory<span style="color: #008000;">&#40;</span>ATL<span style="color: #008080;">::</span><span style="color: #007788;">CTraceCategory</span> <span style="color: #000040;">&amp;</span>category,
           PCSTR pszPrompt<span style="color: #000080;">=</span><span style="color: #0000ff;">NULL</span>,
           UINT uiLevel<span style="color: #000080;">=</span><span style="color: #0000dd;">4</span>,
           ATL<span style="color: #008080;">::</span><span style="color: #007788;">ATLTRACESTATUS</span> eStatus<span style="color: #000080;">=</span>ATL<span style="color: #008080;">::</span><span style="color: #007788;">ATLTRACESTATUS_ENABLED</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008080;">:</span> m_category<span style="color: #008000;">&#40;</span>category<span style="color: #008000;">&#41;</span>
    , m_uiSaveLevel<span style="color: #008000;">&#40;</span>category.<span style="color: #007788;">GetLevel</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
    , m_eSaveStatus<span style="color: #008000;">&#40;</span>category.<span style="color: #007788;">GetStatus</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
    , m_strPrompt<span style="color: #008000;">&#40;</span>pszPrompt<span style="color: #008000;">&#41;</span>
  <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>m_strPrompt.<span style="color: #007788;">IsEmpty</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
      TRACE<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%s - Tracelevel %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, m_strPrompt.<span style="color: #007788;">GetString</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>,uiLevel<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    m_category.<span style="color: #007788;">SetLevel</span><span style="color: #008000;">&#40;</span>uiLevel<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    m_category.<span style="color: #007788;">SetStatus</span><span style="color: #008000;">&#40;</span>eStatus<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  <span style="color: #008000;">&#125;</span>
  ~CDebugEnableTraceForCategory<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
  <span style="color: #008000;">&#123;</span>
    m_category.<span style="color: #007788;">SetLevel</span><span style="color: #008000;">&#40;</span>m_uiSaveLevel<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    m_category.<span style="color: #007788;">SetStatus</span><span style="color: #008000;">&#40;</span>m_eSaveStatus<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>m_strPrompt.<span style="color: #007788;">IsEmpty</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
      TRACE<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%s - Tracelevel %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, m_strPrompt.<span style="color: #007788;">GetString</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, m_uiSaveLevel<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
  <span style="color: #666666;">// Data fields</span>
  ATL<span style="color: #008080;">::</span><span style="color: #007788;">CTraceCategory</span> <span style="color: #000040;">&amp;</span>m_category<span style="color: #008080;">;</span>
  ATL<span style="color: #008080;">::</span><span style="color: #007788;">ATLTRACESTATUS</span> m_eSaveStatus<span style="color: #008080;">;</span>
  UINT m_uiSaveLevel<span style="color: #008080;">;</span>
  CStringA m_strPrompt<span style="color: #008080;">;</span>
  <span style="color: #666666;">// no copy operator</span>
  CDebugEnableTraceForCategory<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> CDebugEnableTraceForCategory <span style="color: #000040;">&amp;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  CDebugEnableTraceForCategory<span style="color: #000040;">&amp;</span> operator<span style="color: #000080;">=</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> CDebugEnableTraceForCategory <span style="color: #000040;">&amp;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></div></div>

<p>Mit dieser Klasse kann ich zum Beispiel alle Windows-Nachrichten an MFC Fenster bei einer bestimmen Aktion ausgeben lassen. Und wenn die Aktion fertig ist stopp auch das Tracing wieder. </p>
<p>Hier als Beispiel um alle Fensternachrichten in der Aktion LoadFrame zu Tracen: </p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> CMyApp<span style="color: #008080;">::</span><span style="color: #007788;">InitInstance</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
...
    CDebugEnableTraceForCategory trace<span style="color: #008000;">&#40;</span>traceWinMsg,<span style="color: #FF0000;">&quot;messages in LoadFrame&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    pMainFrame<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>LoadFrame<span style="color: #008000;">&#40;</span>IDR_MAINFRAME,WS_OVERLAPPEDWINDOW<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
...
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Weitere Infos in der MSDN findet man unter ATL::CTraceCategory und ATLTRACE2 <a href="http://msdn.microsoft.com/en-us/library/dhxsse89(VS.100).aspx">http://msdn.microsoft.com/en-us/library/dhxsse89(VS.100).aspx</a></p>
<hr /><small>Copyright &copy; 2010 Martin Richter<br />Dieser Feed ist nur für den persönlichen, nicht gewerblichen Gebrauch bestimmt. Eine Verwendung dieses Feeds bzw. der hier veröffentlichten Beiträge auf anderen Webseiten bedarf der ausdrücklichen Genehmigung des Autors.<br />(Digital Fingerprint: bdafe67664ea5aacaab71f8c0a581adf)</small>]]></content:encoded>
			<wfw:commentRss>http://blog.m-ri.de/index.php/2010/09/10/vs-tipps-tricks-mfcatl-tracing-selektiv-ein-und-ausschalten/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bug: CSimpleMap und CSimpleArray führen bei Verwendung von SetAtIndex zu einem Leak</title>
		<link>http://blog.m-ri.de/index.php/2010/08/17/bug-csimplemap-und-csimplearray-fuehren-bei-verwendung-von-setatindex-zu-einem-leak/</link>
		<comments>http://blog.m-ri.de/index.php/2010/08/17/bug-csimplemap-und-csimplearray-fuehren-bei-verwendung-von-setatindex-zu-einem-leak/#comments</comments>
		<pubDate>Tue, 17 Aug 2010 17:56:17 +0000</pubDate>
		<dc:creator>Martin Richter</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[VS 2008]]></category>
		<category><![CDATA[VS 2010]]></category>
		<category><![CDATA[Bug]]></category>
		<category><![CDATA[MSDN]]></category>
		<category><![CDATA[VS-2005]]></category>
		<category><![CDATA[VS-2008]]></category>
		<category><![CDATA[VS-2010]]></category>

		<guid isPermaLink="false">http://blog.m-ri.de/?p=655</guid>
		<description><![CDATA[Wieder einmal ein Bug, der seit VC-2005 bekannt ist und in meinen Augen unmöglich als by design abgetan werden darf. Das Problem ist simpel, wenn man die Funktion SetAtIndex in den Klassen CSimpleMap und CSimpleArray angewendet wird, dann wird für das bestehende Element in der Map oder im Array kein Destruktor aufgerufen. D.h. eine CSimpleMap&#60;CString,&#8230;&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>Wieder einmal ein Bug, der seit <em>VC-2005 </em>bekannt ist und in meinen Augen unmöglich als <strong><em>by design </em></strong>abgetan werden darf.</p>
<p>Das Problem ist simpel, wenn man die Funktion <em>SetAtIndex</em> in den Klassen <em>CSimpleMap</em> und <em>CSimpleArray</em> angewendet wird, dann wird für das bestehende Element in der Map oder im Array kein Destruktor aufgerufen. D.h. eine <em>CSimpleMap&lt;CString,&#8230;&gt; </em>bzw. ein <em>CSimpleArray&lt;CString&gt;</em> führt mit der Verwendung von <em>SetAtIndex </em>sofort zu Leaks.</p>
<p>Tückisch in reinen <em>ATL</em> Projekten, weil hier der <em>CRT</em> Heap nicht benutzt wird und die Speicherleaks durch die <em>CRT</em> nicht entdeckt werden, weil der <em>Win32</em> Heap zum Einsatz kommt.</p>
<p>Hier ist der Bug zu finden, inkl. der in meinen Augen korrekten Implementierung:<br />
<a href="https://connect.microsoft.com/VisualStudio/feedback/details/298324/csimplemap-setatindex-do-not-call-a-ditructor">https://connect.microsoft.com/VisualStudio/feedback/details/298324/csimplemap-setatindex-do-not-call-a-ditructor</a></p>
<p>Für mich ist besonders diese Antwort äußerst fragwürdig:</p>
<blockquote><p>CSimpleMap wasn&#8217;t really designed to work for types that needed destruction. The docs state it is limited and you should use CAtlMap instead.</p></blockquote>
<p>Dieser Satz und dieser Hinweis ist in keiner Doku zu finden. Die Doku liest sich ganz anders:<br />
<a href="http://msdn.microsoft.com/en-us/library/d1xc3983(VS.100).aspx">http://msdn.microsoft.com/en-us/library/d1xc3983(VS.100).aspx</a></p>
<blockquote><p><strong>CSimpleMap</strong> provides support for a simple mapping array of <strong><em>any given type T</em></strong>, managing an unordered array of key elements and their associated values.</p></blockquote>
<p><strong>Man kann nur raten <em>SetAtIndex</em> nicht zu verwenden, sondern nur <em>SetAt</em> oder den operator[] <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_exclaim.gif' alt=':!:' class='wp-smiley' /> </strong></p>
<hr /><small>Copyright &copy; 2010 Martin Richter<br />Dieser Feed ist nur für den persönlichen, nicht gewerblichen Gebrauch bestimmt. Eine Verwendung dieses Feeds bzw. der hier veröffentlichten Beiträge auf anderen Webseiten bedarf der ausdrücklichen Genehmigung des Autors.<br />(Digital Fingerprint: bdafe67664ea5aacaab71f8c0a581adf)</small>]]></content:encoded>
			<wfw:commentRss>http://blog.m-ri.de/index.php/2010/08/17/bug-csimplemap-und-csimplearray-fuehren-bei-verwendung-von-setatindex-zu-einem-leak/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Alle SQL Server enumerieren mit den OLE-DB Enumeratoren</title>
		<link>http://blog.m-ri.de/index.php/2010/01/18/alle-sql-server-enumerieren-mit-den-ole-db-enumeratoren/</link>
		<comments>http://blog.m-ri.de/index.php/2010/01/18/alle-sql-server-enumerieren-mit-den-ole-db-enumeratoren/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 19:19:30 +0000</pubDate>
		<dc:creator>Martin Richter</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Windows API]]></category>
		<category><![CDATA[MS-SQL]]></category>
		<category><![CDATA[OLE-DB]]></category>
		<category><![CDATA[OLEDB]]></category>
		<category><![CDATA[SQ 2005]]></category>
		<category><![CDATA[SQL 2000]]></category>
		<category><![CDATA[SQL 2008]]></category>
		<category><![CDATA[Win32]]></category>

		<guid isPermaLink="false">http://blog.m-ri.de/?p=571</guid>
		<description><![CDATA[Wie bekommt man eigentlich einfach eine Liste aller verfügbaren SQL-Server im Netz? In der MSDN findet sich schnell ein Artikel How to enumerate available instances of SQL Server by using the SQLDMO components. Allerdings ist dieser Artikel wenig nützlich, denn SQL-DMO findet man nur noch selten auf einem Rechner. Dabei ist es doch relativ einfach, [...]]]></description>
			<content:encoded><![CDATA[<p>Wie bekommt man eigentlich einfach eine Liste aller verfügbaren SQL-Server im Netz?</p>
<p>In der MSDN findet sich schnell ein Artikel <a href="http://support.microsoft.com/kb/287737/en-us">How to enumerate available instances of SQL Server by using the SQLDMO components</a>. Allerdings ist dieser Artikel wenig nützlich, denn SQL-DMO findet man nur noch selten auf einem Rechner.</p>
<p>Dabei ist es doch relativ einfach, denn OLE-DB sieht hierfür Enumeratoren vor. Aber auch die sind nicht sonderlich gut dokumentiert. In der SQL-2000 Server Doku findet sich noch ein Eintrag für den <a href="http://msdn.microsoft.com/en-us/library/aa198369(SQL.80).aspx">SQLOLEDB Enumerator</a>. Für den neuen nativen OLE-DB Clienst für den SQL-Server finde ich nichts mehr dazu.</p>
<p>ATL stellt direkt Klassen zur Verfügung, die die Nutzung von Enumeratoren zu einem Kinderspiel machen.</p>
<p>Anbei ein Codeschnippsel der alle bekannten MS-SQL Server enumeriert. Ich beginne dabei mit dem neuesten Client (2008) und gehe die Schleife weiter bis zum ältesten Server Client (2000).<br />
Wird ein Enumerator gefunden, und dieser lieferte Ergebnisse, dann wird die Schleife abgebrochen. Denn alle Enumeratoren liefern im Allgemeinen das gleiche Ergebnis.</p>
<p>Code:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">&nbsp;
<span style="color: #666666;">//////////////////////////////////////////////////////////////////////////</span>
<span style="color: #666666;">// Main function to enumerate all servers with the appropriate</span>
<span style="color: #666666;">// known enumerators.</span>
&nbsp;
<span style="color: #0000ff;">typedef</span> std<span style="color: #008080;">::</span><span style="color: #007788;">set</span>  TSET_CString<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">void</span> EnumSQLServer<span style="color: #008000;">&#40;</span>TSET_CString <span style="color: #000040;">&amp;</span>setSQLServer<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
  <span style="color: #666666;">// We may need the local server name. </span>
  <span style="color: #666666;">// We replace the token (local) with the current computer name.</span>
  CString strCompLocal<span style="color: #008080;">;</span>
  DWORD dwLen <span style="color: #000080;">=</span> MAX_COMPUTERNAME_LENGTH<span style="color: #000040;">+</span><span style="color: #0000dd;">1</span><span style="color: #008080;">;</span>
  <span style="color: #008080;">::</span><span style="color: #007788;">GetComputerName</span><span style="color: #008000;">&#40;</span>CStrBuf<span style="color: #008000;">&#40;</span>strCompLocal,dwLen<span style="color: #008000;">&#41;</span>,<span style="color: #000040;">&amp;</span>dwLen<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
  <span style="color: #666666;">// Loop over all enumerators we know</span>
  <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">const</span> PCWSTR aEnumerator<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span>
  <span style="color: #008000;">&#123;</span>
    L<span style="color: #FF0000;">&quot;SQLNCLI10 Enumerator&quot;</span>,    <span style="color: #666666;">// SQL 2008</span>
    L<span style="color: #FF0000;">&quot;SQLNCLI Enumerator&quot;</span>,      <span style="color: #666666;">// SQL 2005</span>
    L<span style="color: #FF0000;">&quot;SQLOLEDB Enumerator&quot;</span>      <span style="color: #666666;">// SQL 2000</span>
  <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
  <span style="color: #666666;">// Try all enumerators</span>
  <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i<span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> _countof<span style="color: #008000;">&#40;</span>aEnumerator<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>i<span style="color: #008000;">&#41;</span>
  <span style="color: #008000;">&#123;</span>
    <span style="color: #666666;">// Check if we have an enumerator</span>
    <span style="color: #0000ff;">bool</span> bFoundAny <span style="color: #000080;">=</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    HRESULT hr<span style="color: #008080;">;</span>
    CLSID clsid<span style="color: #008080;">;</span>
    hr <span style="color: #000080;">=</span> CLSIDFromProgID<span style="color: #008000;">&#40;</span>aEnumerator<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span>,<span style="color: #000040;">&amp;</span>clsid<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>SUCCEEDED<span style="color: #008000;">&#40;</span>hr<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
      <span style="color: #666666;">// Open enumerator and loop over all entries</span>
      CEnumerator enumrator<span style="color: #008080;">;</span>
      hr <span style="color: #000080;">=</span> enumrator.<span style="color: #007788;">Open</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>clsid<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>SUCCEEDED<span style="color: #008000;">&#40;</span>hr<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
      <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>hr<span style="color: #000080;">=</span>enumrator.<span style="color: #007788;">MoveNext</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #000080;">==</span>S_OK<span style="color: #008000;">&#41;</span>
        <span style="color: #008000;">&#123;</span>
          CString strServerName<span style="color: #008000;">&#40;</span>enumrator.<span style="color: #007788;">m_szName</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
          <span style="color: #666666;">// Skip empty server names </span>
          <span style="color: #666666;">// (older enumerators return sometimes an empty name)</span>
          <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>strServerName.<span style="color: #007788;">IsEmpty</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
            <span style="color: #0000ff;">continue</span><span style="color: #008080;">;</span>
&nbsp;
          <span style="color: #666666;">// Some enumerators return (local) for a local main</span>
          <span style="color: #666666;">// SQL server instance</span>
          <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>strServerName.<span style="color: #007788;">CompareNoCase</span><span style="color: #008000;">&#40;</span>_T<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;(local)&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #000080;">==</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span>
          <span style="color: #008000;">&#123;</span>
            ATLTRACE<span style="color: #008000;">&#40;</span>__FUNCTION__ <span style="color: #FF0000;">&quot; found local computer<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            strServerName <span style="color: #000080;">=</span> strCompLocal<span style="color: #008080;">;</span>
          <span style="color: #008000;">&#125;</span>
&nbsp;
          <span style="color: #666666;">// get uppercase server name</span>
          strServerName.<span style="color: #007788;">MakeUpper</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
          <span style="color: #666666;">// Insert in list and avoid duplicates with this, if</span>
          <span style="color: #666666;">// developer decides not to break the loop after the first</span>
          <span style="color: #666666;">// enumerator.</span>
          <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>setSQLServer.<span style="color: #007788;">insert</span><span style="color: #008000;">&#40;</span>strServerName<span style="color: #008000;">&#41;</span>.<span style="color: #007788;">second</span><span style="color: #008000;">&#41;</span>
            ATLTRACE<span style="color: #008000;">&#40;</span>__FUNCTION__ <span style="color: #FF0000;">&quot; found server %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>,
                  CT2A<span style="color: #008000;">&#40;</span>strServerName.<span style="color: #007788;">GetString</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
          bFoundAny <span style="color: #000080;">=</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
      <span style="color: #008000;">&#125;</span>
&nbsp;
      <span style="color: #666666;">// After we have found data in one enumerator. There is no need</span>
      <span style="color: #666666;">// to do this again.</span>
      <span style="color: #666666;">// But a developer might decide to do this for every enumerator</span>
      <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>bFoundAny<span style="color: #008000;">&#41;</span>
        <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
  <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Ein lauffähiges Projekt kann man hier herunterladen: <a href="http://blog.m-ri.de/wp-content/uploads/2010/01/EnumSQLServer.zip">EnumSQLServer.zip</a>.</p>
<hr /><small>Copyright &copy; 2010 Martin Richter<br />Dieser Feed ist nur für den persönlichen, nicht gewerblichen Gebrauch bestimmt. Eine Verwendung dieses Feeds bzw. der hier veröffentlichten Beiträge auf anderen Webseiten bedarf der ausdrücklichen Genehmigung des Autors.<br />(Digital Fingerprint: bdafe67664ea5aacaab71f8c0a581adf)</small>]]></content:encoded>
			<wfw:commentRss>http://blog.m-ri.de/index.php/2010/01/18/alle-sql-server-enumerieren-mit-den-ole-db-enumeratoren/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AfxOleInit versus CoInitializeEx in MFC Programmen</title>
		<link>http://blog.m-ri.de/index.php/2009/04/30/afxoleinit-versus-coinitializeex-in-mfc-programmen/</link>
		<comments>http://blog.m-ri.de/index.php/2009/04/30/afxoleinit-versus-coinitializeex-in-mfc-programmen/#comments</comments>
		<pubDate>Thu, 30 Apr 2009 18:50:14 +0000</pubDate>
		<dc:creator>Martin Richter</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[COM]]></category>

		<guid isPermaLink="false">http://blog.m-ri.de/?p=445</guid>
		<description><![CDATA[Immer wieder mal, taucht MFC Code auf und es wird CoInitializeEx verwendet. Nicht unbedingt ein Fehler, aber ich denke man sollte auch hier die MFC-Art-und-Weise verwenden: AfxOleInit. Und man sollte sich klar sein, welche Apartment Modes man verwenden darf! AfxOleInit selbst ist ein per Thread Wrapper für ::OleInitialize(NULL);. Zudem sorgt AfxOleInit dafür, dass bei Beenden [...]]]></description>
			<content:encoded><![CDATA[<p>Immer wieder mal, taucht <em>MFC </em>Code auf und es wird <em>CoInitializeEx </em>verwendet.<br />
Nicht unbedingt ein Fehler, aber ich denke man sollte auch hier die MFC-Art-und-Weise verwenden: <em>AfxOleInit</em>. Und man sollte sich klar sein, welche Apartment Modes man verwenden darf!</p>
<p><em>AfxOleInit selbst </em>ist ein per Thread Wrapper für <em><a href="http://msdn.microsoft.com/de-de/library/e91aseaz(VS.80).aspx">::OleInitialize(NULL);</a></em>.<br />
Zudem sorgt <em>AfxOleInit </em>dafür, dass bei Beenden des Threads automatisch <em>AfxOleTerm </em>aufgerufen wird.</p>
<p><em>::OleInitialize(NULL)</em> wiederum ist ein Wrapper für den Aufruf von <em>CoInitializeEx</em> im STA Kontext:<br />
Siehe MSDN <a href="http://msdn.microsoft.com/en-us/library/ms690134(VS.85).aspx">http://msdn.microsoft.com/en-us/library/ms690134(VS.85).aspx</a> </p>
<blockquote><p>OleInitialize calls CoInitializeEx internally to initialize the COM library on the current apartment. Because OLE operations are not thread-safe, OleInitialize specifies the concurrency model as single-thread apartment.</p></blockquote>
<p>Die <em>MFC </em>benutzt und verlangt genau diesen <em>STA </em>Modus. Sofern man also nicht wirklich weiß was man mit <em>CoInitializeEx </em>macht, sollte man es in der <em>MFC </em>vermeiden. Zudem man sich eben auch nicht mehr um den Cleanup kümmern muss, da die MFC dies selber macht.</p>
<p>Siehe auch MSDN Doku zu <em>AfxOleInit</em><br />
<a href="http://msdn.microsoft.com/de-de/library/e91aseaz(VS.80).aspx">http://msdn.microsoft.com/de-de/library/e91aseaz(VS.80).aspx</a></p>
<blockquote><p>MFC applications must be initialized as single threaded apartment (STA). If you call CoInitializeEx in your InitInstance override, specify COINIT_APARTMENTTHREADED (rather than COINIT_MULTITHREADED). For more information, see PRB: MFC Application Stops Responding When You Initialize the Application as a Multithreaded Apartment (828643) at <a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;828643">http://support.microsoft.com/default.aspx?scid=kb;en-us;828643</a>.</p></blockquote>
<p>Aber auch hier sei erwähnt, dass man sicherlich auch andere Apartment Modes verwenden kann. Allerdings muss man dann wirklich wissen was man macht und darf sich nicht auf die <em>MFC</em> Funktionen stützen. Für solche Fälle verwende ich hier komplett ATL in meinen <em>MFC</em> Programmen.<br />
Man sollte aber in diesen Fällen wirklich wissen was man macht <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>BTW: Automatisch aufgeräumt bei einem gestarteten Thread wird nur dann, wenn auch AfxBeginThread verwendet wird. Siehe auch: <a class="l" onmousedown="return clk(this.href,'','','res','1','&amp;sig2=AjTmup5MlQdIipqqmGcT-Q')" href="http://blog.m-ri.de/index.php/2008/02/28/afxbeginthread-versus-_beginthreadex/" target="_blank">AfxBeginThread versus _beginthreadex</a></p>
<hr /><small>Copyright &copy; 2010 Martin Richter<br />Dieser Feed ist nur für den persönlichen, nicht gewerblichen Gebrauch bestimmt. Eine Verwendung dieses Feeds bzw. der hier veröffentlichten Beiträge auf anderen Webseiten bedarf der ausdrücklichen Genehmigung des Autors.<br />(Digital Fingerprint: bdafe67664ea5aacaab71f8c0a581adf)</small>]]></content:encoded>
			<wfw:commentRss>http://blog.m-ri.de/index.php/2009/04/30/afxoleinit-versus-coinitializeex-in-mfc-programmen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Das Web Browser Control stiehlt den Fokus wenn ein Dokument geladen wurde</title>
		<link>http://blog.m-ri.de/index.php/2009/04/15/das-web-browser-control-stiehlt-den-fokus-wenn-ein-dokument-geladen-wurde/</link>
		<comments>http://blog.m-ri.de/index.php/2009/04/15/das-web-browser-control-stiehlt-den-fokus-wenn-ein-dokument-geladen-wurde/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 20:05:34 +0000</pubDate>
		<dc:creator>Martin Richter</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Windows API]]></category>
		<category><![CDATA[ActiveX]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[WinAPI]]></category>

		<guid isPermaLink="false">http://blog.m-ri.de/?p=449</guid>
		<description><![CDATA[Wenn man ein Web Browser Control einbindet und dieses eine Seite lädt, dann wird der Fokus in dieses Browser Control gesetzt. Dagegen ist kein Kraut und keine Notification gewachsen. Genaugenommen ist nicht das Webbrowser Control schuld, sondern der Scriptcode der auf der Seite läuft und den Fokus umsetzt. Das sieht man schnell wenn man den [...]]]></description>
			<content:encoded><![CDATA[<p>Wenn man ein Web Browser Control einbindet und dieses eine Seite lädt, dann wird der Fokus in dieses Browser Control gesetzt. Dagegen ist kein Kraut und keine Notification gewachsen.<br />
Genaugenommen ist nicht das Webbrowser Control schuld, sondern der Scriptcode der auf der Seite läuft und den Fokus umsetzt. Das sieht man schnell wenn man den Moment der <em>WM_KILLFOCUS </em>Nachricht im Debugger abpasst und sich den Stacktrace ansieht.</p>
<pre>0013b84c 4a570824 USER32!NtUserSetFocus
0013b858 4a5ce628 mshtml!CDoc::TakeFocus+0x2a
0013b880 4a63fc0b mshtml!CElement::BecomeCurrent+0x167
0013b8b4 4a63fb72 mshtml!CElement::focusHelper+0xcc
0013b8c0 4a587c85 mshtml!CElement::focus+0x1d
0013b8cc 4a5d7477 mshtml!Method_void_void+0x17
0013b94c 4a57fae8 mshtml!CBase::ContextInvokeEx+0x462
0013b97c 4a575413 mshtml!CElement::ContextInvokeEx+0x72
0013b9b0 76fa5295 mshtml!CElement::ContextThunk_InvokeEx+0x44
0013b9e8 76fa5208 jscript!IDispatchExInvokeEx2+0xa9
0013ba20 76fa5323 jscript!IDispatchExInvokeEx+0x56
0013ba90 76fa577b jscript!InvokeDispatchEx+0x78
0013bad8 76fa57c6 jscript!VAR::InvokeByName+0x1c1
0013bb18 76fa4ab0 jscript!VAR::InvokeDispName+0x43
0013bb3c 76fa5a14 jscript!VAR::InvokeByDispID+0xfb
0013bd30 76fa46d8 jscript!CScriptRuntime::Run+0x195b
0013bdf4 76fa506e jscript!ScrFncObj::Call+0x69
0013be6c 76fa5f6a jscript!CSession::Execute+0xb8
0013bf6c 76fa672f jscript!NameTbl::InvokeDef+0x183
0013c040 76fa5295 jscript!NameTbl::InvokeEx+0xd2</pre>
<p>Dummerweise gibt es kein Event mehr, das danach gefeuert wird, wenn der Skript-Code abläuft. Das letzte Event bevor das aktive Fenster den Fokus verliert ist <em>OnDocumentComplete</em>.</p>
<p>Es gibt auch einige Threads die dieses Thema behandeln, aber keine vernünftige Lösung. Von so manchen Timerlösungen halte ich nichts, die da so vorgeschlagen werden, wer weiß schon wann eine Seite geladen ist?<br />
Besonders ärgerlich auch, wenn man das Browser Control nicht mal auf einem sichtbaren Fenster hat, sondern nur in einem versteckten Fenster hält. Auch in diesem Fall verliert das aktive Fenster den Fokus.</p>
<p>Aber mit einem kleinen Trick bekommt man es doch hin ( <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  warum sonst schreibe ich den Artikel )</p>
<ol>
<li>Man baut einen <em>OnDocumentComplete </em>Handler ein.</li>
<li>Wenn das Event eintritt, besorgt man sich mit <em>GetFocus </em>das Fenster, dass aktuell noch den Fokus inne hat.</li>
<li>Nun sendet man mit <em>PostMessage </em>eine selbst definierte Nachricht (<em>#define WM_RESTOREFOCUS (WM_APP+x)</em>) an den Container des Webbrowser Controls und übergibt als <em>wParam </em>einfach das Handle des Fensters, dass man soeben mit <em>GetFocus </em>ermittelt hat.</li>
<li>Nach diesem Event wird der Skript-Code ausgeführt, der den Fokus stiehlt. Das stört uns nicht.</li>
<li>Irgendwann kommt die Messageloop jetzt wieder an die Reihe und zieht die benutzerdefinierte Nachricht <em>WM_RESTOREFOCUS </em>aus der Queue.</li>
<li>Man hat natürlich einen Handler für diese Nachricht im Container des Webbrowser Controls. Dieser macht nun nichts anderes als einen <em>SetFocus</em> auf das <em>HWND </em>Handle auszuführen, das im <em>wParam </em>übergeben wurde. Ein Test zuvor mit <em>IsWindow </em>versteht sich von selbst.</li>
</ol>
<p>Dadurch, dass die Nachricht in der Message-Queue gepostet wird, wird sie zeitnah ausgeführt sobald wirklich der User wieder eine Chance selbst Eingaben zu machen. Problem zufriedenstellend gelöst.</p>
<p>Das sollte sich sogar mit <em>C#</em> oder <em>VB</em> hinbekommen lassen <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<hr /><small>Copyright &copy; 2010 Martin Richter<br />Dieser Feed ist nur für den persönlichen, nicht gewerblichen Gebrauch bestimmt. Eine Verwendung dieses Feeds bzw. der hier veröffentlichten Beiträge auf anderen Webseiten bedarf der ausdrücklichen Genehmigung des Autors.<br />(Digital Fingerprint: bdafe67664ea5aacaab71f8c0a581adf)</small>]]></content:encoded>
			<wfw:commentRss>http://blog.m-ri.de/index.php/2009/04/15/das-web-browser-control-stiehlt-den-fokus-wenn-ein-dokument-geladen-wurde/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Der etwas bessere CMemDC</title>
		<link>http://blog.m-ri.de/index.php/2008/12/14/der-etwas-bessere-cmemdc/</link>
		<comments>http://blog.m-ri.de/index.php/2008/12/14/der-etwas-bessere-cmemdc/#comments</comments>
		<pubDate>Sun, 14 Dec 2008 14:52:42 +0000</pubDate>
		<dc:creator>Martin Richter</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[Windows API]]></category>
		<category><![CDATA[WinAPI]]></category>

		<guid isPermaLink="false">http://blog.m-ri.de/?p=382</guid>
		<description><![CDATA[CMemDC aus dem Artikel Flicker free drawing with MFC ist wohl der Klassiker für Doublebuffering und ist wohl jedem MFC Entwickler bekannt. Er macht was er soll und ich habe ihn selbst über Jahre hinweg unverändert verwendet. Solange man einfache Sachen macht und ausschließlich den MM_TEXT Mappingmode verwendet ist alles OK. Hat man sich aber was [...]]]></description>
			<content:encoded><![CDATA[<p><em>CMemDC </em>aus dem Artikel <a href="http://www.codeproject.com/KB/GDI/flickerfree.aspx">Flicker free drawing with MFC</a> ist wohl der Klassiker für Doublebuffering und ist wohl jedem MFC Entwickler bekannt.</p>
<p>Er macht was er soll und ich habe ihn selbst über Jahre hinweg unverändert verwendet. Solange man einfache Sachen macht und ausschließlich den <em>MM_TEXT </em>Mappingmode verwendet ist alles OK.<br />
Hat man sich aber was spezielles &#8211; zoomfähiges &#8211; zusammengebaut mit <em>MM_ANISOTROPIC</em> dann funktioniert das Ganze nicht mehr, weil Keith an den Window Origin Koordinaten dreht und nicht am Viewport.</p>
<p>Meine abgewandelte Variante trägt einer entsprechende Verwendung auch für andere Mappingmodes Rechnung. Es müsste IMHO für jeden funktionieren. Intensiv getestet habe ich es mit <em>MM_ANISOTROPIC</em>.</p>
<p>Will/muss man auch an den Viewport Koordinaten drehen, dann sollten die alten Viewport Koordinaten gelesen werden und dann entsprechend durch ein Offset geändert werden.<br />
Alles anderen Werte wie die Extents können beliebig verändert werden.<br />
Bei der Verwendung sollte <em>MM_TEXT </em>eingeschaltet sein (entsprechende <em>ASSERTs </em>habe ich ergänzt). <em>MM_TEXT </em>ist normalerweise gesetzt, wenn <em>CMemDC </em>direkt nach Instanzierung des <em>CPaintDC </em>zum Einsatz kommt. Der Destruktor setzt dann den Mappingmode auf <em>MM_TEXT </em>zurück.</p>
<p>Dieser neue, modifizierte <em>CMemDC</em> kann einfach die bisherige Implementierung ersetzen.</p>
<p>Have fun &amp; Happy coding <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> CMemDC <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> CDC
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
  <span style="color: #666666;">// constructor sets up the memory DC</span>
  CMemDC<span style="color: #008000;">&#40;</span>CDC<span style="color: #000040;">*</span> pDC<span style="color: #008000;">&#41;</span>
    <span style="color: #008080;">:</span> CDC<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
    , m_pDC<span style="color: #008000;">&#40;</span>pDC<span style="color: #008000;">&#41;</span>
    , m_pOldBitmap<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span>
    , m_bMemDC<span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>m_pDC<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>IsPrinting<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
  <span style="color: #008000;">&#123;</span>
    ASSERT<span style="color: #008000;">&#40;</span>pDC <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_bMemDC<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
      <span style="color: #666666;">// Create a Memory DC.</span>
      <span style="color: #666666;">// At this moment we should have mapping mode text</span>
      ASSERT<span style="color: #008000;">&#40;</span>m_pDC<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>GetMapMode<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #000080;">==</span>MM_TEXT<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      ASSERT<span style="color: #008000;">&#40;</span>m_pDC<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>GetWindowOrg<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #000080;">==</span>CPoint<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span>,<span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      ASSERT<span style="color: #008000;">&#40;</span>m_pDC<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>GetViewportOrg<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #000080;">==</span>CPoint<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span>,<span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
      <span style="color: #666666;">// Get the clip box and create bitmap for this size</span>
      m_pDC<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>GetClipBox<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>m_rect<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      CreateCompatibleDC<span style="color: #008000;">&#40;</span>m_pDC<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      m_bitmap.<span style="color: #007788;">CreateCompatibleBitmap</span><span style="color: #008000;">&#40;</span>m_pDC, 
              m_rect.<span style="color: #007788;">Width</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, m_rect.<span style="color: #007788;">Height</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      m_pOldBitmap <span style="color: #000080;">=</span> SelectObject<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>m_bitmap<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
      <span style="color: #666666;">// Adjust the view port so that we hit the clip rect.</span>
      SetViewportOrg<span style="color: #008000;">&#40;</span><span style="color: #000040;">-</span>m_rect.<span style="color: #007788;">left</span>, <span style="color: #000040;">-</span>m_rect.<span style="color: #007788;">top</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      IntersectClipRect<span style="color: #008000;">&#40;</span>m_rect<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
      <span style="color: #666666;">// Fill background in case the user has overridden</span>
      <span style="color: #666666;">// WM_ERASEBKGND.  We end up with garbage otherwise.</span>
      FillSolidRect<span style="color: #008000;">&#40;</span>m_rect, m_pDC<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>GetBkColor<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">else</span>
    <span style="color: #008000;">&#123;</span>
      <span style="color: #666666;">// Make a copy of the relevant parts of the current DC for printing</span>
      m_bPrinting <span style="color: #000080;">=</span> m_pDC<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>m_bPrinting<span style="color: #008080;">;</span>
      m_hDC     <span style="color: #000080;">=</span> m_pDC<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>m_hDC<span style="color: #008080;">;</span>
      m_hAttribDC <span style="color: #000080;">=</span> m_pDC<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>m_hAttribDC<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
  <span style="color: #008000;">&#125;</span>
&nbsp;
  <span style="color: #666666;">// Destructor copies the contents of the mem DC to the original DC</span>
  ~CMemDC<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
  <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_bMemDC<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
      <span style="color: #666666;">// The mapping mode might effect the BitBlt. So we need to return to</span>
      <span style="color: #666666;">// MM_TEXT. This makes m_rect.left and m_rect.top again the</span>
      <span style="color: #666666;">// coordinates of our clipped rectangle. And to make sure that the</span>
      <span style="color: #666666;">// coordinates are really used we just clear the ViewportOrg and the</span>
      <span style="color: #666666;">// WindowOrg</span>
      SetMapMode<span style="color: #008000;">&#40;</span>MM_TEXT<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      SetViewportOrg<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span>,<span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
      SetWindowOrg<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span>,<span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
      <span style="color: #666666;">// Copy the off screen bitmap onto the screen.</span>
      <span style="color: #666666;">// For this we just make sure that we really target the rectangle of</span>
      <span style="color: #666666;">// our temporal bitmap.</span>
      m_pDC<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>BitBlt<span style="color: #008000;">&#40;</span>m_rect.<span style="color: #007788;">left</span>, m_rect.<span style="color: #007788;">top</span>, 
              m_rect.<span style="color: #007788;">Width</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, m_rect.<span style="color: #007788;">Height</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>,
              <span style="color: #0000dd;">this</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span>, SRCCOPY<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
      <span style="color: #666666;">//Swap back the original bitmap.</span>
      SelectObject<span style="color: #008000;">&#40;</span>m_pOldBitmap<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">else</span>
    <span style="color: #008000;">&#123;</span>
      <span style="color: #666666;">// All we need to do is replace the DC with an illegal value,</span>
      <span style="color: #666666;">// this keeps us from accidentally deleting the handles associated</span>
      <span style="color: #666666;">// with the CDC that was passed to the constructor.</span>
      m_hDC <span style="color: #000080;">=</span> m_hAttribDC <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
  <span style="color: #008000;">&#125;</span>
&nbsp;
  <span style="color: #666666;">// Allow usage as a pointer</span>
  CMemDC<span style="color: #000040;">*</span> operator<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>  <span style="color: #008000;">&#123;</span>   <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">this</span><span style="color: #008080;">;</span>  <span style="color: #008000;">&#125;</span>
&nbsp;
  <span style="color: #666666;">// Allow usage as a pointer</span>
  operator CMemDC<span style="color: #000040;">*</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>  <span style="color: #008000;">&#123;</span>   <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">this</span><span style="color: #008080;">;</span>  <span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
  CBitmap  m_bitmap<span style="color: #008080;">;</span>    <span style="color: #666666;">// Offscreen bitmap</span>
  CBitmap<span style="color: #000040;">*</span> m_pOldBitmap<span style="color: #008080;">;</span>  <span style="color: #666666;">// bitmap originally found in CMemDC</span>
  CDC<span style="color: #000040;">*</span>   m_pDC<span style="color: #008080;">;</span>     <span style="color: #666666;">// Saves CDC passed in constructor</span>
  CRect  m_rect<span style="color: #008080;">;</span>    <span style="color: #666666;">// Rectangle of drawing area.</span>
  <span style="color: #0000ff;">bool</span>   m_bMemDC<span style="color: #008080;">;</span>    <span style="color: #666666;">// true if CDC really is a Memory DC.</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<hr /><small>Copyright &copy; 2010 Martin Richter<br />Dieser Feed ist nur für den persönlichen, nicht gewerblichen Gebrauch bestimmt. Eine Verwendung dieses Feeds bzw. der hier veröffentlichten Beiträge auf anderen Webseiten bedarf der ausdrücklichen Genehmigung des Autors.<br />(Digital Fingerprint: bdafe67664ea5aacaab71f8c0a581adf)</small>]]></content:encoded>
			<wfw:commentRss>http://blog.m-ri.de/index.php/2008/12/14/der-etwas-bessere-cmemdc/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Externe und interne COM Zugriffe unterscheiden</title>
		<link>http://blog.m-ri.de/index.php/2008/12/10/externe-und-interne-com-zugriffe-unterscheiden/</link>
		<comments>http://blog.m-ri.de/index.php/2008/12/10/externe-und-interne-com-zugriffe-unterscheiden/#comments</comments>
		<pubDate>Wed, 10 Dec 2008 18:54:01 +0000</pubDate>
		<dc:creator>Martin Richter</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[Sonstiges]]></category>
		<category><![CDATA[Windows API]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[WinAPI]]></category>

		<guid isPermaLink="false">http://blog.m-ri.de/?p=322</guid>
		<description><![CDATA[Ich benutze als interne Makrosprache gerne VBScript. D.h. ich hoste VBScript. Ich biete dann bestimmte COM-Objekte (IDisptach) an, die es dem Nutzer erlauben mein  Programm anzupassen oder intern zu steuern. Nun macht es aber unter Umständen einen gravierenden Unterschied, ob ein COM-Objekt von einem programminternen Nutzer, oder von extern angesprochen wird. Intern möchte ich zum Beispiel mehr  [...]]]></description>
			<content:encoded><![CDATA[<p>Ich benutze als interne Makrosprache gerne <em>VBScript</em>. D.h. ich hoste <em>VBScript</em>.<br />
Ich biete dann bestimmte <em>COM</em>-Objekte (<em>IDisptach</em>) an, die es dem Nutzer erlauben mein  Programm anzupassen oder intern zu steuern.</p>
<p>Nun macht es aber unter Umständen einen gravierenden Unterschied, ob ein <em>COM</em>-Objekt von einem programminternen Nutzer, oder von extern angesprochen wird. Intern möchte ich zum Beispiel mehr  oder andere Funktionen erlauben als durch einen externen Zugriff von einem anderen Programm oder Skript.</p>
<p>Wie kann man aber unterscheiden von wo ein <em>COM </em>Zugriff erfolgt <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_question.gif' alt=':?:' class='wp-smiley' /> </p>
<p>Netterweise hat COM die Funktion <a href="http://msdn.microsoft.com/en-us/library/ms691483(VS.85).aspx">CoGetCallContext</a>, die mir genau diese Info liefert. Liefert <em>CoGetCallContext S_OK </em>und damit einen Interfacezeiger auf <em>IServerSecurity</em>, dann wurde der COM Zugriff von einem externen Prozess abgesetzt. Wenn <em>CoGetCallObject E_NOINTERFACE </em>zurück gibt haben wir einen internen Aufruf aus dem eigenen Prozess heraus.</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">bool</span> IsExternalComCall<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
 <span style="color: #666666;">// get context</span>
 CComPtr<span style="color: #000080;">&lt;</span>IServerSecurity<span style="color: #000080;">&gt;</span> spSecurity<span style="color: #008080;">;</span>
 HRESULT hr <span style="color: #000080;">=</span> <span style="color: #008080;">::</span><span style="color: #007788;">CoGetCallContext</span><span style="color: #008000;">&#40;</span>IID_IServerSecurity,
                      <span style="color: #0000ff;">reinterpret_cast</span><span style="color: #000080;">&lt;</span><span style="color: #0000ff;">void</span><span style="color: #000040;">**</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>spSecurity<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
 <span style="color: #0000ff;">return</span> SUCCEEDED<span style="color: #008000;">&#40;</span>hr<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p lang="cpp">Herzlichen Dank an René König für diesen Ansatz, den er mir in microsoft.public.de.vc gab.</p>
<hr /><small>Copyright &copy; 2010 Martin Richter<br />Dieser Feed ist nur für den persönlichen, nicht gewerblichen Gebrauch bestimmt. Eine Verwendung dieses Feeds bzw. der hier veröffentlichten Beiträge auf anderen Webseiten bedarf der ausdrücklichen Genehmigung des Autors.<br />(Digital Fingerprint: bdafe67664ea5aacaab71f8c0a581adf)</small>]]></content:encoded>
			<wfw:commentRss>http://blog.m-ri.de/index.php/2008/12/10/externe-und-interne-com-zugriffe-unterscheiden/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VS Tipps &amp; Tricks: Heap Bugs finden (Teil 3)</title>
		<link>http://blog.m-ri.de/index.php/2008/11/04/vs-tipps-tricks-heap-bugs-finden-teil-3/</link>
		<comments>http://blog.m-ri.de/index.php/2008/11/04/vs-tipps-tricks-heap-bugs-finden-teil-3/#comments</comments>
		<pubDate>Tue, 04 Nov 2008 19:30:59 +0000</pubDate>
		<dc:creator>Martin Richter</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[CRT]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[VS-Tipps&Tricks]]></category>
		<category><![CDATA[Windows API]]></category>
		<category><![CDATA[Debuggen]]></category>
		<category><![CDATA[Qualitätssicherung]]></category>
		<category><![CDATA[WinAPI]]></category>

		<guid isPermaLink="false">http://blog.m-ri.de/?p=357</guid>
		<description><![CDATA[Mancher Bug macht einem nicht den Gefallen und lässt sich in der Debug-Version finden. Ursache ist oft genug eine Variable, die in der Debug-Version initialisiert (0xCC) wird aber in der Release-Version zu einem Crash führt, wenn zufällige Daten auf dem Stack für undefiniertes Verhalten sorgen. Also macht man sich an das debuggen der Release Version [...]]]></description>
			<content:encoded><![CDATA[<p>Mancher Bug macht einem nicht den Gefallen und lässt sich in der Debug-Version finden. Ursache ist oft genug eine Variable, die in der Debug-Version initialisiert (0xCC) wird aber in der Release-Version zu einem Crash führt, wenn zufällige Daten auf dem Stack für undefiniertes Verhalten sorgen.</p>
<p>Also macht man sich an das debuggen der Release Version und kann keinen Fehler finden.<br />
Kaum startet man das Programm ohne Debugger dann kracht es wieder. Warum?</p>
<p>Manch einer könnte jetzt denken: Der Debugger verändert das Memory Layout! Das tut er schon, aber entscheidend für ein anderes Verhalten ist der Debug Heap!<br />
Die wenigsten Entwickler wissen überhaupt, dass es ihn gibt. Ich meine hier nicht die Debug Funktionen, die die CRT zur Verfügung stellt, denn mein Thema heute ist ja das Debuggen eines Release-Programms, und die Debug-CRT hat ja bekanntlich in einem Release Programm nichts zu suchen!</p>
<p>Machen wir es praktisch und nehmen wieder mein kleines Crashtest-Programm:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;windows.h&gt;</span>
<span style="color: #339900;">#include &lt;tchar.h&gt;</span>
<span style="color: #339900;">#include &lt;crtdbg.h&gt;</span>
<span style="color: #0000ff;">int</span> _tmain<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, _TCHAR<span style="color: #000040;">*</span> argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
  <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>pCorrupt <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> <span style="color: #0000ff;">char</span><span style="color: #008000;">&#91;</span><span style="color: #0000dd;">100</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
  ZeroMemory<span style="color: #008000;">&#40;</span>pCorrupt,<span style="color: #0000dd;">104</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span>pOther <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> <span style="color: #0000ff;">char</span><span style="color: #008000;">&#91;</span><span style="color: #0000dd;">100</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
  ZeroMemory<span style="color: #008000;">&#40;</span>pOther,<span style="color: #0000dd;">100</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  <span style="color: #0000dd;">delete</span> <span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> pOther<span style="color: #008080;">;</span>
  <span style="color: #0000dd;">delete</span> <span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> pCorrupt<span style="color: #008080;">;</span>
  <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Wenn wir dieses Programm als Release Version kompilieren und ausführen, dann erhalten wir keine Fehlermeldung <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_exclaim.gif' alt=':!:' class='wp-smiley' />  Interessant. Der Heap ist nicht soweit zerstört, dass es zu einer Zugriffsverletzung kommt. Starten wir aber unser Programm mit dem Debugger, dann wird der so genannte Debug Heap des Systems verwendet, der wie die Debug-CRT Guardbytes setzt und kontrolliert.</p>
<p>Ein weiteres Problem entsteht dadurch, dass der Debug Heap den allokierten Speicher auf feste Werte initialisiert genau wie die Debugversion der CRT. Wenn also nicht initialisierter Speicher genutzt wird, dann ist das Verhalten mit dem Debug-Heap deterministisch, ohne Debug Heap eher zufällig.</p>
<p>Das im Debugger alles etwas anders sein kann ist sogar <a href="http://msdn.microsoft.com/en-us/library/cc266414.aspx">dokumentiert</a> <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<blockquote><p>Processes that the debugger creates (also known as spawned processes) behave slightly differently than processes that the debugger does not create.<br />
Instead of using the standard heap API, processes that the debugger creates use a special debug heap. On Microsoft Windows XP and later versions of Windows, you can force a spawned process to use the standard heap instead of the debug heap by using the _NO_DEBUG_HEAP environment variable or the -hd command-line option.</p></blockquote>
<p>In diesem Text steht auch, wie man den Debug-Heap ausschalten kann, mit:</p>

<div class="wp_syntax"><div class="code"><pre class="bat" style="font-family:monospace;">SETX _NO_DEBUG_HEAP 1</pre></div></div>

<p>Diese Environment-Variable sorgt dafür, dass sich auch bei geladenem Debugger, das Programm so verhält wie ohne Debugger (hoffentlich). Führt man mein Testprogramm nun im Debugger aus, wenn die Environment-Variable <em>_NO_DEBUG_HEAP </em>auf 1 gesetzt ist, erhält man keinen Debug-Break mehr. Denn in diesem Fall gibt es keine Guardbytes, die geprüft werden.<br />
Löscht man den Eintrag <em>_NO_DEBUG_HEAP </em>wieder, dann erhält man im Debugger wieder wie erwartet einen Break.</p>
<p>Will man also wirklich realitätsnah eine Release-Version debuggen, dann kommt man um das Ausschalten des Debug-Heaps nicht herum.</p>
<p>PS: Man kann es auch etwas einfacher haben, wenn man sich nachträglich an den Prozess mit dem Debugger attached (wenn das geht). Ideal ist dieses Verfahren auch beim Remote-Debugging (dazu demnächst mehr).</p>
<hr /><small>Copyright &copy; 2010 Martin Richter<br />Dieser Feed ist nur für den persönlichen, nicht gewerblichen Gebrauch bestimmt. Eine Verwendung dieses Feeds bzw. der hier veröffentlichten Beiträge auf anderen Webseiten bedarf der ausdrücklichen Genehmigung des Autors.<br />(Digital Fingerprint: bdafe67664ea5aacaab71f8c0a581adf)</small>]]></content:encoded>
			<wfw:commentRss>http://blog.m-ri.de/index.php/2008/11/04/vs-tipps-tricks-heap-bugs-finden-teil-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

