<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://jkhines.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">John Hines&amp;#39; Code Blog</title><subtitle type="html" /><id>http://jkhines.com/blogs/code/atom.aspx</id><link rel="alternate" type="text/html" href="http://jkhines.com/blogs/code/default.aspx" /><link rel="self" type="application/atom+xml" href="http://jkhines.com/blogs/code/atom.aspx" /><generator uri="http://communityserver.org" version="3.0.20510.895">Community Server</generator><updated>2007-12-15T21:59:00Z</updated><entry><title>VBScript Consumption of C# enum</title><link rel="alternate" type="text/html" href="http://jkhines.com/blogs/code/archive/2008/04/24/vbscript-consumption-of-c-enum.aspx" /><id>http://jkhines.com/blogs/code/archive/2008/04/24/vbscript-consumption-of-c-enum.aspx</id><published>2008-04-24T21:47:00Z</published><updated>2008-04-24T21:47:00Z</updated><content type="html">&lt;p&gt;I have no idea how to do this.&lt;/p&gt;&lt;img src="http://jkhines.com/aggbug.aspx?PostID=35" width="1" height="1"&gt;</content><author><name>jkhines</name><uri>http://jkhines.com/members/jkhines.aspx</uri></author></entry><entry><title>ASP.NET 2.0 Error Messages</title><link rel="alternate" type="text/html" href="http://jkhines.com/blogs/code/archive/2007/12/15/asp-net-2-0-error-messages.aspx" /><id>http://jkhines.com/blogs/code/archive/2007/12/15/asp-net-2-0-error-messages.aspx</id><published>2007-12-16T06:41:00Z</published><updated>2007-12-16T06:41:00Z</updated><content type="html">&lt;p&gt;&lt;strong&gt;December 22, 2005&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;I&amp;#39;m tackling my first migration of a web app from ASP.NET 1.1 to 2.0.&amp;nbsp;&amp;nbsp;The traditional&amp;nbsp;xcopy deployment works fine for 2.0 apps using&amp;nbsp;the&amp;nbsp;1.1-style ASPX files and DLL code-behind.&amp;nbsp; But I&amp;#39;m trying out&amp;nbsp;ASP.NET binary deployment mentioned in &lt;a href="http://pluralsight.com/blogs/fritz/"&gt;Fritz Onion&lt;/a&gt;&amp;#39;s excellent article titled “&lt;a href="http://msdn.microsoft.com/msdnmag/issues/06/01/ExtremeASPNET/default.aspx"&gt;Codebehind and Compilation in ASP.NET 2.0&lt;/a&gt;” in&amp;nbsp;the &lt;a href="http://msdn.microsoft.com/msdnmag/issues/06/01/default.aspx"&gt;January edition&lt;/a&gt; of &lt;a href="http://msdn.microsoft.com/msdnmag/"&gt;MSDN magazine&lt;/a&gt;.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;After converting my ASP.NET&amp;nbsp;1.1 web app using Visual Studio 2005, I chose “Build-&amp;gt;Publish Web Site” on my development system and then xcopy (ftp, actually)&amp;nbsp;deployed it to a remote system.&amp;nbsp; Browsing to the remote URL resulted in the following errors:&lt;/div&gt;&lt;br /&gt;
&lt;hr /&gt;

&lt;div&gt;Error 1 : Parse Error Message: “&lt;strong&gt;It is an error to use a section registered as allowDefinition=&amp;#39;MachineToApplication&amp;#39; beyond application level. This error can be caused by a virtual directory not being configured as an application in IIS.&lt;/strong&gt;”&lt;br /&gt;&lt;br /&gt;Solution 1: Yep, you guessed it: ensure that the remote directory is enabled as an ASP.NET application in IIS.&amp;nbsp; If it already is, check that no subdirectory has a web.config with root-level settings in it.&amp;nbsp; I had this happen when I had nested applications - the solution is to compile the applications&amp;nbsp;independently and nest them at deploy time.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;hr /&gt;

&lt;div&gt;Error 2: Parse Error Message: “&lt;strong&gt;Unrecognized configuration section &amp;#39;xhtmlConformance&amp;#39;&lt;/strong&gt;”&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Solution 2: Ensure the remote directory is enabled as an ASP.NET 2.0 application.&amp;nbsp; The .NET version can be set under the ASP.NET tab in IIS.&amp;nbsp; If you don&amp;#39;t have an ASP.NET tab in your IIS admin MMC, you&amp;#39;re in a different problem space.&amp;nbsp; I had to request that my ISP enable this for me.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;hr /&gt;

&lt;div&gt;Error 3: Browsing to default.aspx displays “&lt;strong&gt;This is a marker file generated by the precompilation tool, and should not be deleted!&lt;/strong&gt;“&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Solution 3: Ensure you&amp;#39;ve uploaded the file PrecompiledApp.config into the root directory of your web application and that its contents look something like &amp;quot;PRECOMPILEDAPP updatable=&amp;quot;false&amp;quot; version=&amp;quot;2&amp;quot;&amp;quot;.&amp;nbsp; Otherwise ASP.NET will assume you&amp;#39;re using the old 1.1-style presentation/code-behind model and display the content of the ASPX marker files. 
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;hr /&gt;

&lt;div&gt;Error 4: Server Error; Exception Details: “&lt;strong&gt;System.Web.HttpException: The file &amp;#39;/VirtualPath/default.aspx&amp;#39; has not been pre-compiled, and cannot be requested.&lt;/strong&gt;”&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Solution 4: Ensure you&amp;#39;ve uploaded all of the *.config files in the bin directory along with all of your DLLs.. 
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;hr /&gt;

