<?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/tag/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>VS-Tipps und Tricks:Feststellen ob ATL oder MFC in einem Projekt benutzt werden</title>
		<link>http://blog.m-ri.de/index.php/2011/07/10/vs-tipps-und-tricksfeststellen-ob-atl-oder-mfc-in-einem-projekt-benutzt-werden/</link>
		<comments>http://blog.m-ri.de/index.php/2011/07/10/vs-tipps-und-tricksfeststellen-ob-atl-oder-mfc-in-einem-projekt-benutzt-werden/#comments</comments>
		<pubDate>Sun, 10 Jul 2011 15:45:06 +0000</pubDate>
		<dc:creator>Martin Richter</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[VS-Tipps&Tricks]]></category>
		<category><![CDATA[ATL]]></category>

		<guid isPermaLink="false">http://blog.m-ri.de/?p=747</guid>
		<description><![CDATA[Für manche Standardklassen bzw. Header oder Libraries ist es manchmal schön zu wissen ob die ATL oder die MFC in einem Projekt verwendet werden.  In der Vergangenheit habe ich dies oft benutzt um bestimmte Member in Klassen einzubauen, die dann zum Beispiel Daten auch als CString aktzeptieren, oder diese Member dann eben nicht einzubauen um eine Nutzung [...]]]></description>
			<content:encoded><![CDATA[<p>Für manche Standardklassen bzw. Header oder Libraries ist es manchmal schön zu wissen ob die <em>ATL</em> oder die <em>MFC</em> in einem Projekt verwendet werden.  In der Vergangenheit habe ich dies oft benutzt um bestimmte Member in Klassen einzubauen, die dann zum Beispiel Daten auch als <em>CString </em>aktzeptieren, oder diese Member dann eben nicht einzubauen um eine Nutzung in einem &#8220;puren&#8221; <em>WinAPI</em> Projekt zu ermöglichen.<br />
Seit die <em>CString </em>Klassen allerdings eigenständige Templates wurden ist dieser Grund für mich eigentlich weggefallen.<br />
Ich benutzte es heute nur noch um evtl. Memberfunktionen zu unterscheiden die evtl. CWnd* zusätzlich zu HWND Parametern akzeptieren.</p>
<p>Aber wer weiß, vielleicht hat der eine oder andere doch die Frage wie er erkennen kann ob die <em>ATL</em> oder die <em>MFC</em> in einem Projekt Verwendung finden.</p>
<p>Vordefinierte Preprozessor Variablen gibt es dafür nicht, allerdings kann man erkennen ob die Standard <em>ATL</em>/<em>MFC</em>Header in einem Projekt bereits als Include eingefügt wurden, denn in diesem Fall kann man die Existenz der Include-Guards prüfen.</p>
<p>Die <em>MFC</em> benutzt <strong><em>__AFX_H__ </em></strong>als Guard für die <em>afx.h</em>.<br />
Die Basisklassen der <em>ATL</em> befinden sich in der <em>atlbase.h</em>und entsprechend lautet der Guard: <strong><em>__ATLBASE_H__</em></strong>.</p>
<p>Sofern also diese Guards definiert sind wurden auch die entsprechenden Libraries in der <em>stdafx.h</em> oder anderen Headern zuvor included.</p>
<p><strong>Nachtrag 12.07.2011:<br />
Stefan</strong> hat natürlich vollkommen recht mit seinem Kommentar, dass es die zwei Präprozessor-Variablen <strong><em>_MFC_VER </em></strong>und <strong><em>_ATL_VER </em></strong>gibt, die natürlich für den hier erwähnten Einsatz weitaus besser geeigent sind.<br />
Siehe: <a href="http://msdn.microsoft.com/de-de/library/b0084kay.aspx">http://msdn.microsoft.com/de-de/library/b0084kay.aspx</a><br />
Ich habe hier den Wald vor lauter Bäumen nicht gesehen <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /><br />
Herzlichen Dank für diese produktive Ergänzung.</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/07/10/vs-tipps-und-tricksfeststellen-ob-atl-oder-mfc-in-einem-projekt-benutzt-werden/feed/</wfw:commentRss>
		<slash:comments>2</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>VS Tipps &amp; Tricks: Heap Bugs finden (Teil 2)</title>
		<link>http://blog.m-ri.de/index.php/2008/10/31/vs-tipps-tricks-heap-bugs-finden-teil-2/</link>
		<comments>http://blog.m-ri.de/index.php/2008/10/31/vs-tipps-tricks-heap-bugs-finden-teil-2/#comments</comments>
		<pubDate>Fri, 31 Oct 2008 18:42:52 +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[IDE]]></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=355</guid>
		<description><![CDATA[Einige Hilfsmittel um einen Heap-Fehler zu finden habe ich in meinem letzten Beitrag ja beschrieben. Eigentlich wünscht sich der Entwickler nichts mehr, als dass ein falscher Zugriff auf den Heap, sofort einen Break im Debugger auslöst. Die Methoden, die ich bisher gezeigt habe (AfxCheckMemory, _CrtCheckMemory, _CrtSetDbgFlag) können das nicht direkt , aber zumindest helfen sie den [...]]]></description>
			<content:encoded><![CDATA[<p>Einige Hilfsmittel um einen Heap-Fehler zu finden habe ich in meinem <a href="http://blog.m-ri.de/index.php/2008/10/27/vs-tipps-tricks-heap-bugs-finden-teil-1/">letzten Beitrag</a> ja beschrieben.</p>
<p>Eigentlich wünscht sich der Entwickler nichts mehr, als dass ein falscher Zugriff auf den Heap, sofort einen <em>Break </em>im Debugger auslöst. Die Methoden, die ich bisher gezeigt habe (<em>AfxCheckMemory</em>, <em>_CrtCheckMemory</em>, <em>_CrtSetDbgFlag</em>) können das nicht direkt , aber zumindest helfen sie den Fehler einzukreisen.</p>
<p>Ein unverzichtbarer Helfer, der sofort solch einen <em>Break </em>auslösen kann, ist der <a href="http://msdn.microsoft.com/de-de/library/ms220948(VS.80).aspx">Application Verifier</a>, den ich bereits in einem älteren Artikel als <a href="http://blog.m-ri.de/index.php/2007/03/02/der-application-verifier-mein-neuer-freund/">Freund und Helfer</a> vorgestellt habe.</p>
<p>Seit <em>Visual Studio 2005 </em>kann man direkt Parameter für den <em>Application Verifier </em>im Projekt einstellen und auch direkt den Debug-Prozess mit dem Application Verifier starten (<em>Umschalt+Alt+F5</em>).<br />
An den Standardeinstellungen im Projekt braucht man hier gar nichts zu ändern:<br />
<em>Conserve Memory </em>- No<br />
<em>Protection Location </em>- Je nach Testfall (man sollte mit beiden Einstellungen mal debuggen)<br />
Alle anderen Einstellungen <em>Verification Layers Settings </em>- auf Enable</p>
<p>Mit dem <em>Application Verifier </em>lässt sich der so genannte <em>Paged Heap </em>nutzen, der Guard Pages anlegt hinter oder vor den allokierten Speicherbereichen (siehe auch GFLAGS.EXE). Der Vorteil: Man erhält sofort eine Access Violation, wenn man den Speicherbereich überschreitet.</p>
<p>Mein kleines Demoproramm</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
</pre></td><td 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;">106</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// -- This will corrupt the heap</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></td></tr></table></div>

<p>crashed mit der Nutzung des <em>Application Verifiers </em>sofort und man kann im Call Stack die Zeile 7 ausmachen.<br />
Genial ist besonders, dass der <em>Application Verifier</em> auch mit der Release Version sofort die Zeile 7 als Ursache identifiziert. Gerade wenn man also nicht auf die <em>Debug-CRT</em> zurückgreifen kann, ist der Application Verifier ein super Hilfsmittel.</p>
<p>Der Nachteil: Die Guard Pages liegen nicht exakt und direkt hinter dem allokierten Bereich, sondern auf der nächsten Page Boundary. Deshalb crashed mein Sample auch nicht wenn man den Speicher um nur 1 Byte überschreitet.</p>
<p>Aber der Application Verifier ist zum Testen ein absolutes Muss, weil auch falsche Handles erkannt werden und auch der Lock Verfification Layer für die Qualitätssicherung einfach nützlich zum entwanzen sind. (siehe auch <a href="http://msdn.microsoft.com/en-us/library/ms220936.aspx">Application Verifier Einstellungen in der MSDN</a>).</p>
<p>Hinweis <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_exclaim.gif' alt=':!:' class='wp-smiley' /> </p>
<p>Auf <em>Windows XP </em>und <em>Windows Server 2003 </em>erhält man ohne administrative Rechte die folgende Fehlermeldung:</p>
<blockquote><p>Access denied. You need administrative credentials to use Application Verifier on image &lt;App_Name.exe&gt; on machine &lt;Machine_Name&gt;. Contact your system administrator for assistance</p></blockquote>
<p>Unter Windows Vista oder Windows Server 2008 erhält man die flogende Fehlermeldung wenn der Application Verifier nicht elevated gestartet wird:</p>
<blockquote><p>Access denied. You need administrative credentials to use Application Verifier on image &lt;App_Name.exe&gt; on machine &lt;Machine_Name&gt; or per user verifier settings should be enabled by the administrator. Please refer to documentation for more information.</p></blockquote>
<p>Durch einen simplen Eintrag in der Registry lässt sich aber auch als normaler Benutzer, ohne administrative Rechte, der<em> Application Verifier </em>nutzen, man erzeugt einen DWORD Eintrag in der Registry mit dem Wert 1<br />
<em>HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manger\ImageExecutionOptions<br />
</em>Nach einem Reboot kann man nun einfach den <em>Application Verifier </em>auch non-elevated, als normaler Benutzer nutzen.</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/10/31/vs-tipps-tricks-heap-bugs-finden-teil-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Late Binding und schwache Performance durch GetIDsOfNames</title>
		<link>http://blog.m-ri.de/index.php/2008/02/16/late-binding-und-schwache-performance-durch-getidsofnames/</link>
		<comments>http://blog.m-ri.de/index.php/2008/02/16/late-binding-und-schwache-performance-durch-getidsofnames/#comments</comments>
		<pubDate>Sat, 16 Feb 2008 13:45:34 +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[COM]]></category>

		<guid isPermaLink="false">http://blog.m-ri.de/index.php/2008/02/16/late-binding-und-schwache-performance-durch-getidsofnames/</guid>
		<description><![CDATA[Immer wieder sehe ich Entwickler, die über Late Binding COM Komponenten ansprechen. Das ist an sich nur zu unterstützen, denn DISPIDs können sich schnell mal ändern, wenn sich ein Interface ändert. Gerade bei den rasant an Verbreitung zunehmenden .NET Komponenten, die man mal schnell in die eigene Anwendung per COM einbindet, kann das Binding über die Interfaces [...]]]></description>
			<content:encoded><![CDATA[<p>Immer wieder sehe ich Entwickler, die über Late Binding COM Komponenten ansprechen. Das ist an sich nur zu unterstützen, denn <em>DISPIDs </em>können sich schnell mal ändern, wenn sich ein Interface ändert. Gerade bei den rasant an Verbreitung zunehmenden .NET Komponenten, die man mal schnell in die eigene Anwendung per COM einbindet, kann das Binding über die Interfaces und <em>DISPIDs </em>schnell zum Frust werden. Gleiches gilt für Office Komponenten, bei denen man sich nicht zwingend an ein Interface binden will. Zudem ist es der von <a href="http://support.microsoft.com/kb/247579/en-us">Microsoft empfohlene Weg</a> die Office-Automation zu benutzen (siehe auch <a href="http://support.microsoft.com/kb/245115/en-us">hier</a>).</p>
<p>OK! Also man nimmt Late Binding und verwendet z.B. die aktuellen Wrapper, die netterweise von der ATL zur Verfügung gestellt werden,  z.B. die netten Funktionen aus der <a href="http://msdn2.microsoft.com/en-us/library/9yb5s0fk(VS.80).aspx"><em>CComDispatchDriver</em></a> Klasse. <em>GetPropertyByName</em>, <em>PutPropertyByName </em>und auch die Funktionen <em>Invoke0</em>, <em>Invoke1 </em>und <em>InvokeN </em>haben entsprechende Überladungen, die die Verwendung von Funktions-/Eigenschaftsnamen direkt erlauben.</p>
<p>Der Nachteil liegt nicht gleich auf der Hand. Immer wenn solch eine Funktion aufgerufen wird, wird nicht durch der <em>IDispatch::Involke </em>ausgeführt, sondern auch ein Aufruf von <em>IDispatch::GetIDsOfNames</em>. Bei einem Out-Of-Process-Server kann dieser Roundtrip einiges an Performance kosten. Dabei ist es so einfach es besser zu machen.</p>
<p>Die Doku von <em><a href="http://msdn2.microsoft.com/en-us/library/ms221306(VS.85).aspx">IDispatch::GetIDsOfNames</a></em> sagt folgendes:  </p>
<blockquote><p>The member and parameter DISPIDs must remain constant for the lifetime of the object. This allows a client to obtain the DISPIDs once, and cache them for later use.</p></blockquote>
<p>Und wer den oben genannten <a href="http://support.microsoft.com/kb/247579/en-us">KB-Artikel</a> aufmerksam gelesen hat, der hat auch was von DISPID-Caching mitbekommen.</p>
<p>Ich benutze gerne die die Wrapper, die in der MFC automatisch erzeugt werden, wenn man einen <em>Type-Library</em> über den Class View importiert. Hier werden die Funktionen auch in eine nette kleine <em>COleDispatchDriver</em>-Klasse verpackt und man bekommt netterweise ein gutes Exception Handling den Fehlerfall geliefert. Leider werden hier aber auch wieder nur <em>DISPIDs </em>verwendet<em>.<br />
</em>Aber mit einem kleinen Trick, kann man diese Klassen genial einfach für <em>Late Binding </em>nutzen. Ich gehe wie folgt vor:</p>
<ul>
<li>Ich importiere die <em>Type-Library</em> (tlb) mit dem Visual Studio Class View.</li>
<li>D.h. ich habe jetzt alle Wrapper mit DISPIDs, Was ich eigentlich für Late Binding vermeiden will.</li>
<li>Jetzt passe ich einfach die einzelnen Wrapper Funktionen in der folgenden Art und Weise an, ich ersetze die DISPID durch eine statische Variable:</li>
</ul>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">&nbsp;
<span style="color: #0000ff;">void</span> CMyWrapper<span style="color: #008080;">::</span><span style="color: #007788;">DoSomething</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span>
  <span style="color: #0000ff;">static</span> CDispIdHolder dispid<span style="color: #008000;">&#40;</span>m_lpDispatch,L<span style="color: #FF0000;">&quot;DoSomething&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  InvokeHelper<span style="color: #008000;">&#40;</span>dispid, DISPATCH_METHOD, VT_EMPTY, <span style="color: #0000ff;">NULL</span>, <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<ul>
<li>Die kleine Klasse die ich hier verwende macht nun den Rest und besorgt die <em>DISPID</em> und cached sie damit weil die Variable statisch definiert ist:</li>
</ul>

<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
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">&nbsp;
<span style="color: #0000ff;">class</span> CDispIdHolder
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
 CDispIdHolder<span style="color: #008000;">&#40;</span>IDispatch <span style="color: #000040;">*</span>pDispatch,LPCOLESTR pName<span style="color: #008000;">&#41;</span>
  <span style="color: #008080;">:</span> m_dispid<span style="color: #008000;">&#40;</span>DISPID_UNKNOWN<span style="color: #008000;">&#41;</span>
  <span style="color: #008000;">&#123;</span>
   HRESULT hr <span style="color: #000080;">=</span> pDispatch<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>GetIDsOfNames<span style="color: #008000;">&#40;</span>
         IID_NULL,
         <span style="color: #000040;">&amp;</span><span style="color: #0000ff;">const_cast</span><span style="color: #000080;">&lt;</span>LPOLESTR<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>pName<span style="color: #008000;">&#41;</span>,
         <span style="color: #0000dd;">1</span>,
         LOCALE_SYSTEM_DEFAULT,
         <span style="color: #000040;">&amp;</span>m_dispid<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
   <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>FAILED<span style="color: #008000;">&#40;</span>hr<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
    AfxThrowOleException<span style="color: #008000;">&#40;</span>hr<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
  <span style="color: #008000;">&#125;</span>
  operator DISPID<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> m_dispid<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
 DISPID m_dispid<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Die Exception, die man verwendet ist natürlich Implementierungsfrage.</p>
<p> <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_exclaim.gif' alt=':!:' class='wp-smiley' />  Der Performance Gain ist zum Teil beträchtlich, besonders wnen bestimmte Funktionen sehr oft aufgerufen werden müssen!</p>
<p>Anmerkung (für alle die es ganz genau nehmen):<br />
Wenn man die Doku genau liest, heißt es natürlich hier, dass die Implementierung nur für die Lebenszeit des Objektes konstante <em>DISPIDs</em> garantiert. Wenn man allerdings bei Early Binding schon <em>DISPIDs </em>als konstant annimmt, ist meine Methode für Late Binding sicherlich vertretbar.</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/02/16/late-binding-und-schwache-performance-durch-getidsofnames/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Wie man sich mit CComDispatchDriver bzw. CComPtr&lt;IDispatch&gt;::InvokeN hereinlegen kann</title>
		<link>http://blog.m-ri.de/index.php/2008/02/02/wie-man-sich-mit-ccomdispatchdriver-bzw-ccomptrinvoken-hereinlegen-kann/</link>
		<comments>http://blog.m-ri.de/index.php/2008/02/02/wie-man-sich-mit-ccomdispatchdriver-bzw-ccomptrinvoken-hereinlegen-kann/#comments</comments>
		<pubDate>Sat, 02 Feb 2008 15:09:29 +0000</pubDate>
		<dc:creator>Martin Richter</dc:creator>
				<category><![CDATA[ATL]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[COM]]></category>

		<guid isPermaLink="false">http://blog.m-ri.de/index.php/2008/02/02/wie-man-sich-mit-ccomdispatchdriver-bzw-ccomptrinvoken-hereinlegen-kann/</guid>
		<description><![CDATA[Eigentlich müsste dieser Artikel eine weitere Überschrift bekommen: Wie fatal es ist, dass es keine vollständige ATL Dokumentation gibt! Einige werden CComDispatchDriver kennen. Seit den VS-200x Versionen ist diese Klasse nichts anderes als sie Spezialisierung CComPtr&#60;IDispatch&#62; Ich hatte vor, eine bestimmte .NET Komponente per late binding in ein C++ Programm zu integrieren. Kein Problem. CreateInstance, [...]]]></description>
			<content:encoded><![CDATA[<p>Eigentlich müsste dieser Artikel eine weitere Überschrift bekommen:<br />
<strong>Wie fatal es ist, dass es keine vollständige ATL Dokumentation gibt!</strong></p>
<p>Einige werden <em>CComDispatchDriver </em>kennen. Seit den VS-200x Versionen ist diese Klasse nichts anderes als sie Spezialisierung <em>CComPtr&lt;IDispatch&gt;</em></p>
<p>Ich hatte vor, eine bestimmte .NET Komponente per <em>late binding </em>in ein C++ Programm zu integrieren.<br />
Kein Problem. <em>CreateInstance</em>, hier ein <em>Invoke0</em>, dort ein <em>Invoke2 </em>und da noch ein <em>InvokeN </em> <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_surprised.gif' alt=':eek:' class='wp-smiley' />  &#8230; und hier geht auf einmal nichts mehr. Dokumentation in der MSDN: Fehlanzeige!</p>
<p>Bestandsaufnahme: Ich habe einen CComVariant Array aufgebaut und die entsprechenden Daten übergeben. Sieht alles richtig aus. Aber ich erhalte immer nur Fehler (immer <em>E_NOINTERFACE</em>).</p>
<ol>
<li>OK, nächster Schritt. Das ganze mal direkt mit dem entsprechenden Interface versuchen. Also <em>CComQIPtr</em> eingebaut und direkter Aufruf über die existierende duale Schnittstelle. Komisch, nun geht es.</li>
<li>Nun denn. Das ganze nun mal als Klasse mit dem Classview importiert und einen MFC Wrapper gebaut. Der verwendet ja auch <em>IDispatch. </em>Jetzt wird es mysteriös: Es geht auch!</li>
</ol>
<p>Dann debuggen wir mal den MFC Wrapper. Schrittweise gehe ich durch den Code im <em>COleDispatchDriver::InvokeHelperV </em>bis Zeile 223 und dort lese ich den folgenden Code und Kommentar:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;">pArg <span style="color: #000040;">+</span><span style="color: #000080;">=</span> dispparams.<span style="color: #007788;">cArgs</span> <span style="color: #000040;">-</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span> <span style="color: #666666;">// params go in opposite order</span></pre></div></div>

<p> <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_exclaim.gif' alt=':!:' class='wp-smiley' />  Aha! Hier liegt der Hase im Pfeffer. Ich hatte den <em>CComVariant </em>Array natürlich so aufgebaut, dass das erste Argument auch das erste Element im Array war. <em>InvokeN </em>will aber die selbe Reihenfolge wie <em>IDispatch::Invoke</em>, d.h. in umgekehrter Folge. Also beginnt der Array nun mit dem letzten Argument und endet mit dem ersten und siehe da: Es geht <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_exclaim.gif' alt=':!:' class='wp-smiley' /> </p>
<p>Schade, dass hier die ATL-Doku so lückenhaft ist. Das hätte mir hier, 2 Stunden Arbeit gespart.<br />
Ich hätte es auch schneller haben können, wenn ich mir aufmerksam die Implementierung von <em>CComPtr&lt;IDispatch&gt;::Invoke2</em> angesehen hätte (Man achte auf den Array varArgs):</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">inline</span> HRESULT CComPtr<span style="color: #000080;">&lt;</span>IDispatch<span style="color: #000080;">&gt;</span><span style="color: #008080;">::</span><span style="color: #007788;">Invoke2</span><span style="color: #008000;">&#40;</span>__in DISPID dispid, 
       __in VARIANT<span style="color: #000040;">*</span> pvarParam1, 
       __in VARIANT<span style="color: #000040;">*</span> pvarParam2, 
       __out_opt VARIANT<span style="color: #000040;">*</span> pvarRet<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">throw</span><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>pvarParam1 <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span> <span style="color: #000040;">||</span> pvarParam2 <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> 
   <span style="color: #0000ff;">return</span> E_INVALIDARG<span style="color: #008080;">;</span> 
 CComVariant varArgs<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">2</span><span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> <span style="color: #008000;">&#123;</span> <span style="color: #000040;">*</span>pvarParam2, <span style="color: #000040;">*</span>pvarParam1 <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span> 
 DISPPARAMS dispparams <span style="color: #000080;">=</span> <span style="color: #008000;">&#123;</span> <span style="color: #000040;">&amp;</span>varArgs<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#93;</span>, <span style="color: #0000ff;">NULL</span>, <span style="color: #0000dd;">2</span>, <span style="color: #0000dd;">0</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span> 
 <span style="color: #0000ff;">return</span> p<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Invoke<span style="color: #008000;">&#40;</span>dispid, IID_NULL, LOCALE_USER_DEFAULT, 
     DISPATCH_METHOD, <span style="color: #000040;">&amp;</span>dispparams, pvarRet, <span style="color: #0000ff;">NULL</span>, <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> 
<span style="color: #008000;">&#125;</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/02/02/wie-man-sich-mit-ccomdispatchdriver-bzw-ccomptrinvoken-hereinlegen-kann/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Produktvergleich der verschiedenen Visual Studio 2008 Editionen</title>
		<link>http://blog.m-ri.de/index.php/2008/02/01/produktvergleich-der-verschiedenen-visual-studio-2008-editionen/</link>
		<comments>http://blog.m-ri.de/index.php/2008/02/01/produktvergleich-der-verschiedenen-visual-studio-2008-editionen/#comments</comments>
		<pubDate>Fri, 01 Feb 2008 12:06:28 +0000</pubDate>
		<dc:creator>Martin Richter</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[VS 2008]]></category>
		<category><![CDATA[ATL]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[VS-2008]]></category>

		<guid isPermaLink="false">http://blog.m-ri.de/index.php/2008/02/01/produktvergleich-der-verschiedenen-visual-studio-2008-editionen/</guid>
		<description><![CDATA[In diesem Produktvergleich http://msdn2.microsoft.com/en-us/vstudio/products/cc149003.aspx kann man einfach herausfinden welche Komponenten mit den verschiedenen Visual Studio Editionen ausgeliefert werden. Die häufigste Frage lautet immer wieder in den Foren: Was benötige ich für eine Edition um ATL+MFC Programme zu schreiben? Antwort: Die Visual Studio 2008 Standard Edition! Die Express-Edition enthält weder ATL noch MFC. Copyright &#169; 2010 Martin [...]]]></description>
			<content:encoded><![CDATA[<p>In diesem Produktvergleich <a href="http://msdn2.microsoft.com/en-us/vstudio/products/cc149003.aspx">http://msdn2.microsoft.com/en-us/vstudio/products/cc149003.aspx</a> kann man einfach herausfinden welche Komponenten mit den verschiedenen <em>Visual Studio Editionen </em>ausgeliefert werden.</p>
<p>Die häufigste Frage lautet immer wieder in den Foren:<br />
Was benötige ich für eine Edition um ATL+MFC Programme zu schreiben?<br />
Antwort: Die Visual Studio 2008 Standard Edition! Die Express-Edition enthält weder ATL noch MFC.</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/02/01/produktvergleich-der-verschiedenen-visual-studio-2008-editionen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Die Cx2y Falle&#8230;</title>
		<link>http://blog.m-ri.de/index.php/2007/09/12/die-cx2y-falle/</link>
		<comments>http://blog.m-ri.de/index.php/2007/09/12/die-cx2y-falle/#comments</comments>
		<pubDate>Wed, 12 Sep 2007 18:55:39 +0000</pubDate>
		<dc:creator>Martin Richter</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[ATL]]></category>

		<guid isPermaLink="false">http://blog.m-ri.de/index.php/2007/09/12/die-cx2y-falle/</guid>
		<description><![CDATA[In einem Programm habe ich diese unscheinbare Schleife für eine spezielle Analyse im Debug-Mode eingebaut. for (POSITION pos= m_aBind.GetHeadPosition(); pos; ) {   S_BIND&#38; b= m_aBind.GetNext(pos);  TRACE(__FUNCTION__ &#8220;  %-32s %2d\n&#8221;,   CT2A(b.sName.GetString()),   b.GetStatus()); } Sieht auf den ersten Blick OK aus. Auf den zweiten Blick wundert einen evtl. die Nutzung von CT2A. Warum nehme ich [...]]]></description>
			<content:encoded><![CDATA[<p>In einem Programm habe ich diese unscheinbare Schleife für eine spezielle Analyse im Debug-Mode eingebaut.</p>
<p class="ccode">for (POSITION pos= m_aBind.GetHeadPosition(); pos; )<br />
{ <br />
 S_BIND&amp; b= m_aBind.GetNext(pos);<br />
 TRACE(__FUNCTION__ &#8220;  %-32s %2d\n&#8221;,<br />
  CT2A(b.sName.GetString()),<br />
  b.GetStatus());<br />
}</p>
<p>Sieht auf den ersten Blick OK aus.<br />
Auf den zweiten Blick wundert einen evtl. die Nutzung von <em>CT2A</em>. Warum nehme ich nicht einfach den Zeiger von GetString wie er ist? Es ist ja ein <em>PCTSTR</em>! Begründung:</p>
<ol>
<li>Das Projekt ist ein Unicode Projekt.<em> </em></li>
<li><em>CT2A</em> verwende ich hier, weil die <em>TRACE</em> Funktion in dieser Schreibweise nur MBCS Strings verwendet. D.h. <em>%s</em> erwartet einen Zeiger auf einen MBCS String.</li>
<li>Die <em>_T </em>Schreibweise für die Ausgabemaske ist hier nicht geeignet, weil ich gerne den Funktionsnamen auch mit ausgegeben hätte. Und <em>__FUNCTION__</em> ist nun mal eine normale String-Konstante, und kein <em>wchar_t</em>-String.</li>
<li><em>T2A</em> verwende ich nicht, weil dies in einer Schleife tödlich ist, weil der Stack immer weiter anwächst.</li>
</ol>
<p>OK! Soweit dazu, warum der Code aussieht wie er aussieht.</p>
<p> <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_exclaim.gif' alt=':!:' class='wp-smiley' />  Nur&#8230; es kommt nur Schrott dabei heraus!<br />
Die Ausgabe zeigt brav, den Text, den ich haben möchte, nur die Zahlenwerte stimmen in keiner Weise mit den Rückgabewerten von <em>GetStatus </em>überein! Warum? <img src='http://blog.m-ri.de/wp-includes/images/smilies/icon_question.gif' alt=':?:' class='wp-smiley' /> </p>
<p>Was ist passiert? Der Debugger gibt schnell Auskunft:<br />
<em>CT2W</em> erzeugt ein Objekt vom Typ <em>CW2AEX</em>!!! Dieses Objekt ist aber größer als ein <em>PCSTR</em> Zeiger. Dieses Objekt umfasst bei meinen Projekteinstellungen 4 Bytes für einen Zeiger plus einen <em>char</em>-Array der Größe 128. <em>TRACE</em> hätte aber gerne einen 4-Byte Zeiger auf dem Stack und danach für die Ausgabe einen Integer.<br />
Ausgegeben, werden also die 4 ersten Bytes des Puffers von <em>CW2AEX </em>und nicht die gewünschten numerischen Werte für <em>GetStatus</em>!</p>
<p>Das ist übrigens die selbe Falle in die man tritt, wenn man <em>CString</em> direkt ohne <em>CString::GetString</em> in <em>printf/TRACE</em> und Konsorten verwendet. Nur hat man hier das Glück, dass ein <em>CString </em>exakt 4 Bytes groß ist und genau aus einem Zeiger auf einen <em>PTSTR</em> besteht.</p>
<p>Wie macht man es richtig?<br />
Genau&#8230; man führt den entsprechenden cast ein. Der cast benutzt nun den cast-Operator der Klasse <em>CW2AEX,</em> und der liefert uns den Zeiger den wir wollten.</p>
<p class="ccode">for (POSITION pos= m_aBind.GetHeadPosition(); pos; )<br />
{<br />
 S_BIND&amp; b= m_aBind.GetNext(pos);<br />
 TRACE(__FUNCTION__ &#8221; %-32s %2d\n&#8221;,<br />
  <strong><u>static_cast&lt;PCSTR&gt;(</u></strong>CT2A(b.sName.GetString())<strong><u>)</u></strong>,<br />
  b.GetStatus());<br />
}</p>
<p>Amerkungen:</p>
<ul>
<li>Ich brauche wahrscheinlich nicht zu erwähnen, dass ähnliche Probleme mit <em>CA2W</em>, <em>CA2T </em>etc. auch auftauchen können.</li>
<li>An den meisten Stellen an denen, wir diese Konvertierungen, wie z.B. <em>CT2A </em>verwenden wird auch direkt ein <em>PCTSTR </em>erwartet, oder eben ein Zeiger auf den entsprechend konvertieren String. Dadurch wird implizit der Konvertierungs-Operator der Klasse aufgerufen und damit funktioniert ales wie es soll.</li>
<li>Auch wenn das Projekt ein MBCS Projekt gewesen wäre, hätte es die selben Probleme verursacht. Denn in diesem Fall wird aus <em>CT2A </em>eine Objekt der Klasse <em>CA2AEX</em>. Im Gegensatz dazu würde <em>T2A </em>einfach zu ener Noop.</li>
</ul>
<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/2007/09/12/die-cx2y-falle/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

