Visual Basic Q&A

As a software engineer, I focus on .NET, especially asp.net, C#, WCF and so on, and I am also very interested in Search Engine Optimization.

Entries Tagged ‘internet information services’

PRB: “Requested Registry Access Is Not Allowed” Error Message When ASP.NET Application Tries to Write New EventSource in the EventLog

Symptoms
When you use ASP.NET to create a new event source in the event log, you may receive the following error message:

System.Security.SecurityException: Requested registry access is not allowed.
Resolution
By default, the user token of the ASP.NET worker process is ASPNET (or NetworkService for applications that run on Internet Information Services [IIS] 6.0). The problem in the “Symptoms” section occurs because your account does not have the correct user rights to create an event source.

How To Retrieve XML Data with a Template File from a Visual Basic Client

Symptoms
This sample in this article demonstrates how to retrieve an XML document from SQL Server 2000 by using a template file that contains parameters.More specifically, a query is issued against SQL Server 2000 by using an ActiveX Data Objects (ADO) 2.6 command stream. This query fetches the XML DataStream.
This sample reads the “products.xml” template file from disk and sets thecommand text for the ADODB.Command object for the query to run.
You must set the following properties for the Properties collection of the ADODB.Command object:Base Path. This property establishes the location of the template and the Extensible Style Sheet Language (XSL) files.Output Stream. This property designates where the resulting XML data stream will be piped.Dialect. The dialect defines the syntax and the general rules that the provider uses to parse the string or the stream. By setting the command language dialect, you specify how the Microsoft OLE DB Provider for SQL Server interprets the command text that is received from ADO. The dialect is specified by a globally unique identifier (GUID) and is set by using the Dialect property of the Command object.XSL. This property transforms the XML document.NOTE: Output Stream may be any object that supports an IStream or ISequentialStream interface. Objects that support the IStream interfaces are the ADODB.Stream object, the Microsoft Internet Information Services (IIS) 5.0 Response object, and a Microsoft XML (MSXML) DomDocument object.
Resolution
Create a new Standard EXE project in Visual Basic. Form1 is created by default.On the Project menu, click Components, and then add a reference to both Microsoft Internet Controls and Microsoft ActiveX Data Objects 2.6.Add a Web browser to the form, name it WebBrowser1, and then size it accordingly.Add a frame to the form, and place two option buttons in it. Name the first button optXSLYes with the caption XSL Yes, and then name the second button optXSLNo with the caption XSL No.Add two command buttons. Name the first button cmdTestIt with the caption Test, and then name the second button cmdExitProgram with the caption Exit.Paste the following Visual Basic code in the Code window of the form:

Option ExplicitConst DBGUID_DEFAULT As String = “{C8B521FB-5CF3-11CE-ADE5-00AA0044773D}” Private Sub cmdExitProgram_Click()Unload MeEndEnd SubPrivate Sub cmdTestIt_Click()Dim cn As New ADODB.ConnectionDim cmd As New ADODB.CommandDim cmdStream As New ADODB.StreamDim cmdOutput As New ADODB.StreamDim txtOutputFileName As String’ open the database connectioncn.Open “provider=sqloledb;data source=.;initial catalog=northwind;uid=sa;pwd=”‘ open the command stream that will eventually contain the templated querycmdStream.Open’ set the character set to asciicmdStream.Charset = “ascii”‘ set the command stream type to text, not binary.cmdStream.Type = adTypeText’ read the template file from disk into the command stream to executecmdStream.LoadFromFile App.Path & “\products.xml”‘ set the command connectionSet cmd.ActiveConnection = cn’ set the command’s command stream to hook the template query to the command you want to run.Set cmd.CommandStream = cmdStream’ set the command dialectcmd.Dialect = DBGUID_DEFAULT’ open the output stream to receive the results for the command execute.cmdOutput.Open’ set the base path for where the template file resides.’ Currently, this must point to a file on disk. Remote templates via’ http://…template.xml” are not allowed.cmd.Properties(“Base Path”) = App.Path’ set up the output stream that will receive the output of the command execute.cmd.Properties(“Output Stream”) = cmdOutput’ set the XSL to process if the user requested the output to be fixed.If optXSLYes Then’ set the file name for the XSL: this inherits the “base path” settingcmd.Properties(“XSL”) = “products.xsl”‘ set the file extension to “.htm”, mainly so the Web browser displays’ set the output as a table.Try with a “.xml” extension… what is displayed?txtOutputFileName = App.Path & “\queryout.htm”ElsetxtOutputFileName = App.Path & “\queryout.xml”End If’ execute the command stream with the settings specified above.cmd.Execute , , adExecuteStream’ position the stream back to the beginning: the “file position” in the’stream will be at the end of the stream.Writing to a stream will append’on the end and only while the output from the command execute generates.cmdOutput.Position = 0’save the output to a file, this is only needed to use the navigate on the Web browser controlcmdOutput.SaveToFile txtOutputFileName, adSaveCreateOverWrite’ Navigate/display the results of the command executes.WebBrowser1.Navigate txtOutputFileName’ close and clean-up the objects used.cmdOutput.ClosecmdStream.Closecn.CloseSet cmdOutput = NothingSet cmdStream = NothingSet cmd = NothingSet cn = NothingEnd Sub To create a template file, create a new text file, paste the following template into the file, and then save it with a name of products.xml:

