RE: Exception Handling Block not writing to Vista Event Log

Tech-Archive recommends: Fix windows errors by optimizing your registry



Zhi-Xin,

Perhaps I wasn't completely clear, I will try again.

As I wrote originally "I have written code which
creates an Event Source for the application using a Custom Installer which
overrides the Install method of the Installer class". This works fine.
The code that creates the registry key at
"SYSTEM\CurrentControlSet\Services\EventLog\Application\Driver Documents
Manager" runs during the installation of the application and does create the
key with UAC turned on and running as a normal user.

When I try to run the application which is installed is when I have problems
writing to the registry. Again if I just use code such as
EventLog.WriteEntry an event will be written to the event log if I am a
normal user, however, using the Exception Handling Application Block, it does
not unless I run the application as Administrator.

As for elevating privileges, it wouldn't make sense to me to elevate
privileges upon a button click since this is not when the registry key is
being created. The registry key is created during the installation.
Additionally the only time I am writing to the event log is when an exception
occurs so if I needed to elevate privileges here I would either have to
include the shield on every button in the application in case an exception
occurs or write code to elevate to administrator privileges each time an
exception occurs.

I hope I have made this more clear and look forward to your response.

--
TomM


"Zhi-Xin Ye [MSFT]" wrote:

Dear TomM,

As I said in my last reply, it requires the Administrator privileges to
create register keys.

In your code, you try to create the following register key if it did not
exist:

"SYSTEM\CurrentControlSet\Services\EventLog\Application\Driver Documents
Manager"

============ Your Code================

keyName = String.Concat(EVENTLOG_REGISTERY_KEY_NAME, eventLogName,
System.IO.Path.DirectorySeparatorChar, sourceName)
rkEventSource = Registry.LocalMachine.OpenSubKey(keyName, False)

'Check whether event source key exists.
If rkEventSource Is Nothing Then
Registry.LocalMachine.CreateSubKey(keyName & "")
rkEventSource = Registry.LocalMachine.OpenSubKey(keyName,
False)
Else
'The key already exists. Just continue.
End If

======================================

However, on Vista, the UAC is turned on by default, which means when the
UAC is on and you don't run the application as Administrator, it won't have
privileges to create the register key, resulting the failure of your
application. It's NOT the Exception Handling Application Block that causes
the problem. The EventLog.WriteEntry method works running as a normal user
because this method does NOT require the administrator privileges.

--> " What changes after I run it as adminstrator once which then allows it
to write to the Application event log even when not run as administrator
and how can I get around have to run it as administrator the first time?"

After you running the application as Administrator, the register key you
need is created. So next time you run the application, since the register
key you need exists, it just skips the calling for the
Registry.LocalMachine.CreateSubKey method, so the application works fine.
However, if you go to the Windows Register Editor and delete the register
key you created ( which is
"SYSTEM\CurrentControlSet\Services\EventLog\Application\Driver Documents
Manager"), and run you application again as a normal user, it should fail.

When designing applications for Vista, I would recommend you elevate the
process for admin tasks, showing the UAC prompt dialog if the current user
did not have the Administrator privileges, I write the following sample
code about how to do this for your information. In this sample, there's a
button on the form, when the form loads, it checks whether the current user
is Administrator or not, if not, a UAC shield is displayed on the button,
and when the button is clicked, the UAC prompt dialog pops up.

=========== My Sample For Your Information ===========

Public Class Form4

Shared Sub CreateEventSource()

Dim eventLogName As String = "Application"
Dim sourceName As String = "Driver Documents Manager"
Dim keyName As String = String.Empty
Dim rkEventSource As RegistryKey = Nothing
Dim eventMessageFile As Object

Const EVENTLOG_REGISTERY_KEY_NAME As String =
"SYSTEM\CurrentControlSet\Services\EventLog\"

Try
keyName = String.Concat(EVENTLOG_REGISTERY_KEY_NAME,
eventLogName, System.IO.Path.DirectorySeparatorChar, sourceName)
rkEventSource = Registry.LocalMachine.OpenSubKey(keyName, False)

'Check whether event source key exists.
If rkEventSource Is Nothing Then
Registry.LocalMachine.CreateSubKey(keyName & "")
rkEventSource = Registry.LocalMachine.OpenSubKey(keyName,
False)
Else
'The key already exists. Just continue.
End If

'Other code here
Catch
Finally

End Try

End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click

If Me.IsAdmin Then
CreateEventSource()
Else
Dim startInfo As ProcessStartInfo = New ProcessStartInfo
startInfo.UseShellExecute = True
startInfo.WorkingDirectory = Environment.CurrentDirectory
startInfo.FileName = Application.ExecutablePath
startInfo.Verb = "runas"
Try
Dim p As Process = Process.Start(startInfo)
Catch ex As System.ComponentModel.Win32Exception
Return
End Try
Application.Exit()
End If

End Sub

Const BCM_SETSHIELD As UInteger = &H160C

'Elevated button
Private IsAdmin As Boolean = True

<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=False)> _
Private Shared Function SendMessage(ByVal hWnd As IntPtr, _
ByVal Msg As UInteger, ByVal wParam
As IntPtr, _
ByVal lParam As IntPtr) As IntPtr
End Function


Private Sub Form4_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim id As WindowsIdentity = WindowsIdentity.GetCurrent
Dim p As WindowsPrincipal = New WindowsPrincipal(id)
Me.IsAdmin = p.IsInRole(WindowsBuiltInRole.Administrator)
If Not Me.IsAdmin Then
Me.Button1.FlatStyle = FlatStyle.System
SendMessage(Button1.Handle, BCM_SETSHIELD, 0, &HFFFFFFFF)
Me.IsAdmin = False
End If
End Sub
End Class

================================================

If any of my explanation is unclear, please let me know.

Sincerely,
Zhi-Xin Ye
Microsoft Managed Newsgroup Support Team

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
msdnmg@xxxxxxxxxxxxxx

This posting is provided "AS IS" with no warranties, and confers no rights.




.


Quantcast