Hmm $50,-- :-)
I have written a class that can solve this problem , i use this class to
write to a locations where normall users do not have access rights
### CLASS CODE ###
'Michel Posseth [MCP] 10-07-2008 , written to run parts of code in another
user context during runtime
Imports System.Security
Imports System.Security .Principal
Imports System.Runtime. InteropServices
Public Class ImpersonateSpec ificUser
Implements IDisposable
Private Const LOGON32_LOGON_I NTERACTIVE As Integer = 2
Private Const LOGON32_PROVIDE R_DEFAULT As Integer = 0
Private impersonationCo ntext As WindowsImperson ationContext
Declare Function LogonUserA Lib "advapi32.d ll" (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 Integer
Declare Auto Function DuplicateToken Lib "advapi32.d ll" ( _
ByVal ExistingTokenHa ndle As IntPtr, _
ByVal ImpersonationLe vel As Integer, _
ByRef DuplicateTokenH andle As IntPtr) As Integer
Declare Auto Function RevertToSelf Lib "advapi32.d ll" () As Long
Declare Auto Function CloseHandle Lib "kernel32.d ll" (ByVal handle As
IntPtr) As Long
Public Event eSpecificUserIm personation(ByV al Success As Boolean)
Private _Impersonated As Boolean
''' <summary>
''' Gets or sets a value indicating whether this <see
cref="Impersona teSpecificUser" /is impersonated.
''' </summary>
''' <value><c>tru e</cif impersonated; otherwise, <c>false</c>.</value>
Public Property Impersonated() As Boolean
Get
Return _Impersonated
End Get
Private Set(ByVal value As Boolean)
_Impersonated = value
End Set
End Property
''' <summary>
''' Initializes a new instance of the <see cref="Impersona teSpecificUser" />
class.
''' </summary>
''' <param name="UserName" >Name of the user.</param>
''' <param name="Password" >The password.</param>
''' <param name="Domain">T he domain.</param>
Public Sub New(ByVal UserName As String, ByVal Password As String, ByVal
Domain As String)
If impersonateVali dUser(UserName, Domain, Password) Then
RaiseEvent eSpecificUserIm personation(Tru e)
Else
'Your impersonation failed. Therefore, include a fail-safe mechanism here.
RaiseEvent eSpecificUserIm personation(Fal se)
End If
End Sub
''' <summary>
''' Impersonates the valid user.
''' </summary>
''' <param name="userName" >Name of the user.</param>
''' <param name="domain">T he domain.</param>
''' <param name="password" >The password.</param>
''' <returns></returns>
Private Function impersonateVali dUser(ByVal userName As String, ByVal domain
As String, ByVal password As String) As Boolean
Dim tempWindowsIden tity As WindowsIdentity
Dim token As IntPtr = IntPtr.Zero
Dim tokenDuplicate As IntPtr = IntPtr.Zero
impersonateVali dUser = False
If RevertToSelf() Then
If LogonUserA(user Name, domain, password, LOGON32_LOGON_I NTERACTIVE,
LOGON32_PROVIDE R_DEFAULT, token) <0 Then
If DuplicateToken( token, 2, tokenDuplicate) <0 Then
tempWindowsIden tity = New WindowsIdentity (tokenDuplicate )
impersonationCo ntext = tempWindowsIden tity.Impersonat e()
If Not impersonationCo ntext Is Nothing Then
impersonateVali dUser = True
End If
End If
End If
End If
If Not tokenDuplicate. Equals(IntPtr.Z ero) Then
CloseHandle(tok enDuplicate)
End If
If Not token.Equals(In tPtr.Zero) Then
CloseHandle(tok en)
End If
End Function
''' <summary>
''' Undoes the impersonation.
''' </summary>
Public Sub undoImpersonati on()
impersonationCo ntext.Undo()
Impersonated = False
End Sub
#Region " IDisposable Support "
Private disposedValue As Boolean = False ' To detect redundant calls
' IDisposable
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValu e Then
If disposing Then
' TODO: free other state (managed objects).
End If
If Impersonated Then 'wees er zeer van dat we weer in een normale context
draaien
undoImpersonati on()
End If
' TODO: free your own state (unmanaged objects).
' TODO: set large fields to null.
End If
Me.disposedValu e = True
End Sub
' This code added by Visual Basic to correctly implement the disposable
pattern.
Public Sub Dispose() Implements IDisposable.Dis pose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As
Boolean) above.
Dispose(True)
GC.SuppressFina lize(Me)
End Sub
#End Region
''' <summary>
''' Impersonates the specific user_e specific user impersonation.
''' </summary>
''' <param name="Success"> if set to <c>true</c[success].</param>
Private Sub ImpersonateSpec ificUser_eSpeci ficUserImperson ation(ByVal Success
As Boolean) Handles Me.eSpecificUse rImpersonation
Me.Impersonated = Success
End Sub
End Class
### CLASS CODE ###
Usage :
Using UImp As New UserImpersonate .ImpersonateSpe cificUser("User name",
"password", "Domain")
IF UImp.Impersonat ed Then
'all code here that must run in the user context or the method calls to
other procedures
End If
End Using
after this point the code runs in "Normall" modus
HTH
Michel Posseth [MCP]
"Zarborg" <Za*****@discus sions.microsoft .comschreef in bericht
news:F0******** *************** ***********@mic rosoft.com...
I'm writing a little program that will run when a user logs in, checks
their
password expiration and also installs a piece of monitoring software if
necessary.
The program has to run on Vista so I got my first experience writing for
UAC.
I've worked though the signed manifest and all the other little quirky
stuff
I have to do to get my app to run as Administrator
(System.Directo ryServices
said it required admin rights) and everything is working just dandy.
But, I would also like to map drives for the user as I do this. Problem
is
that when I map the drive using the Admin split token privs, it actually
maps
the drive for the admin user, not the lower priv user token. So I see
that
it works, it reports that it works, even checking the existence of the
drive
letter work but the drive letters don't show for the end user.
Now for the weird $50 question.
Is there a way while my program is running under the Admin token to
execute
something as the user? Like open a cmd shell and run a simple net use
command?
I have this code running the mapping. Works great on XP, and works under
Vista but I just don't see the drives as the user on Vista. (comments
removed for space)
Dim myProcess As Process = New Process
myProcess.Start Info.FileName = "cmd.exe"
myProcess.Start Info.WindowStyl e = ProcessWindowSt yle.Hidden
myProcess.Start Info.CreateNoWi ndow = True
myProcess.Start Info.Arguments = "/C net use K: \\vail\vmdk /persistent:no"
myProcess.Start ()
myProcess.WaitF orExit(10000)
If System.IO.Direc tory.Exists(str Drive) Then
txtStatus.Text = txtStatus.Text & "->Success "
Else
txtStatus.Text = txtStatus.Text & "->Failed "
End If
Really hoping that made sense....