<?xml version=’1.0′ ?><root xmlns:sql=”urn:schemas-microsoft-com:xml-sql”><sql:header><sql:param name=”ProdName”>%</sql:param></sql:header><sql:query>SELECT*FROMProductsWHEREProductName like ‘%’ + @ProdName + ‘%’ORDER BYProductNameFOR XML AUTO</sql:query></root> As an option, create a file named products.xsl with the following code to transform the output:

<?xml version=’1.0′ ?><xsl:stylesheet xmlns:xsl=”http://www.w3.org/TR/WD-xsl”><xsl:template match=”/”><html><head><title>MSDN ADO Product Sample with SQL Server 2000 Features</title><base href=”http://localhost/3tier/” /></head><body><table border=”0″ cellPadding=”1″ cellSpacing=”1″width=”100%”style=”COLOR:black;FONT-FAMILY:Arial;FONT-SIZE:12pt.;FONT-WEIGHT:500″><tr bgColor=”#336699″ align=”center”><TD><P ><STRONG><FONT color=”white” size=”2″>Product ID:</FONT></STRONG></P></TD><TD><P ><STRONG><FONT color=”white” size=”2″>Product Name:</FONT></STRONG></P></TD><TD><P ><STRONG><FONT color=”white” size=”2″>Unit Price:</FONT></STRONG></P></TD><TD><P ><STRONG><FONT color=”white” size=”2″>Units In Stock:</FONT></STRONG></P></TD><TD><P ><STRONG><FONT color=”white” size=”2″>Restock Level:</FONT></STRONG></P></TD><TD><P ><FONT color=”white” size=”2″><STRONG>Units On Order:</STRONG></FONT></P></TD></tr><xsl:for-each select=”root/Products”><tr style=”COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 0.8em; FONT-WEIGHT: 500″><td bgColor=”#F0F0F0″><xsl:value-of select=”@ProductID”/></td><td bgColor=”#F0F0F0″><xsl:value-of select=”@ProductName”/></td><td bgColor=”#F0F0F0″><xsl:value-of select=”@UnitPrice”/></td><td bgColor=”#F0F0F0″><xsl:value-of select=”@UnitsInStock”/></td><td bgColor=”#F0F0F0″><xsl:value-of select=”@ReorderLevel”/></td><td bgColor=”#F0F0F0″><xsl:value-of select=”@UnitsOnOrder”/></td></tr></xsl:for-each></table></body></html></xsl:template></xsl:stylesheet>

How to implement impersonation in an ASP.NET application

Symptoms
This article describes different ways to implement impersonation in an ASP.NET application.
Resolution
If you want to impersonate a user on a thread in ASP.NET, you can use one of the following methods, based on your requirments: Impersonate the IIS authenticated account or userImpersonate a specific user for all the requests of an ASP.NET application Impersonate the authenticating user in codeImpersonate a specific user in codeNote You can use the following code to determine what user the thread is executing as:

System.Security.Principal.WindowsIdentity.GetCurrent().Name
Impersonate the IIS Authenticated Account or User To impersonate the Microsoft Internet Information Services (IIS) authenticating user on every request for every page in an ASP.NET application, you must include an <identity> tag in the Web.config file of this application and set the impersonate attribute to true. For example:

<identity impersonate=”true” />
Impersonate a Specific User for All the Requests of an ASP.NET Application To impersonate a specific user for all the requests on all pages of an ASP.NET application, you can specify the userName and password attributes in the <identity> tag of the Web.config file for that application. For example:

<identity impersonate=”true” userName=”accountname” password=”password” /> Note The identity of the process that impersonates a specific user on a thread must have the “Act as part of the operating system” privilege. By default, the Aspnet_wp.exe process runs under a computer account named ASPNET. However, this account does not have the required privileges to impersonate a specific user. You receive an error message if you try to impersonate a specific user. This information applies only to the .NET Framework 1.0. This privilege is not required for the .NET Framework 1.1.
To work around this problem, use one of the following methods: Grant the “Act as part of the operating system” privilege to the ASPNET account (the least privileged account).
Note Although you can use this method to work around the problem, Microsoft does not recommend this method.Change the account that the Aspnet_wp.exe process runs under to the System account in the <processModel> configuration section of the Machine.config file.
Impersonate the Authenticating User in Code To impersonate the authenticating user (User.Identity) only when you run a particular section of code, you can use the code to follow. This method requires that the authenticating user identity is of type WindowsIdentity.
Visual Basic .NET

Dim impersonationContext As System.Security.Principal.WindowsImpersonationContextDim currentWindowsIdentity As System.Security.Principal.WindowsIdentitycurrentWindowsIdentity = CType(User.Identity, System.Security.Principal.WindowsIdentity)impersonationContext = currentWindowsIdentity.Impersonate()’Insert your code that runs under the security context of the authenticating user here.impersonationContext.Undo() Visual C# .NET