&lt;div&gt;Error 5: Applications beneath the root virtual directory break.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Solution 5: This is one I&amp;#39;m still working on.&amp;nbsp; Both / (the website root) and /code (this blog) are application-enabled.&amp;nbsp; Uploading the 2.0 version of the web.config for the root domain breaks all sub-applications.&amp;nbsp; I thought this blog would be isolated from its parent, but that&amp;#39;s obviously not the case.&amp;nbsp; I&amp;#39;ll have to fiddle with it some more.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;hr /&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;Steps 1 - 4 eventually did get me a working, binary deployed ASP.NET 2.0 application, but any web applications underneath the root virtual directory stopped working.&amp;nbsp; Until I fix that, it&amp;#39;s my hope that some of these error messages might help someone else in need.&amp;nbsp; Good luck!&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://jkhines.com/aggbug.aspx?PostID=16" width="1" height="1"&gt;</content><author><name>jkhines</name><uri>http://jkhines.com/members/jkhines.aspx</uri></author><category term="coding" scheme="http://jkhines.com/blogs/code/archive/tags/coding/default.aspx" /></entry><entry><title>Visual Studio Debugging Tips</title><link rel="alternate" type="text/html" href="http://jkhines.com/blogs/code/archive/2007/12/15/visual-studio-debugging-tips.aspx" /><id>http://jkhines.com/blogs/code/archive/2007/12/15/visual-studio-debugging-tips.aspx</id><published>2007-12-16T06:40:00Z</published><updated>2007-12-16T06:40:00Z</updated><content type="html">&lt;p&gt;&lt;strong&gt;December 03, 2004&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Min Kwan Park of Microsoft has the best article on the web detailing how to &lt;a href="http://blogs.msdn.com/mkpark/articles/86872.aspx"&gt;fix Visual Studio debugging problems&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The only error I haven&amp;#39;t noticed on the page is due to having both .NET Framework 1.x and .NET Framework 2.x Beta installed on the same machine.&amp;nbsp; When Visual Studio creates a new ASP.NET web application, IIS will default to using the highest&amp;nbsp;version of .NET, which, of course, Visual Studio is not expecting.&lt;/p&gt;
&lt;p&gt;When you attempt to launch the debugger in this situation, you&amp;#39;ll get a “Microsoft Development Environment” messagebox that simply says “&lt;strong&gt;Error while trying to run project.&lt;/strong&gt;”&lt;/p&gt;
&lt;p&gt;The solution is to force IIS to use the proper version of .NET.&amp;nbsp; Go to Start-&amp;gt;All Programs-&amp;gt;Administrative Tools-&amp;gt;Internet Information Services Manager.&amp;nbsp; Browse to your web application, right-click it, and select Properties.&amp;nbsp; Under the ASP.NET tab, change the ASP.NET version to use the production version of the .NET framework.&lt;/p&gt;&lt;img src="http://jkhines.com/aggbug.aspx?PostID=15" width="1" height="1"&gt;</content><author><name>jkhines</name><uri>http://jkhines.com/members/jkhines.aspx</uri></author><category term="coding" scheme="http://jkhines.com/blogs/code/archive/tags/coding/default.aspx" /></entry><entry><title>ASP.NET HTTPException Timeout</title><link rel="alternate" type="text/html" href="http://jkhines.com/blogs/code/archive/2007/12/15/asp-net-httpexception-timeout.aspx" /><id>http://jkhines.com/blogs/code/archive/2007/12/15/asp-net-httpexception-timeout.aspx</id><published>2007-12-16T06:38:00Z</published><updated>2007-12-16T06:38:00Z</updated><content type="html">&lt;p&gt;&lt;strong&gt;December 03, 2004&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yesterday I had an ASP.NET web application which would fail after a few minutes with one of two errors:&lt;br /&gt;a)&amp;nbsp;An ASP.NET error message saying: “System.Web.&lt;span class="highlight1"&gt;HttpException&lt;/span&gt;: &lt;strong&gt;&lt;span class="highlight2"&gt;Request&lt;/span&gt; &lt;span class="highlight3"&gt;timed&lt;/span&gt; out&lt;/strong&gt;”. (There was no stack trace information given, and it would fail at different points in the code).&lt;br /&gt;b) An IE client error that said “Server Not Found” as if I&amp;#39;d typed in a bad URL.&lt;/p&gt;
&lt;p&gt;Turns out they were both related to the fact that the default ASP.NET script execution &lt;a href="http://www.dotnet247.com/247reference/msgs/58/291378.aspx"&gt;stops after 90 seconds&lt;/a&gt;&amp;nbsp;by default.&amp;nbsp; ASP.NET ignores the script timeout settings for ASP set via IIS, and looks at the machine.config and web.config instead.&lt;/p&gt;
&lt;p&gt;I mistakenly assumed the ASP settings would roll over.&amp;nbsp; Once I added the following web.config entry to &lt;a href="http://www.dotnet247.com/247reference/msgs/43/216582.aspx"&gt;increase&amp;nbsp;ASP.NET execution time&lt;/a&gt; to 15 minutes, things started to work:&lt;br /&gt;&amp;lt;HTTPRUNTIME executionTimeout=&amp;quot;900&amp;quot;&amp;gt;&lt;/p&gt;&lt;img src="http://jkhines.com/aggbug.aspx?PostID=14" width="1" height="1"&gt;</content><author><name>jkhines</name><uri>http://jkhines.com/members/jkhines.aspx</uri></author><category term="coding" scheme="http://jkhines.com/blogs/code/archive/tags/coding/default.aspx" /></entry><entry><title>Using RootDSE</title><link rel="alternate" type="text/html" href="http://jkhines.com/blogs/code/archive/2007/12/15/using-rootdse.aspx" /><id>http://jkhines.com/blogs/code/archive/2007/12/15/using-rootdse.aspx</id><published>2007-12-16T06:36:00Z</published><updated>2007-12-16T06:36:00Z</updated><content type="html">&lt;p&gt;&lt;strong&gt;November 24, 2004&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I used to think that RootDSE was pretty magical. It would work on ASP pages without any kind of authentication and let me know which domain I was in. Which is true. Sort of. &lt;/p&gt;
&lt;p&gt;When writing ASP pages that users from multiple Active Directory domains would see, I would use code like this: &lt;/p&gt;
&lt;blockquote&gt;Set rootDSE = GetObject(&amp;quot;LDAP://SERVERNAME/RootDSE&amp;quot;)&lt;br /&gt;Response.Write rootDSE.Get(&amp;quot;defaultNamingContext&amp;quot;) &lt;/blockquote&gt;
&lt;p&gt;The output would look something like:&lt;br /&gt;DC=MyDomain,DC=com &lt;/p&gt;
&lt;p&gt;The first thing you need to know is that the domain displayed (MyDomain) has nothing to do with the user looking at the ASP page. It&amp;#39;s the domain that SERVERNAME lives in. If you point the GetObject() call at a different server in a different domain, your defaultNamingContext will change. &lt;/p&gt;
&lt;p&gt;The second, and arguably more important, thing to note is that getting output from rootDSE doesn&amp;#39;t mean that you can start reading from MyDomain. rootDSE will work on ASP pages using Anonymous authentication and running as IUSR_MyServer, but GetObject() calls on users in the domain will fail if your Active Directory doesn&amp;#39;t allow anonymous reads. You&amp;#39;ll either need to supply credentials via the objADsNamespeace.OpenDSObject() function or configure IIS to run as a domain user. &lt;/p&gt;
&lt;p&gt;Yep, the well-known &amp;quot;double hop&amp;quot; issue. Although opening up anonymous read access to Active Directory opens up all kinds of security holes, it does make coding easier. Which do you think is more important? &lt;/p&gt;&lt;img src="http://jkhines.com/aggbug.aspx?PostID=13" width="1" height="1"&gt;</content><author><name>jkhines</name><uri>http://jkhines.com/members/jkhines.aspx</uri></author><category term="coding" scheme="http://jkhines.com/blogs/code/archive/tags/coding/default.aspx" /></entry><entry><title>Query AD for telephoneNumber in VBScript</title><link rel="alternate" type="text/html" href="http://jkhines.com/blogs/code/archive/2007/12/15/query-ad-for-telephonenumber-in-vbscript.aspx" /><id>http://jkhines.com/blogs/code/archive/2007/12/15/query-ad-for-telephonenumber-in-vbscript.aspx</id><published>2007-12-16T06:35:00Z</published><updated>2007-12-16T06:35:00Z</updated><content type="html">&lt;p&gt;&lt;strong&gt;October 13, 2004&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;OK -- I couldn&amp;#39;t resist this one. I noticed a Google search hitting my page for the title topic. Since nobody ever leaves feedback, there&amp;#39;s no way to know if any of the info here answers the question. So here you go.&lt;/p&gt;
&lt;p&gt;In general, VBS makes it a piece of cake to retrieve information from users, groups, and computers. But actually finding the path (ADsPath) to the object is the hard part. 
&lt;p&gt;So to find the ADsPath, you&amp;#39;ll want to query the global catalog of your forest for the account name (sAMAccountName). You&amp;#39;ll also want to change the pertinant info to match your domain.&lt;/p&gt;
&lt;blockquote&gt;01: Dim objConn&lt;br /&gt;02: Dim objRS&lt;br /&gt;03: Dim objUser&lt;br /&gt;04: Dim strUsername&lt;br /&gt;05: Dim strTelephoneNumber&lt;br /&gt;06: &amp;nbsp;&lt;br /&gt;07: strUsername = &amp;quot;jkhines&amp;quot;&lt;br /&gt;08: &amp;nbsp;&lt;br /&gt;09: Set objConn = CreateObject(&amp;quot;ADODB.Connection&amp;quot;)&lt;br /&gt;10: objConn.Provider = &amp;quot;ADsDSOObject&amp;quot;&lt;br /&gt;11: objConn.Open&lt;br /&gt;12: &amp;nbsp;&lt;br /&gt;13: Set objRS = objConn.Execute(&amp;quot;;&amp;quot; &amp;amp;_&lt;br /&gt;14: &amp;nbsp;&amp;nbsp;&amp;quot;((objectCategory=person)(sAMAccountName=&amp;quot; &amp;amp; strUsername &amp;amp; &amp;quot;));&amp;quot; &amp;amp;_&lt;br /&gt;15: &amp;nbsp;&amp;nbsp;&amp;quot;adsPath;Subtree&amp;quot;)&lt;br /&gt;16: &amp;nbsp;&lt;br /&gt;17: Set objUser = GetObject(objRS(&amp;quot;adsPath&amp;quot;)) &amp;#39; or objRS.Fields(0) - same thing&lt;br /&gt;18: strTelephoneNumber = oUser.telephoneNumber&lt;br /&gt;19: &amp;nbsp;&lt;br /&gt;20: Set objUser = Nothing&lt;br /&gt;21: Set objRS = Nothing&lt;br /&gt;22: Set objConn = Nothing&lt;br /&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you already know the ADsPath to the object (that&amp;#39;s the path in the form of LDAP://CN=Hines\, John,OU=Users,DC=MyDomain,DC=com) then you simply start at line 17. Lucky you.&lt;/p&gt;
&lt;p&gt;In order to find what user attributes exit, use adsiedit. Personally, I use an arcane program called adsvw.exe.&lt;/p&gt;&lt;img src="http://jkhines.com/aggbug.aspx?PostID=12" width="1" height="1"&gt;</content><author><name>jkhines</name><uri>http://jkhines.com/members/jkhines.aspx</uri></author><category term="coding" scheme="http://jkhines.com/blogs/code/archive/tags/coding/default.aspx" /></entry><entry><title>Variant Conversion Functions</title><link rel="alternate" type="text/html" href="http://jkhines.com/blogs/code/archive/2007/12/15/variant-conversion-functions.aspx" /><id>http://jkhines.com/blogs/code/archive/2007/12/15/variant-conversion-functions.aspx</id><published>2007-12-16T06:34:00Z</published><updated>2007-12-16T06:34:00Z</updated><content type="html">&lt;p&gt;&lt;strong&gt;August 17, 2004&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I was converting binary SIDs to hex SIDs in VBScript for the millionth time when I stumbled across this ancient Microsoft article concerning &lt;a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;Q250344"&gt;Variant Conversion Functions (Q250344)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The COM component lets me skip doing this in VBS, which is extremely slow. It also has quite a few other functions for converting VBS&amp;#39;s ubiquitous Variant type to other useful forms.&lt;/p&gt;
&lt;p&gt;The Microsoft code snippet is pretty simple, even if the component&amp;#39;s method name isn&amp;#39;t:&lt;br /&gt;&lt;/p&gt;
&lt;blockquote&gt;Set objGroup = GetObject(&amp;quot;LDAP://MyAdsPath&amp;quot;)&lt;br /&gt;objGroup.GetInfoEx Array(&amp;quot;tokengroups&amp;quot;), 0&lt;br /&gt;objSids = objGroup.Get(&amp;quot;tokengroups&amp;quot;)&lt;br /&gt;&lt;br /&gt;Set oConvert = CreateObject(&amp;quot;ADs.ArrayConvert&amp;quot;)&lt;br /&gt;For Each objSid in objSids&lt;br /&gt;&amp;nbsp;&amp;nbsp;strHexSid = oConvert.CvOctetStr2vHexStr(objSid)&lt;br /&gt;&amp;nbsp;&amp;nbsp;set objParentGroup = GetObject(&amp;quot;LDAP://&lt;/blockquote&gt;&lt;img src="http://jkhines.com/aggbug.aspx?PostID=11" width="1" height="1"&gt;</content><author><name>jkhines</name><uri>http://jkhines.com/members/jkhines.aspx</uri></author><category term="coding" scheme="http://jkhines.com/blogs/code/archive/tags/coding/default.aspx" /></entry><entry><title>Access DFS from .NET posted</title><link rel="alternate" type="text/html" href="http://jkhines.com/blogs/code/archive/2007/12/15/access-dfs-from-net-posted.aspx" /><id>http://jkhines.com/blogs/code/archive/2007/12/15/access-dfs-from-net-posted.aspx</id><published>2007-12-16T06:31:00Z</published><updated>2007-12-16T06:31:00Z</updated><content type="html">&lt;p&gt;&lt;strong&gt;June 29, 2004 &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;[UPDATE 09 Feb 2005: I added the sample code from this post to the &lt;a href="http://www.pinvoke.net/default.aspx/netapi32.NetDfsAdd"&gt;NetDfsAdd definition&lt;/a&gt; at &lt;a href="http://www.pinvoke.net/"&gt;pinvoke.net&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;[UPDATE 29 Dec 2004: I added some C# code for utilizing NetDfsAdd at the end of this post]&lt;/p&gt;
&lt;p&gt;As an IT developer, I&amp;#39;m subject to the downtime schedule of my customers.&amp;nbsp; This means that I&amp;#39;m often informed (usually around holidays) of an upcoming change that will affect some of my many automation tasks.&amp;nbsp; This 4th of July is no exception.&lt;/p&gt;
&lt;p&gt;I have less than two days to modify, test, and deploy&amp;nbsp;four production scripts to account for&amp;nbsp;several important server changes&amp;nbsp;and a new dependency on Microsoft&amp;#39;s &lt;a href="http://www.microsoft.com/windows2000/techinfo/howitworks/fileandprint/dfsnew.asp"&gt;Distributed File System&lt;/a&gt; (DFS).&amp;nbsp; My biggest challenge is taking legacy VBScript code and adding the ability to create DFS links.&amp;nbsp;&amp;nbsp;The issue with using VBScript&amp;nbsp;is that there&amp;#39;s no &lt;a href="http://pinvoke.net/"&gt;p/invoke&lt;/a&gt; ability to use the &lt;a href="http://gethelp.devx.com/techtips/nt_pro/10_minute_solutions/10minNT0501-3.asp"&gt;DFS APIs&lt;/a&gt; in netapi32.dll, and no native&amp;nbsp;COM wrapper for DFS.&amp;nbsp; I can&amp;#39;t wrap netapi32 myself due to a dispersed install base, hatred of COM,&amp;nbsp;and lack of time.&lt;/p&gt;
&lt;p&gt;I&amp;#39;m resigned to shelling out (via the &lt;a href="http://msdn.microsoft.com/library/en-us/script56/html/wserrwhatsnew.asp"&gt;Exec method in WSH 5.6&lt;/a&gt;) to &lt;a href="http://www.microsoft.com/resources/documentation/WindowsServ/2003/standard/proddocs/en-us/dfscmd.asp"&gt;dfscmd.exe&lt;/a&gt;.&amp;nbsp; While it&amp;#39;s frustrating to not have the time to dig a bit deeper, the legacy scripts&amp;nbsp;must get moved over quickly and&amp;nbsp;continue to work reliably over time.&lt;/p&gt;
&lt;p&gt;How would I like to see it done?&amp;nbsp; I&amp;#39;d like to write an XML Web Service in C# that would &lt;a href="http://www.pinvoke.net/default.aspx/netapi32.NetDfsAdd"&gt;p/invoke NetDfsAdd&lt;/a&gt; to create the link.&amp;nbsp; I&amp;#39;d&amp;nbsp;configure&amp;nbsp;&lt;a href="http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetHT05.asp"&gt;Kerberos delegation&lt;/a&gt;&amp;nbsp;and enable impersonation so that anyone in the enterprise who already has native&amp;nbsp;permissions would be able to use the web service from any OS.&amp;nbsp; I&amp;#39;d add MS SQL logging of all transactions, including errors, so that I could track usage and trend success rate over time.&amp;nbsp; And I&amp;#39;d do this for every little task like this until I don&amp;#39;t have to write code anymore.&lt;/p&gt;
&lt;p&gt;Here is some C# code which might work if you wish to call NetDfsAdd from .NET: 
&lt;blockquote&gt;[DllImport(&amp;quot;Netapi32.dll&amp;quot;, CharSet=CharSet.Auto, SetLastError=true)]&lt;br /&gt;static extern int NetDfsAdd(&lt;br /&gt;&amp;nbsp;[MarshalAs(UnmanagedType.LPWStr)]&lt;br /&gt;&amp;nbsp;string DfsEntryPath,&lt;br /&gt;&amp;nbsp;[MarshalAs(UnmanagedType.LPWStr)]&lt;br /&gt;&amp;nbsp;string ServerName,&lt;br /&gt;&amp;nbsp;[MarshalAs(UnmanagedType.LPWStr)]&lt;br /&gt;&amp;nbsp;string PathName,&lt;br /&gt;&amp;nbsp;[MarshalAs(UnmanagedType.LPWStr)]&lt;br /&gt;&amp;nbsp;string Comment,&lt;br /&gt;&amp;nbsp;int Flags);&lt;br /&gt;&amp;nbsp;&lt;br /&gt;void TestMethod(void) {&lt;br /&gt;&amp;nbsp;// DFS_ADD_VOLUME has a value of 1&lt;br /&gt;&amp;nbsp;NetDfsAdd(&amp;quot;\\DfsRoot\Path\Dir&amp;quot;, &amp;quot;FileServer&amp;quot;, &amp;quot;Share&amp;quot;, &amp;quot;Comment&amp;quot;, 1);&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;&lt;img src="http://jkhines.com/aggbug.aspx?PostID=10" width="1" height="1"&gt;</content><author><name>jkhines</name><uri>http://jkhines.com/members/jkhines.aspx</uri></author><category term="coding" scheme="http://jkhines.com/blogs/code/archive/tags/coding/default.aspx" /></entry><entry><title>Good Web Design</title><link rel="alternate" type="text/html" href="http://jkhines.com/blogs/code/archive/2007/12/15/good-web-design.aspx" /><id>http://jkhines.com/blogs/code/archive/2007/12/15/good-web-design.aspx</id><published>2007-12-16T06:30:00Z</published><updated>2007-12-16T06:30:00Z</updated><content type="html">&lt;p&gt;&lt;strong&gt;May 10, 2004&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ask some ASP/ASP.NET web developers what constitutes good web design and how to judge it, and you&amp;#39;ll likely receive as many answers (or more) than the people you question.&amp;nbsp; For me, the answer is simple:&lt;br /&gt;When good design goes into a web app, useful functionality and good markup come out.&lt;/p&gt;
&lt;p&gt;“Useful functionality” is in the eye of the beholder.&amp;nbsp; And since it&amp;#39;s subjective it&amp;#39;s difficult to measure.&lt;/p&gt;
&lt;p&gt;Thankfully, good markup is easy to measure.&amp;nbsp; After all the times I&amp;#39;ve done a View-&amp;gt;Source only to be scared witless by chaotic lines of open-ended markup, I wish Microsoft would bake-in the &lt;a href="http://validator.w3.org/"&gt;W3C Markup Validation Service&lt;/a&gt;&amp;nbsp;into every single one of its web-enabled tools.&amp;nbsp; Now that Visual Studio is hardwiring CSS into ASP.NET web apps, the &lt;a href="http://jigsaw.w3.org/css-validator/"&gt;W3C CSS Validation Service&lt;/a&gt;&amp;nbsp;would be another welcome addition.&lt;/p&gt;
&lt;p&gt;In the meantime, you can manually validate your web app output using these tools.&lt;/p&gt;
&lt;p&gt;Lastly, if you&amp;#39;re interested in creating good web sites that look the same in all modern browsers (without hacks), I&amp;#39;d recommend &lt;a href="http://www.zeldman.com/"&gt;Jeffrey Zeldman&lt;/a&gt;&amp;#39;s book &lt;a href="http://www.zeldman.com/dwws/"&gt;&lt;em&gt;Designing with Web Standards&lt;/em&gt;&lt;/a&gt;.&amp;nbsp; And &lt;a href="http://www.stopdesign.com/"&gt;Douglas Bowman &lt;/a&gt;deserves a mention in this Microsoft-oriented blog for his &lt;a href="http://www.stopdesign.com/articles/throwing_tables/"&gt;guerilla re-write of Microsoft&amp;#39;s web site&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://jkhines.com/aggbug.aspx?PostID=9" width="1" height="1"&gt;</content><author><name>jkhines</name><uri>http://jkhines.com/members/jkhines.aspx</uri></author><category term="coding" scheme="http://jkhines.com/blogs/code/archive/tags/coding/default.aspx" /></entry><entry><title>Microsoft Certification for MCSD.Net</title><link rel="alternate" type="text/html" href="http://jkhines.com/blogs/code/archive/2007/12/15/microsoft-certification-for-mcsd-net.aspx" /><id>http://jkhines.com/blogs/code/archive/2007/12/15/microsoft-certification-for-mcsd-net.aspx</id><published>2007-12-16T06:12:00Z</published><updated>2007-12-16T06:12:00Z</updated><content type="html">&lt;p&gt;&lt;strong&gt;Microsoft Exam 70-315&lt;br /&gt;June 18, 2004&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#39;m glad to note that I passed &lt;a href="http://www.microsoft.com/learning/exams/70-315.asp"&gt;Microsoft certification exam 70-315&lt;/a&gt; today with a score of 824. Prometric gave out a score sheet after the exam with the total points and bar graphs that guage competency in areas like &amp;quot;Creating User Services&amp;quot; and &amp;quot;Consuming and Manipulating Data&amp;quot;. This was my first Microsoft exam.&lt;/p&gt;
&lt;p&gt;In order to prepare&amp;nbsp;for 70-315 I read the &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0735615845/qid=1087602928/sr=8-2/ref=sr_8_xs_ap_i2_xgl14/103-7375715-4087859?v=glance&amp;amp;s=books&amp;amp;n=507846"&gt;MS Press 70-315 study guide&lt;/a&gt;&amp;nbsp;for&amp;nbsp;a general overview of what MS wants you to know about ASP.NET.&amp;nbsp; To brush up, I bought the &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0789729016/qid=1087602811/sr=8-2/ref=pd_ka_2/103-7375715-4087859?v=glance&amp;amp;s=books&amp;amp;n=507846"&gt;Exam Cram 2 70-315 guide&lt;/a&gt; on a lark and&amp;nbsp;ended up scouring four chapters a day right up until the test. It&amp;#39;s far, far&amp;nbsp;superior to the MS book and its questions are in MS exam format. I wouldn&amp;#39;t have passed by reviewing the MS book alone. Preparing for the test with the MS book&amp;#39;s exam and the Exam Cram practice tests were a good combination.&amp;nbsp; By the time you take the test you should be scoring at least 90% on all of the practice tests.&lt;/p&gt;
&lt;p&gt;As far as the exam goes, it places a huge emphasis on ADO.NET. I think the Exam Cram book really nailed the key areas: Know all of the ADO.NET classes for SQL,&amp;nbsp;the right way to use them, and when to use the right one. Know how to invoke Transactions and work with XML.&amp;nbsp; Know the web.config and how to register controls.&amp;nbsp; And if you&amp;#39;re weak on any of the areas, simply build a test web app and work your way through it. As of last week, a lot of the broader areas, such as Custom Controls, Custom Events, and Globalization, were all completely new to me, so I&amp;#39;m pretty happy with the results.&lt;/p&gt;
&lt;p&gt;One nitpick: My testing machine was a museum piece whose monitor had a refresh rate of 60Hz.&amp;nbsp; At this rate, the monitor looks like it&amp;#39;s constantly flashing, and I thought I was going to be sick for the first half hour.&amp;nbsp; The staff at the test center said there was nothing they could do.&amp;nbsp; Doesn&amp;#39;t MS have some kind of minimum hardware spec for these systems?&lt;/p&gt;&lt;strong&gt;Problems with Prometric&lt;br /&gt;Saturday, August 14, 2004&lt;/strong&gt; 
&lt;p&gt;After a horrible testing experience yesterday, I felt I had to document some issues with &lt;a href="http://www.prometric.com/"&gt;Prometric&lt;/a&gt;, a vendor of Microsoft exams.&amp;nbsp; Hopefully other people can avoid these issues by avoiding Prometric.&lt;/p&gt;
&lt;p&gt;I used Prometric&amp;#39;s web site to schedule exam &lt;a href="http://www.microsoft.com/learning/exams/70-300.asp"&gt;70-300&lt;/a&gt;&amp;nbsp;for August 6th.&amp;nbsp; No problem.&amp;nbsp; On August 4th, I used Prometric&amp;#39;s web site to push the test out one week to August 13th.&amp;nbsp; Yep, Friday the 13th.&amp;nbsp; I should&amp;#39;ve known.&lt;/p&gt;
&lt;p&gt;I showed up at the testing center on the 13th&amp;nbsp;to the greeting: “You&amp;#39;re not on our schedule today.“&amp;nbsp; Apparently Prometric&amp;#39;s web application broke in the middle of the reschedule.&amp;nbsp; While Prometric&amp;#39;s web site showed that my test was rescheduled, the testing center was never notified.&amp;nbsp; In fact, they still had me down for the 6th listed as a “No Show”.&amp;nbsp; Even worse, the testing center was booked had no openings until the following week.&lt;/p&gt;
&lt;p&gt;To review: I scheduled the test.&amp;nbsp; I rescheduled it and got a confirmation email.&amp;nbsp; I studied a lot.&amp;nbsp; I took time off work and showed up early.&amp;nbsp; And I couldn&amp;#39;t take the test.&lt;/p&gt;
&lt;p&gt;So here&amp;#39;s what the testing center (&lt;a href="http://www.newhorizons.com/retail/English/learningCenters/centersearchresult.asp?SiteID=111"&gt;New Horizons&lt;/a&gt; in Beaverton, Oregon) did for me.&amp;nbsp; They called their helpdesk and changed their business hours so that it looked like they opened at 6am.&amp;nbsp; Then they scheduled me for the fake 6am slot and set up a computer for me to take the test.&amp;nbsp; After more wrangling with Prometric, they got Prometric to agree to reschedule me for 6am and download the 70-300 exam to the new computer.&lt;/p&gt;
&lt;p&gt;But the Prometric download wasn&amp;#39;t working.&lt;/p&gt;
&lt;p&gt;To review: I got an opening at the testing center.&amp;nbsp; I got a test machine to take the exam on.&amp;nbsp; And I couldn&amp;#39;t take the test.&lt;/p&gt;
&lt;p&gt;After an hour and 40 minutes of dealing with all of these issues, I left.&amp;nbsp; I certainly wasn&amp;#39;t in the frame of mind to take an exam.&amp;nbsp; I went home and dealt&amp;nbsp;with Prometric registration staff (again).&amp;nbsp; The conclusion?&amp;nbsp; They&amp;#39;ll call me back on Tuesday.&amp;nbsp; The only thing they were able to tell me for certain is&amp;nbsp;that the two “No Shows” (on for 8/6 and one for 8/13 at 6am) can be taken of my record.&lt;/p&gt;
&lt;p&gt;Advice for Prometric:&amp;nbsp;If you&amp;#39;re a company that sells exams on how to write web apps, you should hire people who take them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Microsoft Exam 70-300&lt;br /&gt;September 03, 2004&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I squeaked by &lt;a href="http://www.microsoft.com/learning/exams/70-300.asp"&gt;Microsoft Exam 70-300&lt;/a&gt; today with a score of 700 (with 700 required to pass). I absolutely would not have passed if I hadn&amp;#39;t found &lt;a href="http://dotnetjunkies.com/WebLog/jhaley/archive/2004/05/22/14245.aspx"&gt;this post&lt;/a&gt; by &lt;a href="http://dotnetjunkies.com/weblog/jhaley/"&gt;Jason Haley&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;I had heard that this exam was easy and that it could be passed with half a day of studying. I found the exam to be on the hard side, as there&amp;#39;s no hands-on technical work you can do to understand architecture. While experience helps, this is not an easy exam. &lt;/p&gt;
&lt;p&gt;I&amp;#39;ll focus on three things: studying for the exam, passing the &lt;a href="http://www.transcender.com/"&gt;Transcender&lt;/a&gt; practice exams, and taking the actual exam. &lt;/p&gt;
&lt;p&gt;&lt;b&gt;Studying for the exam&lt;/b&gt;&lt;br /&gt;I focused on the &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0789729296/qid=1094253237/sr=8-1/ref=pd_ka_1/103-6634533-4279836?v=glance&amp;amp;s=books&amp;amp;n=507846"&gt;Exam Cram 2 70-300 study guide&lt;/a&gt; and Chapter 1 of the &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0735618941/qid=1094253237/sr=8-4/ref=pd_ka_4/103-6634533-4279836?v=glance&amp;amp;s=books&amp;amp;n=507846"&gt;MS Press book&lt;/a&gt;. You have to drop all of your own architecture habits and use the information given in these books only. &lt;/p&gt;
&lt;p&gt;Take the Exam Cram 2 practice exams last but only as a knowledge guage. They are not in the same format as the real exam. Like Jason says, only use them as a guideline - if you get over a 900 on both Exam Cram 2 practice exams the first time you take them, schedule the real thing. Otherwise, get the Transcender product. &lt;/p&gt;
&lt;p&gt;&lt;b&gt;Passing the Transcender exams&lt;/b&gt;&lt;br /&gt;If you&amp;#39;re like me, you understand what it takes to get a product designed, built, and deployed. But if you&amp;#39;ve never taken a case study exam, this knowledge is essentially worthless. This is where the Transcender practice exams help immensely. Their format for reading a case study and navigating/answering questions is just like the real exam. &lt;/p&gt;
&lt;p&gt;&lt;b&gt;Warning&lt;/b&gt;: The Transcender exams consist of three case studies and a fixed set of questions. Once you take a case study, you&amp;#39;ve seen all of the questions. You can randomize the order, but you will never see new questions. This means you should save at least one case study until near your exam. Don&amp;#39;t run through all of the case studies and assume the questions will be replaced with new ones like the MS Press book exams. &lt;/p&gt;
&lt;p&gt;Once you&amp;#39;re easily passing the Transcender exams (including that one you saved for last) you&amp;#39;ll be ready for the real thing. Arm yourself with a good note-taking plan, confidence with case studies, and enhanced reading comprehension skills. &lt;/p&gt;
&lt;p&gt;&lt;b&gt;Taking the real exam&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Point one&lt;/b&gt;: Don&amp;#39;t use the number of questions as a guide for managing your time (plus my exam intro gave the wrong number of overall questions). Everything I&amp;#39;ve read and experienced indicates that there are three case study questions. Break down your 120 minutes accordingly, knowing that at least one case study is likely to be extremely complex. Know your own average times for taking notes and answering questions. &lt;/p&gt;
&lt;p&gt;&lt;b&gt;Point two&lt;/b&gt;: &lt;b&gt;WATCH THE CLOCK&lt;/b&gt;. I had some wierdness on my &amp;#39;remaining time&amp;#39; clock not adding up to two hours for all of the case studies. If I had to do it again, I would have ignored the in-program clock and allocated 40 minutes for each case study. The clock really was my enemy on this exam. &lt;/p&gt;
&lt;p&gt;&lt;b&gt;Point three&lt;/b&gt;: Be sure that you&amp;#39;re completely happy with each case study before you move on. Since I was too rushed for time, I ended all of my case studies thinking I could go back and review them. Once you click &amp;#39;Next&amp;#39; from the last question on the last case study, you&amp;#39;re done. I didn&amp;#39;t get a chance to review my last case study at all. &lt;/p&gt;
&lt;p&gt;&lt;b&gt;Point four&lt;/b&gt;: I feel that 70-300 is really about relationships. If you can read a case study and draw a detailed Entity Releationship Diagram, 60% of the remaining questions will be answered. I recommend getting the list of tables from the questions and laying them out as you read the case study. Then you can draw your ERD and answer questions about ORM, cardinality, query performance, and logic flow. &lt;/p&gt;
&lt;p&gt;My nervous rush to get through all of the case studies almost cost me a passing grade for this exam. If you&amp;#39;re methodical and treat it like another run through the practice exams, you&amp;#39;ll be just fine. == Don’t Use Prometric for Microsoft Exams posted @ Monday, April 18, 2005 1:19 PM &lt;/p&gt;
&lt;p&gt;Last Autumn I posted &amp;quot;Problems With Prometric&amp;quot; detailing some harrowing testing experiences I had with Thomson Prometric, a vendor of Microsoft certification exams.&amp;nbsp; The summary is that&amp;nbsp;Prometric screwed up my exam schedule so badly due to technical glitches that&amp;nbsp;Prometric eventually agreed to give me an exam for free.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Today I called Prometric&amp;#39;s customer service (1-800-775-3926, option 2) about my ticket, #1977354.&amp;nbsp; I&amp;#39;m ready to take my next exam (70-316), and wanted to schedule the free exam I was due.&amp;nbsp; Guess what?&amp;nbsp; After being on hold for 30 minutes, I was told that nothing in my ticket (owned by David) mentioned a free exam.&amp;nbsp; Prometric refused to give me the free exam that David had promised me verbally over the phone. 
&lt;p&gt;So let&amp;#39;s review my experiences with Prometric: Technical glitches that drop me off the schedule, break the reschedule, and break the download of the actual exam.&amp;nbsp; Hold times of 20 to 30 minutes for each and every call, and&amp;nbsp;TERRIBLE customer service.&amp;nbsp; And last but not least, not living up to their promises.&amp;nbsp; Studying for exams is hard enough without all of these distractions!&lt;/p&gt;
&lt;p&gt;You&amp;#39;re looking at a &lt;a href="http://www.vue.com/"&gt;Pearson Vue&lt;/a&gt; customer for life.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Microsoft Exam 70-316&lt;br /&gt;May 06, 2005&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;Today I passed &lt;a href="http://www.microsoft.com/learning/exams/70-316.asp"&gt;Microsoft Exam 70-316&lt;/a&gt; with a score of 940.&amp;nbsp; I have two exams left before I obtain &lt;a href="http://www.microsoft.com/mcsd/"&gt;MCSD&lt;/a&gt;&amp;nbsp;certification.&lt;/p&gt;
&lt;p&gt;It&amp;#39;s been eight months since my last exam and I had never jumped into the GUI world before.&amp;nbsp; So in that long period of time I really wanted to understand Windows Forms, and did a lot more than you need to do in order to pass the exam.&lt;br /&gt;1. I went through the &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0735619263/ref=pd_sim_b_2/002-0547567-3733623?%5Fencoding=UTF8&amp;amp;v=glance"&gt;MS Press 70-316 study guide&lt;/a&gt;&amp;nbsp;to get a feel for Microsoft&amp;#39;s emphasis.&amp;nbsp; It wasn&amp;#39;t very useful.&amp;nbsp; I found the practice test to be helpful in guaging my general knowledge, but I didn&amp;#39;t need to it to pass the exam.&lt;br /&gt;2. I went through Chris Sell&amp;#39;s &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0321116208/qid=1115401092/sr=8-1/ref=pd_csp_1/002-0547567-3733623?v=glance&amp;amp;s=books&amp;amp;n=507846"&gt;Windows Forms Programming in C#&lt;/a&gt;&amp;nbsp;while writing a complex, multithreaded Windows application.&amp;nbsp; The book&amp;nbsp;is an&amp;nbsp;introductory-level&amp;nbsp;overview of Windows Forms&amp;nbsp;and is&amp;nbsp;a good replacement for the &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/157231995X/qid=1115401225/sr=8-1/ref=pd_csp_1/002-0547567-3733623?v=glance&amp;amp;s=books&amp;amp;n=507846"&gt;Petzold&lt;/a&gt; or &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/1572316950/ref=pd_sim_b_2/002-0547567-3733623?%5Fencoding=UTF8&amp;amp;v=glance"&gt;Prosise&lt;/a&gt; books.&lt;br /&gt;3. I went through the &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0789729024/ref=pd_sim_b_2/002-0547567-3733623?%5Fencoding=UTF8&amp;amp;v=glance"&gt;Exam Cram 2 70-316 study guide&lt;/a&gt;.&amp;nbsp; Of the three Exam Cram books I&amp;#39;ve studied, this was the most pertinent and did the best job of pointing out my weak spots.&lt;br /&gt;4. Lastly, I took the best instructor-led class I&amp;#39;ve had, class &lt;a href="http://www.microsoft.com/learning/SYLLABI/2555AFINAL.ASP"&gt;2555A&lt;/a&gt; led by &lt;a href="http://www.dotnetdevs.com/articles/IsolatedStorage.aspx"&gt;Chris Tavares&lt;/a&gt;.&amp;nbsp; Chris answered all the questions I had from Sells&amp;#39; book and more.&amp;nbsp; I&amp;#39;ve taken loads of training before, and I&amp;#39;m still telling people about&amp;nbsp;how great Chris&amp;#39; class was.&lt;/p&gt;
&lt;p&gt;As for the exam itself, well, my version was&amp;nbsp;really, really&amp;nbsp;&lt;em&gt;easy&lt;/em&gt;&lt;em&gt;.&lt;/em&gt;&amp;nbsp; I can&amp;#39;t really detail what &lt;em&gt;wasn&amp;#39;t&lt;/em&gt; on the exam for giving away what it contains.&amp;nbsp; But just getting a simple multithreaded Windows application working with help, validation, and configuration covered much more than this exam.&amp;nbsp; By emphasizing ADO.NET so prominently, Microsoft are omitting many other important areas of programming.&amp;nbsp; I could have passed this exam with just a basic understanding of the technology.&lt;/p&gt;
&lt;p&gt;If you want to get through the exam, just review the Sells and Exam Cram books.&amp;nbsp; Personally, I&amp;#39;d like to follow the above pattern for all of the MCSD exams, but I don&amp;#39;t have 40 months of my life to dedicate to it.&amp;nbsp; I&amp;#39;m hoping to punch out Web Services and my elective as fast as possible and move on.&amp;nbsp; Especially now that I understand that MCSD really means you&amp;#39;ve been introduced to the technology, and aren&amp;#39;t necessarily a master of it.&lt;/p&gt;&lt;strong&gt;Microsoft Exam 70-320&lt;br /&gt;August 12, 2005&lt;/strong&gt; 
&lt;p&gt;Today I passed &lt;a href="http://www.microsoft.com/learning/exams/70-320.asp"&gt;Microsoft Exam 70-320&lt;/a&gt; with a score of 952.&amp;nbsp; I have one elective exam until the &lt;a href="http://www.microsoft.com/mcsd/"&gt;MCSD&lt;/a&gt;&amp;nbsp;certification is mine.&lt;/p&gt;
&lt;p&gt;I have to start by saying I was suprised to score so highly. Although I&amp;#39;ve been using Web Services in production since early 2003, I hadn&amp;#39;t done much with the server components that are also on the exam. I felt I was weak on the COM+ features implemented by serviced components. The epiphany I had while preparing this time was &amp;quot;&lt;i&gt;It doesn&amp;#39;t matter whether the textbook answer is right if you&amp;#39;re wrong&lt;/i&gt;.&amp;quot; In other words, the best approach to Microsoft exams is to first eliminate wrong answers, regardless of the question.&lt;/p&gt;
&lt;p&gt;To prepare, I went through &lt;a href="http://www.keithba.net/blog/2003_03_01_archive.htm#91631074"&gt;Keith Ballinger&lt;/a&gt;&amp;#39;s book &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0321113594/qid=1123885947/sr=8-1/ref=pd_bbs_1/104-7030923-6088704?v=glance&amp;amp;s=books&amp;amp;n=507846"&gt;.NET Web Services&lt;/a&gt;. I thought it was too focused on internals the first time I went through it, and really enjoyed it as I reviewed it. My conclusion is that it&amp;#39;s a great book for anyone who&amp;#39;s going to write, deploy, and (most especially) debug web services. Just understand that it&amp;#39;s a single component of this exam. I then did three chapters a week of the &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0789728974/qid=1123886219/sr=2-1/ref=pd_bbs_b_2_1/104-7030923-6088704"&gt;Exam Cram 2 70-320 study guide&lt;/a&gt; and did a week of review.&lt;/p&gt;
&lt;p&gt;I powered through the practice tests, but was really worried for the first half of the real thing. I was weak on serviced components and their performance and deployment issues, and reviewed about 40% of the questions before I finished. I still have mixed emotions seeing so much database and XML focus on these exams, but seeing them for the third time helped my overall score. My web service experience really paid off. I don&amp;#39;t have the mastery of 70-320 that I had of 70-316, but knowing how to eliminate the wrong questions got me a higher score on this exam.&lt;/p&gt;
&lt;p&gt;If you want to get through the exam, just review the Exam Cram book. I&amp;#39;m full of so many opinions about the entire MCSD process, but I&amp;#39;m saving them for a single post on improving the process. So far my MCSD experience has been like taking five multiple choice tests on the grammar of French, Greek, Russian, German, and English. It&amp;#39;s a good overview and a great way to stay current, but you have to use it daily in order to be fluent.&lt;/p&gt;&lt;strong&gt;Microsoft Exam 70-229&lt;br /&gt;November 10, 2005&lt;/strong&gt; 
&lt;p&gt;Today I passed &lt;a href="http://www.microsoft.com/learning/exams/70-229.asp"&gt;Microsoft Exam 70-229&lt;/a&gt; with a score of 908. This ends my five exams for the MCSD.NET certification with an average score of 865.&lt;/p&gt;
&lt;p&gt;I started studying for this exam on October 3rd and took it on November 10th. To prepare, I did the bare minimum: I went through a chapter per day of the &lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/0789731061/qid=1131652756/sr=8-1/ref=pd_bbs_1/104-3976586-8834343?v=glance&amp;amp;s=books&amp;amp;n=507846"&gt;Exam Cram 2 70-229 study guide&lt;/a&gt;, got sick for two weeks, and did a week of book review and a week with the &lt;a href="http://www.transcender.com/"&gt;Transcender&lt;/a&gt; practice test.&lt;/p&gt;
&lt;p&gt;The Transcender exams are really what got me through 70-229. I felt that the Exam Cram 2 questions were too easy, and I was right. By reviewing the concepts behind the Transcender questions I was extremely well prepared to take the exam. For once I wasn&amp;#39;t frustrated at the amount of database information on an MCSD exam, I was just wondering why a software engineer would ever need to know when to use clustered or nonclustered indexes. Fortunately I&amp;#39;ve used MS-SQL for years and had taken 70-300, which is 80% database design. This really cut down on the amount of new material I had to review&lt;/p&gt;
&lt;p&gt;The exam itself was one of the more focused of the MCSD exams because it didn&amp;#39;t need to mix MS product recommendations with technical questions. I was surprised that I didn&amp;#39;t have a single question designing complex table relationships. However most of the questions are based on a good understanding of foreign keys, indexes, views, and constraints. The exam posed when the best time was to use each technology rather than doing a deep-dive into how each technology works.&lt;/p&gt;
&lt;p&gt;If you want to get through the exam, you need to be fluent in T-SQL and have experience with the Enterprise Tools. SQL Books Online is really the best reference out there. From there you can pick any study book and test out each concept as it&amp;#39;s introduced. I&amp;#39;m happy to say I&amp;#39;ll probably use some of this knowledge in the future, but not as a DBA.&lt;/p&gt;&lt;strong&gt;Thoughts on MCSD Certification&lt;br /&gt;November 10, 2005&lt;/strong&gt; 
&lt;p&gt;After more than a year of effort and two weeks after Microsoft announced a &lt;a href="http://www.microsoft.com/learning/mcp/newgen/"&gt;new Microsoft certification track&lt;/a&gt;, I passed the final exam required for my qualification as a &lt;a href="http://www.microsoft.com/learning/mcp/mcsd/"&gt;Microsoft Certified Solution Developer for Microsoft .NET&lt;/a&gt;. I wanted to consolidate many of the thoughts I&amp;#39;ve had through the entire process as advice for others who would have considered this certification. 
&lt;p&gt;It&amp;#39;s easy to pick where to begin - my biggest lesson was what MCSD.NET really means. I used to think that an MCSD would be an elite developer who could explain non-deterministic finalization to me, or how the CLR uses garbage collection statistics to help the OS determine a process&amp;#39; virtual memory size. This is not the case. MCSD means that the developer has been exposed to broad .NET concepts: the concept of how .NET works, how desktop, web, and distributed apps should work, and good ways to run a database or ensure security. If you want to be an expert in a particular part of .NET, it&amp;#39;s better to subscribe to the expert blogs, keep up on the trade journals, and dedicate time to actually writing code.&lt;/p&gt;
&lt;p&gt;This brings me to my second point - the certification so far too broad. I don&amp;#39;t feel like I&amp;#39;ve developed a depth of expertise in any specific technology, including basic language syntax. The features that make .NET apps cool are ignored or lightly touched on in the certification. Things like advanced IIS role-based security, desktop app multithreading techniques, cross-OS web service interoperability barely scratch the surface of my memory from the exams. ADO.NET is emphasized too much and tested too frequently. The core MCAD exams share 25% of their questions on ADO.NET alone. You won&amp;#39;t get specialized knowledge by getting certified. If you want to be a master of a small part of .NET, identify what that part is and learn everything you can about it.&lt;/p&gt;
&lt;p&gt;My last point has to do with the exams themselves. While it would be difficult to walk in off the street and pass an exam, they&amp;#39;re still too easy. If Microsoft wants to make the exams a challenge, multiple choice has got to go. There must be some real coding done on the exams. There should be more of a Computer Science emphasis than a &amp;quot;what product to use when&amp;quot; emphasis. Even on the multiple choice, a base level of knowledge means test takers can eliminate obviously incorrect answers to guess at the right solution. And lastly, the exams are mirrored too closely by the practice exams available. By the end of the track I&amp;#39;ve mastered how to take Microsoft certification exams as much as the material itself. Now I understand how some people pass five tests in a couple of months. Microsoft needs to do better to keep the exams relevant. Otherwise, what does a certification really mean?&lt;/p&gt;
&lt;p&gt;I&amp;#39;m going to end on a positive note. A year ago I had only touched the surface of .NET and felt like my programming skills were slipping into obsolesence. Getting certified motivated me to get a baseline understanding of .NET to the point where I&amp;#39;m a reference for friends. I&amp;#39;ve written web services, web apps, console apps, desktop apps, Windows services, stored procedures, user-defined functions, and remote objects. I&amp;#39;m starting to feel like a software engineer again. If you&amp;#39;re coming from nothing, certification is a great way to get up to speed on the minimum you need to know. Don&amp;#39;t be afraid to do it - there&amp;#39;s an entire industry out there to help you succeed. Once you&amp;#39;ve gotten your MCSD.NET or Enterprise MCPD, you&amp;#39;ll be ready to choose your favorite area and &lt;i&gt;really&lt;/i&gt; get to know what .NET is all about.&lt;/p&gt;
&lt;p&gt;Good luck!&lt;/p&gt;&lt;img src="http://jkhines.com/aggbug.aspx?PostID=8" width="1" height="1"&gt;</content><author><name>jkhines</name><uri>http://jkhines.com/members/jkhines.aspx</uri></author><category term="certification" scheme="http://jkhines.com/blogs/code/archive/tags/certification/default.aspx" /></entry><entry><title>Working with Windows Group Membership</title><link rel="alternate" type="text/html" href="http://jkhines.com/blogs/code/archive/2007/12/15/working-with-windows-group-membership.aspx" /><id>http://jkhines.com/blogs/code/archive/2007/12/15/working-with-windows-group-membership.aspx</id><published>2007-12-16T05:59:00Z</published><updated>2007-12-16T05:59:00Z</updated><content type="html">&lt;p&gt;&lt;strong&gt;May 06, 2004&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;[UPDATE 14 May 2004: If you plan on adding members to AD groups from .NET 1.0 or 1.1, be aware of the following bug: &lt;a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;818031"&gt;http://support.microsoft.com/default.aspx?scid=kb;en-us;818031&lt;/a&gt;]&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve had to determine user group membership in quite a different number of ways; local groups, domain groups, domain groups with nesting. Sometimes I&amp;#39;ve known what group I was looking for, sometimes not. Microsoft does provide code to do all of this -- the downside is that it can be extremely slow (like IADsGroup.IsMember in an Active Directory Domain). This is an attempt to list out my best known methods and great web resources for working with group membership.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Group Membership Scripts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First off, &lt;a href="http://hilltop%20lab/"&gt;Hilltop Lab&lt;/a&gt; has one of the most well presented sites on ADSI scripting for Windows NT 5.x environments I&amp;#39;ve found on the web. All of the code we care about is in the section labeled &lt;a href="http://group%20membership%20tests/"&gt;Group Membership Tests&lt;/a&gt;. The list there is more complete than anything I&amp;#39;ve found on the MS site.&lt;/p&gt;
&lt;p&gt;The only thing I&amp;#39;d add is that always enumerating the IADsUser.Groups attribute can be slow, especially in interpreted VBScript and also if the user is a member of many groups. I&amp;#39;ve found the fastest way to check for a single group membership is the following:&lt;br /&gt;
&lt;blockquote&gt;Dim oUser&lt;br /&gt;Dim strGroups&lt;br /&gt;oUser = GetObject(&amp;quot;LDAP://CN=Hines\, John,DC=MyDomain,DC=com&amp;quot;)&lt;br /&gt;strGroups = Join(oUser.memberOf)&lt;br /&gt;If (InStr(strGroups, &amp;quot;CN=MyGroup,&amp;quot;) &amp;lt;&amp;gt; 0) Then&lt;br /&gt;&amp;#39; user is a member! for me, this test is ~10x faster than enumeration&lt;br /&gt;End If&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you&amp;#39;re looking to display the groups later, you can Join( ) with any special character that&amp;#39;s invalid in a group ADsPath and then Replace( ) it with a vbCrLf.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Finding Nested Group Membership: VERY USEFUL&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The key to enumerating nested groups is the&amp;quot;tokenGroups&amp;quot;; attribute, which must be explicitly copied down from the domain once you&amp;#39;ve bound to the user object. Microsoft has an example of enumerating tokenGroups in VB Script in &lt;a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;Q301916"&gt;Q301916&lt;/a&gt; (http://support.microsoft.com/default.aspx?scid=kb;en-us;Q301916). I haven&amp;#39;t done any tests comparing the tokenGroups method to walking up the IADsGroup.managedBy tree, but it&amp;#39;s more intuitive and non-recursive.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Finding Group Membership in ASP.NET&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The fastest way to determine group membership in ASP.NET is through the user of the Security Principal objects.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;using System.Security.Principal; &lt;/p&gt;
&lt;p&gt;WindowsPrincipal user = (HttpContext.Current.User as WindowsPrincipal);&lt;br /&gt;if (user.IsInRole(@&amp;quot;MyDomain\MyGroup&amp;quot;)) {&lt;br /&gt;// user is a member!&lt;br /&gt;} &lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;If you&amp;#39;re curious about more ways to work with role-based security in ASP.NET, I&amp;#39;d recommend &lt;a href="http://www.4guysfromrolla.com/ASPscripts/PrintPage.asp?REF=/webtech/121901-1.2.shtml"&gt;Implementing Role-Based Security with ASP.NET&lt;/a&gt; and this advanced article about &lt;a href="http://www.codebetter.com/blogs/brendan.tompkins/archive/2004/03/16/9252.aspx"&gt;Scalable ASP.NET Expanded User Properties Model&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Finding the Groups a User can Manage&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Lastly, once you know what groups your user is in, you may then want to know what groups they have permission to manage. For direct management you&amp;#39;ll want to check the IADsUser.managedObjects property. For direct and inherited management it&amp;#39;s preferable to submit an ADO query and have the domain find out for you.&lt;/p&gt;
&lt;p&gt;The algorithm I use constructs an ADO query filter that essentially says “Return every group that is directly managed by my user or any group my user is a member of”. Be aware this misses things like permission settings on OUs, but it&amp;#39;s the best method I&amp;#39;ve found so far.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;using System;&lt;br /&gt;using System.Text;&lt;br /&gt;using System.DirectoryServices;&lt;br /&gt;using System.Collections; &lt;/p&gt;
&lt;p&gt;string username = &amp;quot;MyDomain\jkhines&amp;quot;;&lt;/p&gt;
&lt;p&gt;//&lt;br /&gt;// perform an AD search for the user object&lt;br /&gt;// assume username is set to MyDomain\MyUser&lt;br /&gt;//&lt;br /&gt;DirectorySearcher ds = new DirectorySearcher();&lt;br /&gt;ds.SearchRoot = new DirectoryEntry(&amp;quot;LDAP://DC=MyDomain,DC=com&amp;quot;);&lt;br /&gt;ds.SearchScope = SearchScope.Subtree;&lt;br /&gt;ds.Filter = String.Format(&amp;quot;(&amp;amp;(objectCategory=person)(sAMAccountName={0}))&amp;quot;,&lt;br /&gt;username.Split(&amp;#39;\\&amp;#39;)[1]);&lt;br /&gt;ds.PropertiesToLoad.Add(&amp;quot;adsPath&amp;quot;);&lt;br /&gt;SearchResult userSearch = ds.FindOne();&lt;br /&gt;string userAdsPath = userSearch.Properties[&amp;quot;adsPath&amp;quot;][0].ToString(); &lt;/p&gt;
&lt;p&gt;//&lt;br /&gt;// bind to the user object and get the tokenGroups&lt;br /&gt;//&lt;br /&gt;DirectoryEntry user = new DirectoryEntry(userAdsPath);&lt;br /&gt;user.RefreshCache(new String[] {&amp;quot;tokenGroups&amp;quot;}); &lt;/p&gt;
&lt;p&gt;//&lt;br /&gt;// start construction of a query filter of all the groups the user belongs to&lt;br /&gt;//&lt;br /&gt;StringBuilder filter = new StringBuilder();&lt;br /&gt;filter.AppendFormat(&amp;quot;(|(&amp;amp;(objectCategory=group)(managedBy={0}))&amp;quot;,&lt;br /&gt;user.Properties[&amp;quot;distinguishedName&amp;quot;][0]); &lt;/p&gt;
&lt;p&gt;DirectoryEntry group;&lt;br /&gt;byte[] currentSID;&lt;br /&gt;StringBuilder hexString = new StringBuilder();&lt;br /&gt;IEnumerator groupList = user.Properties[&amp;quot;tokenGroups&amp;quot;].GetEnumerator(); &lt;/p&gt;
&lt;p&gt;while (groupList.MoveNext()) {&lt;br /&gt;//&lt;br /&gt;// convert the byte[] SID to a friendly SID string&lt;br /&gt;//&lt;br /&gt;currentSID = (byte[])groupList.Current;&lt;br /&gt;foreach (byte inByte in currentSID) {&lt;br /&gt;hexString.AppendFormat(&amp;quot;{0:X2}&amp;quot;, inByte);&lt;br /&gt;} &lt;/p&gt;
&lt;p&gt;//&lt;br /&gt;// bind to the group to get the distinguishedName&lt;br /&gt;//&lt;br /&gt;try {&lt;br /&gt;group = new DirectoryEntry(String.Format(&amp;quot;LDAP://&amp;quot;,&lt;br /&gt;hexString.ToString())); &lt;/p&gt;
&lt;p&gt;filter.AppendFormat(&amp;quot;(&amp;amp;(objectCategory=group)(managedBy={0}))&amp;quot;,&lt;br /&gt;group.Properties[&amp;quot;distinguishedName&amp;quot;][0]);&lt;br /&gt;}&lt;br /&gt;catch(Exception err) {&lt;br /&gt;// ignore errors if this is a local group&lt;br /&gt;}&lt;br /&gt;hexString.Remove(0, hexString.Length);&lt;br /&gt;}&lt;br /&gt;filter.Append(&amp;quot;)&amp;quot;); &lt;/p&gt;
&lt;p&gt;//&lt;br /&gt;// set new searcher filter&lt;br /&gt;//&lt;br /&gt;ds.Filter = filter.ToString(); &lt;/p&gt;
&lt;p&gt;//&lt;br /&gt;// execute new query and display results&lt;br /&gt;//&lt;br /&gt;foreach(SearchResult groupSearch in ds.FindAll()) {&lt;br /&gt;// use groupSearch.Properties[&amp;quot;adsPath&amp;quot;][0];&lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Thursday, July 15, 2004 1:59 PM&lt;/strong&gt;&lt;br /&gt;
&lt;p&gt;Today I stumbled on posts by Joe Kaplan, an MVP for ADSI,&amp;nbsp;showing an unsupported but great method for listing&amp;nbsp;nested Windows group membership without requiring an enumeration through the tokengroups attribute.&lt;/p&gt;
&lt;p&gt;Visual Basic code can be found in the original articles &lt;a href="http://www.error-bank.com/microsoft.public.dotnet.security/7225_Thread.aspx"&gt;here&lt;/a&gt; and &lt;a href="http://www.dotnet247.com/247reference/msgs/33/166991.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Joe posts the following warning: “Do not use this in production code as reflecting on private members is NOT a good idea and the implementation may change in a future version of the Framework!”&amp;nbsp; Here&amp;#39;s&amp;nbsp;my stab at a &amp;nbsp;C# version of&amp;nbsp;Joe&amp;#39;s .NET Framework 1.0-1.1 code:&lt;/p&gt;
&lt;blockquote&gt;using System;&lt;br /&gt;using System.Reflection;&lt;br /&gt;using System.Security.Principal;&lt;br /&gt;&lt;br /&gt;class Class1 {&lt;br /&gt;&amp;nbsp;static void Main(string[] args) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;string[] roles = GetRoles(WindowsIdentity.GetCurrent());&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;foreach (string role in roles) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(role);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;static string[] GetRoles(WindowsIdentity identity) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;Type idType = identity.GetType();&lt;br /&gt;&amp;nbsp;&amp;nbsp;object result = idType.InvokeMember(&amp;quot;_GetRoles&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;BindingFlags.Static | BindingFlags.InvokeMethod | BindingFlags.NonPublic,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;null, identity, new object[] { identity.Token }, null);&lt;br /&gt;&amp;nbsp;&amp;nbsp;return (string[]) result;&lt;br /&gt;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;
&lt;p&gt;However I&amp;#39;m surprised that&amp;nbsp;MS didn&amp;#39;t publicly expose _GetRoles.&amp;nbsp; The supported method of enumerating through tokengroups SIDs requires binding to a Domain Controller in order to fetch&amp;nbsp;the friendly name, and it doesn&amp;#39;t cover custom roles.&amp;nbsp; Why not just make _GetRoles a public method?&lt;/p&gt;
&lt;p&gt;As of Whidbey Beta1 (.NET Framework v40607) it looks like MS may have done just that.&amp;nbsp; While I&amp;#39;m having issues with the beta, here&amp;#39;s an example from the Help:&lt;br /&gt;&lt;/p&gt;
&lt;blockquote&gt;&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; %&amp;gt;&lt;br /&gt;&amp;lt;%@ Import Namespace=&amp;quot;System.Web.Security&amp;quot;%&amp;gt;&lt;br /&gt;&amp;lt;SCRIPT runat=&amp;quot;server&amp;quot;&amp;gt;&lt;br /&gt;&lt;br /&gt;string[] rolesArray;&lt;br /&gt;&lt;br /&gt;public void Page_Load() {&lt;br /&gt;RolePrincipal r = (RolePrincipal)User;&lt;br /&gt;rolesArray = r.GetRoles();&lt;br /&gt;UserRolesGrid.DataSource = rolesArray;&lt;br /&gt;UserRolesGrid.DataBind();&lt;br /&gt;&lt;br /&gt;Heading.Text = &amp;quot;Roles for &amp;quot; + User.Identity.Name;&lt;br /&gt;}&lt;br /&gt;. . .&lt;br /&gt;&lt;/blockquote&gt;
&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;Past Comments&lt;/strong&gt; &lt;/p&gt;
&lt;hr /&gt;
&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;group code&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;hi john, i have been trying your code to get the ldap group. i cannot get it to work. below. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;if the userid is m-----y and the domain is cabrini.edu then how do you fill in the string? should this be able to run alone on an .asp page? &lt;/span&gt;&lt;span style="FONT-SIZE:10pt;COLOR:#aaaaaa;FONT-FAMILY:Verdana;"&gt;11/19/2004 8:23 AM | &lt;a href="http://www.cabrini.edu/" target="_blank"&gt;&lt;font color="#223355"&gt;mike b&lt;/font&gt;&lt;/a&gt; &lt;/span&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;re: Working with Windows Group Membership&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;Use the ADSI Edit utility to determine your ADsPath for the GetObject call. This url has a brief walkthrough of ADSI Edit: &lt;br /&gt;&lt;a href="http://www.w2kcfg.net/adsi_edit.htm" target="_new"&gt;&lt;font color="#223355"&gt;http://www.w2kcfg.net/adsi_edit.htm&lt;/font&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;The code will run from an ASP page if your Active Directory configuration allows anonymous read access. Here are a few articles on accessing AD from ASP: &lt;br /&gt;1. &lt;a href="http://www.serverwatch.com/tutorials/article.php/1476961" target="_new"&gt;&lt;font color="#223355"&gt;http://www.serverwatch.com/tutorials/article.php/1476961&lt;/font&gt;&lt;/a&gt; &lt;br /&gt;2. &lt;a href="http://www.serverwatch.com/tutorials/article.php/1478231" target="_new"&gt;&lt;font color="#223355"&gt;http://www.serverwatch.com/tutorials/article.php/1478231&lt;/font&gt;&lt;/a&gt; &lt;br /&gt;3. &lt;a href="http://www.serverwatch.com/tutorials/article.php/1482281" target="_new"&gt;&lt;font color="#223355"&gt;http://www.serverwatch.com/tutorials/article.php/1482281&lt;/font&gt;&lt;/a&gt; &lt;/span&gt;&lt;span style="FONT-SIZE:10pt;COLOR:#aaaaaa;FONT-FAMILY:Verdana;"&gt;11/19/2004 8:24 AM | &lt;a href="http://www.r3jkh.com/code" target="_blank"&gt;&lt;font color="#223355"&gt;john&lt;/font&gt;&lt;/a&gt; &lt;/span&gt;&lt;a class="" title="221" name="221"&gt;&lt;/a&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;re: Working with Windows Group Membership &lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;[Note: edited for length -- jkh] &lt;br /&gt;&lt;br /&gt;This issue all started because the code I am using currently which uses winnt sometimes just stops working and they have to reboot the webserver. Here is the line that stops working &lt;br /&gt;Set oADsObject = oADsNamespace.OpenDSObject(strADsPath, tempstr, strPassword, 0) &lt;br /&gt;&lt;br /&gt;I have tried many scripts and some work and some do not. For example--this works on a asp page on the server. &lt;br /&gt;set rootdse = getobject(&amp;quot;LDAP://SERVERNAME/Rootdse&amp;quot;) note-I must insert server name otherwise I get nothing. &lt;br /&gt;response.write &amp;quot;subschemasubentry&amp;quot; &amp;amp; rootdse.get(&amp;quot;subschemasubentry&amp;quot;)&amp;amp;&amp;quot; &lt;br /&gt;&lt;br /&gt;so I know the asp page can get info without needing a user name to sign onto the ldap server. But I cannot get thru the line starting with oUser.Faculty&amp;amp;Staff is a group &lt;br /&gt;&lt;br /&gt;Dim oUser &lt;br /&gt;Dim strGroups &lt;br /&gt;oUser=GetObject(&amp;quot;LDAP://SERVERNAME/CN=Users,CN=MYUSERNAME,dc=MYDOMAIN&amp;quot; &lt;br /&gt;) &lt;br /&gt;strGroups = Join(oUser.memberOf) &lt;br /&gt;If (InStr(strGroups, &amp;quot;CN=Faculty&amp;amp;Staff,&amp;quot;) &amp;lt;&amp;gt; 0) Then &lt;br /&gt;response.write &amp;quot;hello&amp;quot; &lt;br /&gt;End If &lt;br /&gt;&lt;br /&gt;The server is either w2000 or w2003. Is it really possible for this code to work? It seems to simple to be true. &lt;/span&gt;&lt;span style="FONT-SIZE:10pt;COLOR:#aaaaaa;FONT-FAMILY:Verdana;"&gt;11/24/2004 5:57 PM | &lt;a href="http://www.cabrini.edu/" target="_blank"&gt;&lt;font color="#223355"&gt;mike b&lt;/font&gt;&lt;/a&gt; &lt;/span&gt;&lt;a class="" title="222" name="222"&gt;&lt;/a&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;re: Working with Windows Group Membership &lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;It looks like you&amp;#39;re running into either a bad GetObject call or a security context issue. &lt;br /&gt;&lt;br /&gt;Firstly, you have to use &amp;#39;Set&amp;#39; on your GetObject call and fix the LDAP Path: &lt;br /&gt;01: Set oUser = GetObject(&amp;quot;LDAP://SERVERNAME/CN=MYUSERNAME,OU=Users,dc=MYDOMAIN&amp;quot;) &lt;br /&gt;Use ADSI Edit to ensure you have the right path, some businesses have a CN that differs from USERNAME. &lt;br /&gt;&lt;br /&gt;If changing that one line doesn&amp;#39;t just magically work (and it will if your Active Directory allows anonymous queries), then you have a security context issue and need to pass credentials to the Domain Controller via your code or IIS. &lt;br /&gt;&lt;br /&gt;Doing it from code is pretty simple: &lt;br /&gt;02: Set objADsNamespace = GetObject(&amp;quot;LDAP:&amp;quot;) &lt;br /&gt;03: Set objUser = objADsNamespace.OpenDSObject(strADsPath, strUser, strPassword, 0) &lt;br /&gt;04: Response.Write Join(objUser.memberOf) &lt;br /&gt;05: &lt;br /&gt;06: Set objUser = Nothing &lt;br /&gt;07: Set objADsNamespace = Nothing &lt;br /&gt;&lt;br /&gt;Note that the strADsPath in line 03 is the same string that was passed to GetObject() on line 01, and that strUser is in the form of &amp;quot;DOMAIN\USERNAME&amp;quot;. I numbered the lines just for convenience. &lt;br /&gt;&lt;br /&gt;You can also configure IIS (under Properties-&amp;gt;Directory Security-&amp;gt;Edit) to run as a domain account or use Basic Authentication (under SSL) to work around this. &lt;/span&gt;&lt;span style="FONT-SIZE:10pt;COLOR:#aaaaaa;FONT-FAMILY:Verdana;"&gt;11/24/2004 6:00 PM | &lt;a href="http://www.r3jkh.com/code" target="_blank"&gt;&lt;font color="#223355"&gt;john&lt;/font&gt;&lt;/a&gt; &lt;/span&gt;&lt;a class="" title="227" name="227"&gt;&lt;/a&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;re: Working with Windows Group Membership&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;Hi, &lt;br /&gt;&lt;br /&gt;My Name is Roberto T. &lt;br /&gt;&lt;br /&gt;I am a bit lost on the following snippet of code from above: &lt;br /&gt;&lt;br /&gt;group = new DirectoryEntry(String.Format(&amp;quot;LDAP://&amp;lt;SID={0}gt;&amp;quot;, &lt;br /&gt;hexString.ToString())); &lt;br /&gt;&lt;br /&gt;&amp;quot;LDAP:// ....&amp;quot; &lt;br /&gt;&lt;br /&gt;what am I supposed to enter here. and how do I use adsi to help find the right path for this. I guess this is the final component to resolve the sid to the actual group name. &lt;br /&gt;&lt;br /&gt;thanks for all your help... &lt;/span&gt;&lt;span style="FONT-SIZE:10pt;COLOR:#aaaaaa;FONT-FAMILY:Verdana;"&gt;12/5/2004 10:03 AM | &lt;a href="mailto:rtorres1228@yahoo.com" target="_blank"&gt;&lt;font color="#223355"&gt;rtorres1228@yahoo.com&lt;/font&gt;&lt;/a&gt; &lt;/span&gt;&lt;a class="" title="229" name="229"&gt;&lt;/a&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;re: Working with Windows Group Membership &lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;Roberto, &lt;br /&gt;Firstly, the gt; is a formatting error from the .TEXT interface, it&amp;#39;s meant to be the closing angle bracket (&amp;gt;). I&amp;#39;ll fix the article. &lt;br /&gt;&lt;br /&gt;Second, you&amp;#39;re right that it&amp;#39;s the final component for getting the friendly group name. Check out &lt;u&gt;&lt;span style="COLOR:#223355;"&gt;&lt;a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;Q301916"&gt;&lt;font color="#223355"&gt;http://support.microsoft.com/default.aspx?scid=kb;en-us;Q301916&lt;/font&gt;&lt;/a&gt;&lt;/span&gt;&lt;/u&gt; - it&amp;#39;s a simpler example for using the SID binding. &lt;br /&gt;&lt;br /&gt;You&amp;#39;re not going to enter a SID value in here by hand. Under the example hexString is the value that&amp;#39;s being passed, and hexString just holds one SID from the user&amp;#39;s tokenGroups attribute. &lt;/span&gt;&lt;span style="FONT-SIZE:10pt;COLOR:#aaaaaa;FONT-FAMILY:Verdana;"&gt;12/5/2004 12:34 PM | &lt;a href="http://www.r3jkh.com/code" target="_blank"&gt;&lt;font color="#223355"&gt;john&lt;/font&gt;&lt;/a&gt; &lt;/span&gt;&lt;a class="" title="230" name="230"&gt;&lt;/a&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;re: Working with Windows Group Membership &lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;[Note: edited for length -- jkh] &lt;br /&gt;&lt;br /&gt;John I tried the code you sent me and it works. I managed to determine which group a person is in also. &lt;br /&gt;&lt;br /&gt;But our system has some exchange users and some not. Because of that, exchange users have a path like &lt;br /&gt;strADsPath = &amp;quot;LDAP://SERVERNAME/CN=Lastname\, &lt;br /&gt;Firstname,CN=Users,dc=MyDomain&amp;quot; &lt;br /&gt;&lt;br /&gt;So the code only seems to work if &lt;br /&gt;&amp;quot;LDAP://SERVERNAME/CN=theirusername,CN=Users,dc= MyDomain&amp;quot; &lt;/span&gt;&lt;span style="FONT-SIZE:10pt;COLOR:#aaaaaa;FONT-FAMILY:Verdana;"&gt;12/5/2004 1:12 PM | &lt;a href="http://www.cabrini.edu/" target="_blank"&gt;&lt;font color="#223355"&gt;mike b&lt;/font&gt;&lt;/a&gt; &lt;/span&gt;&lt;span style="FONT-SIZE:10pt;COLOR:#aaaaaa;FONT-FAMILY:Verdana;"&gt;&lt;/span&gt;&lt;a class="" title="231" name="231"&gt;&lt;/a&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;re: Working with Windows Group Membership &lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;Mike, &lt;br /&gt;At this point I only have time to point you at a couple &lt;br /&gt;links. &lt;br /&gt;&lt;br /&gt;1. How To Use ADO to Access Objects Through an ADSI LDAP Provider &lt;br /&gt;&lt;a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;187529" target="_new"&gt;&lt;font color="#223355"&gt;http://support.microsoft.com/default.aspx?scid=kb;en-us;187529&lt;/font&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;and the Microsoft Script Center for Active Directory &lt;br /&gt;&lt;a href="http://www.microsoft.com/technet/scriptcenter/scripts/ad/default.mspx" target="_new"&gt;&lt;font color="#223355"&gt;http://www.microsoft.com/technet/scriptcenter/scripts/ad/default.mspx&lt;/font&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;Between these two, you should be able to get what you need &lt;/span&gt;&lt;span style="FONT-SIZE:10pt;COLOR:#aaaaaa;FONT-FAMILY:Verdana;"&gt;12/5/2004 1:13 PM | &lt;a href="http://www.r3jkh.com/code/" target="_blank"&gt;&lt;font color="#223355"&gt;john&lt;/font&gt;&lt;/a&gt;&lt;/span&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;re: Working with Windows Group Membership &lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;John, &lt;br /&gt;&lt;br /&gt;I appreciate your prompt response. You are very generous with your time. &lt;br /&gt;&lt;br /&gt;However, I looked at the link you had listed. It is done in Visual Basic. My limitted expertise is in C#. If you can point me to another example done in the later I would be much appreciative. Also I think my problem stems with my lack of familiarity with ADSI programming. When you try to get a &amp;quot;DirectoyEnty&amp;quot; using the hexString as a parameter to &amp;quot;LDAP://&amp;lt;SID={0}&amp;quot; don&amp;#39;t you need to prefix this with &lt;br /&gt;&amp;quot;LDAP://distiguished-name of some node/&amp;lt;SID={0}&amp;quot;. Forgive me if I am using the wrong terms here. I find it hard to see how it would now where to look? &lt;br /&gt;&lt;br /&gt;thanks &lt;/span&gt;&lt;span style="FONT-SIZE:10pt;COLOR:#aaaaaa;FONT-FAMILY:Verdana;"&gt;12/5/2004 3:50 PM | &lt;a href="http://rtorres1228@yahoo.com" target="_blank"&gt;&lt;font color="#223355"&gt;rtorres1228&lt;/font&gt;&lt;/a&gt; &lt;/span&gt;&lt;a class="" title="233" name="233"&gt;&lt;/a&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;re: Working with Windows Group Membership &lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;I meant &amp;quot;LDAP://&amp;lt;SID={0}&amp;gt;,...&amp;quot; &lt;br /&gt;&lt;br /&gt;How does it know where this is will mapped. To say the least It is now working for me. I get an unkown error when I try it. &lt;br /&gt;&lt;br /&gt;thanks &lt;/span&gt;
&lt;p class="MsoNormal" style="MARGIN:0in 0in 0pt;"&gt;&lt;span style="FONT-SIZE:10pt;COLOR:#aaaaaa;FONT-FAMILY:Verdana;"&gt;12/5/2004 3:52 PM | &lt;a href="http://rtorres1228@yahoo.com" target="_blank"&gt;&lt;font color="#223355"&gt;rtorres1228&lt;/font&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="" title="234" name="234"&gt;&lt;/a&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;re: Working with Windows Group Membership&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;I mean it is not working... &lt;/span&gt;
&lt;p class="MsoNormal" style="MARGIN:0in 0in 0pt;"&gt;&lt;span style="FONT-SIZE:10pt;COLOR:#aaaaaa;FONT-FAMILY:Verdana;"&gt;12/5/2004 3:52 PM | &lt;a href="http://rtorres1228@yahoo.com" target="_blank"&gt;&lt;font color="#223355"&gt;rtorres1228&lt;/font&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="" title="235" name="235"&gt;&lt;/a&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;re: Working with Windows Group Membership&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Verdana;"&gt;John, &lt;br /&gt;&lt;br /&gt;I found out where the problem was. I found this article: &lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;span style="COLOR:#223355;"&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ad/ad/binding_to_an_object_using_a_sid.asp"&gt;&lt;font color="#223355"&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ad/ad/binding_to_an_object_using_a_sid.asp&lt;/font&gt;&lt;/a&gt;&lt;/span&gt;&lt;/u&gt; &lt;br /&gt;&lt;br /&gt;where it explains: &lt;br /&gt;&lt;br /&gt;&amp;quot;LDAP://servername/&amp;lt;SID=XXXXX&amp;gt; &lt;br /&gt;&lt;br /&gt;In this example, servername is the name of the directory server &lt;br /&gt;and XXXXX is the string representation of the hexadecimal value of &lt;br /&gt;the SID. The servername is optional. The SID string is specified in &lt;br /&gt;a form where each character in the string is the hexadecimal representation &lt;br /&gt;of each byte of the SID.&amp;quot; &lt;br /&gt;&lt;br /&gt;The machine I am development from is not a member of the AD domain. Once I typed the name of the DC in place of Servername I was working. &lt;br /&gt;&lt;br /&gt;Thanks for your help! &lt;br /&gt;&lt;br /&gt;(:-) &lt;/span&gt;
&lt;p class="MsoNormal" style="MARGIN:0in 0in 0pt;"&gt;&lt;span style="FONT-SIZE:10pt;COLOR:#aaaaaa;FONT-FAMILY:Verdana;"&gt;12/5/2004 4:43 PM | &lt;a href="http://rtorres1228@yahoo.com" target="_blank"&gt;&lt;font color="#223355"&gt;rtorres1228&lt;/font&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;img src="http://jkhines.com/aggbug.aspx?PostID=7" width="1" height="1"&gt;</content><author><name>jkhines</name><uri>http://jkhines.com/members/jkhines.aspx</uri></author><category term="coding" scheme="http://jkhines.com/blogs/code/archive/tags/coding/default.aspx" /></entry></feed>