System.Security.Principal.WindowsImpersonationContext impersonationContext;impersonationContext =((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();//Insert your code that runs under the security context of the authenticating user here.impersonationContext.Undo(); Visual J# .NET

System.Security.Principal.WindowsImpersonationContext impersonationContext;impersonationContext =((System.Security.Principal.WindowsIdentity)get_User().get_Identity()).Impersonate();//Insert your code that runs under the security context of the authenticating user here.impersonationContext.Undo();
Impersonate a Specific User in Code To impersonate a specific user only when you run a particular section of code, use the following code:
Visual Basic .NET

<%@ Page Language=”VB” %><%@ Import Namespace = “System.Web” %><%@ Import Namespace = “System.Web.Security” %><%@ Import Namespace = “System.Security.Principal” %><%@ Import Namespace = “System.Runtime.InteropServices” %><script runat=server>Dim LOGON32_LOGON_INTERACTIVE As Integer = 2Dim LOGON32_PROVIDER_DEFAULT As Integer = 0Dim impersonationContext As WindowsImpersonationContextDeclare Function LogonUserA Lib “advapi32.dll” (ByVal lpszUsername As String, _ByVal lpszDomain As String, _ByVal lpszPassword As String, _ByVal dwLogonType As Integer, _ByVal dwLogonProvider As Integer, _ByRef phToken As IntPtr) As IntegerDeclare Auto Function DuplicateToken Lib “advapi32.dll” ( _ByVal ExistingTokenHandle As IntPtr, _ByVal ImpersonationLevel As Integer, _ByRef DuplicateTokenHandle As IntPtr) As IntegerDeclare Auto Function RevertToSelf Lib “advapi32.dll” () As LongDeclare Auto Function CloseHandle Lib “kernel32.dll” (ByVal handle As IntPtr) As LongPublic Sub Page_Load(ByVal s As Object, ByVal e As EventArgs)If impersonateValidUser(“username”, “domain”, “password”) Then’Insert your code that runs under the security context of a specific user here.undoImpersonation()Else’Your impersonation failed. Therefore, include a fail-safe mechanism here.End IfEnd SubPrivate Function impersonateValidUser(ByVal userName As String, _ByVal domain As String, ByVal password As String) As BooleanDim tempWindowsIdentity As WindowsIdentityDim token As IntPtr = IntPtr.ZeroDim tokenDuplicate As IntPtr = IntPtr.ZeroimpersonateValidUser = FalseIf RevertToSelf() ThenIf LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT, token) <> 0 ThenIf DuplicateToken(token, 2, tokenDuplicate) <> 0 ThentempWindowsIdentity = New WindowsIdentity(tokenDuplicate)impersonationContext = tempWindowsIdentity.Impersonate()If Not impersonationContext Is Nothing ThenimpersonateValidUser = TrueEnd IfEnd IfEnd IfEnd IfIf Not tokenDuplicate.Equals(IntPtr.Zero) ThenCloseHandle(tokenDuplicate)End IfIf Not token.Equals(IntPtr.Zero) ThenCloseHandle(token)End IfEnd FunctionPrivate Sub undoImpersonation()impersonationContext.Undo()End Sub</script>Visual C# .NET

<%@ Page Language=”C#”%><%@ Import Namespace = “System.Web” %><%@ Import Namespace = “System.Web.Security” %><%@ Import Namespace = “System.Security.Principal” %><%@ Import Namespace = “System.Runtime.InteropServices” %><script runat=server>public const int LOGON32_LOGON_INTERACTIVE = 2;public const int LOGON32_PROVIDER_DEFAULT = 0;WindowsImpersonationContext impersonationContext; [DllImport("advapi32.dll")]public static extern int LogonUserA(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]public static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]public static extern bool RevertToSelf();[DllImport("kernel32.dll", CharSet=CharSet.Auto)]public static externbool CloseHandle(IntPtr handle);public void Page_Load(Object s, EventArgs e){ if(impersonateValidUser(“username”, “domain”, “password”)) { //Insert your code that runs under the security context of a specific user here. undoImpersonation(); } else { //Your impersonation failed. Therefore, include a fail-safe mechanism here. }}private bool impersonateValidUser(String userName, String domain, String password){ WindowsIdentity tempWindowsIdentity; IntPtr token = IntPtr.Zero; IntPtr tokenDuplicate = IntPtr.Zero; if(RevertToSelf()) { if(LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0) { if(DuplicateToken(token, 2, ref tokenDuplicate) != 0) { tempWindowsIdentity = new WindowsIdentity(tokenDuplicate); impersonationContext = tempWindowsIdentity.Impersonate(); if (impersonationContext != null) { CloseHandle(token); CloseHandle(tokenDuplicate); return true; } } } } if(token!= IntPtr.Zero) CloseHandle(token); if(tokenDuplicate!=IntPtr.Zero) CloseHandle(tokenDuplicate); return false;}private void undoImpersonation(){ impersonationContext.Undo();}</script>Visual J# .NET

<%@ Page language=”VJ#” %><%@ Import Namespace=”System.Web” %><%@ Import Namespace=”System.Web.Security” %><%@ Import Namespace=”System.Security.Principal” %><%@ Import Namespace=”System.Runtime.InteropServices” %><script runat=server>public static int LOGON32_LOGON_INTERACTIVE = 2;public static int LOGON32_PROVIDER_DEFAULT = 0;WindowsImpersonationContext impersonationContext; /** @attribute DllImport(“advapi32.dll”) */ public static native int LogonUserA(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, System.IntPtr[] phToken);/** @attribute DllImport(“advapi32.dll”, CharSet=CharSet.Auto, SetLastError=true) */ public static native int DuplicateToken(System.IntPtr hToken, int impersonationLevel, System.IntPtr[] hNewToken);/** @attribute DllImport(“kernel32.dll”,CharSet=CharSet.Auto) */ public static nativeboolean CloseHandle(System.IntPtr[] handle);/** @attribute DllImport(“advapi32.dll”, CharSet=CharSet.Auto,SetLastError=true) */ public static native boolean RevertToSelf();public void Page_Load(Object s, System.EventArgs e){ if(impersonateValidUser(“username”, “domain”, ” password”)) { //Insert your code that runs under the security context of a specific user here. undoImpersonation(); } else { //Your impersonation failed. Therefore, include a fail-safe mechanism here. }}private boolean impersonateValidUser(String userName, String domain, String password){ WindowsIdentity tempWindowsIdentity; System.IntPtr[] token = new System.IntPtr[1]; System.IntPtr[] tokenDuplicate = new System.IntPtr[1]; if(RevertToSelf()) { if(LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, token) != 0) { if(DuplicateToken(token[0], 2, tokenDuplicate) != 0) { tempWindowsIdentity = new WindowsIdentity(tokenDuplicate[0]); impersonationContext = tempWindowsIdentity.Impersonate(); if (impersonationContext != null) { CloseHandle(tokenDuplicate); CloseHandle(token); return true; } } } } if(!token[0].Equals(System.IntPtr.Zero)) CloseHandle(token); if(!tokenDuplicate[0].Equals(System.IntPtr.Zero)) CloseHandle(tokenDuplicate); return false;}private void undoImpersonation(){ impersonationContext.Undo();}</script> Note The identity of the process that impersonates a specific user on a thread must have the “Act as part of the operating system” privilege if the Aspnet_wp.exe process is running on a Microsoft Windows 2000-based computer. The “Act as part of the operating system” privilege is not required if the Aspnet_wp.exe process is running on a Windows XP-based computer or on a Windows Server 2003-based computer. By default, the Aspnet_wp.exe process runs under a computer account named ASPNET. However, this account does not have the required privileges to impersonate a specific user. You receive an error message if you try to impersonate a specific user. .
To work around this problem, use one of the following methods: Grant the “Act as part of the operating system” privilege to the ASPNET account.
Note We do not recommend this method to work around the problem.Change the account that the Aspnet_wp.exe process runs under to the System account in the <processModel> configuration section of the Machine.config file.