|
|
Question : 97 Runtime problems in XP limited user account
|
|
We are having several problems with a 97 runtime application running in various XP environments when the user is a limited account. We are using Wise and the SageKey scripts to build the install, and everything works fine as long as the account used to install the program is the same account used to run it. But we have some clients who understandably want to do the install from one account and have the user run it from another account.
Our errors have included:
1. on startup, "can't be started - was unable to initialize the Windows registry" error (this occurs when Access XP is also installed) 2. on exit from app, "you do not have access to make the required system configuration modifications" (this occurs on limited user accounts in a client-server setup) 3. within app, 3027 error when reattaching to back end tables unless we are running from the same account that did the runtime install - even another admin account gets this error.
I think all of these issues probably have to do with the user not being able to update the registry. My questions are:
1. Are there people out there successfully running 97 runtime fe/be apps in XP limited user accounts? or is that too much to ask? 2. Is there a "run as" option or other workaround that consistently works? Our testing with "run as" has had problems, too.
I have not been successful at finding anything on the web which specifically addresses 97 runtime in a limited XP user environment.
Thank you.
|
Answer : 97 Runtime problems in XP limited user account
|
|
I have vb code that allows you to "run as" using win32 api very reliably, you could wrap it up as a vb exe and have users launch that (hopefully the same account as was used to install due to sage key settings etc creating Access user profiles in the registry) and that would use automation to launch your app. The only problem, or inconvenince is that you will need to have code that will terminate the VB app when you close your application because the vb app is waht crates the "Power User" context thread for your app to use, not really a big deal becasue it don't need to have a UI for the VB app but it is a bit more code.
I will post the api and hopefully you can modify to suit your needs, certainly post back if I can help with the bits and pieces.
Now that I think about it, you don't really need VB as the code would work just as well in any VBA host, be it Access, Excel, Word or AutoCAD.
Steve
ok ... next section of code goes into a new standard module ...
'------------------------------------------------------------------------------- ' Environment Option Explicit Option Base 0 '------------------------------------------------------------------------------- ' ' '------------------------------------------------------------------------------- ' Win32 API declarations Public Declare Function GetComputerNameEx Lib "kernel32.dll" Alias "GetComputerNameExA" (ByVal NameFormat As Long, ByVal Buffer As String, Size As Long) As Long Public Declare Function GetUserNameAPI Lib "advapi32.dll" Alias "GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long Public Declare Function LogonUser Lib "advapi32.dll" Alias "LogonUserA" (ByVal UserName As String, ByVal Domain As String, ByVal Password As String, ByVal LogonType As Long, ByVal LogonProvider As Long, Token As Any) As Long Public Declare Function ImpersonateLoggedOnUser Lib "advapi32.dll" (ByVal Token As Long) As Long Public Declare Function RevertToSelf Lib "advapi32.dll" () As Boolean Public Declare Function RegSaveKey Lib "advapi32.dll" Alias "RegSaveKeyA" (ByVal hKey As Long, ByVal lpFile As String, lpSecurityAttributes As SECURITY_ATTRIBUTES) As Long '------------------------------------------------------------------------------- 'Computer Name Format Public Const ComputerNameDnsDomain = 2 'LogonUser enumerations Public Const LOGON32_LOGON_INTERACTIVE = 2 'Public Const LOGON32_LOGON_NETWORK = 3 Public Const LOGON32_LOGON_BATCH = 4 'Public Const LOGON32_LOGON_SERVICE = 5 Public Const LOGON32_PROVIDER_DEFAULT = 0 Public Const LOGON32_PROVIDER_WINNT35 = 1 Public Const LOGON32_PROVIDER_WINNT40 = 2 Public Const LOGON32_PROVIDER_WINNT50 = 3 '------------------------------------------------------------------------------- 'SECURITY_ATTRIBUTES data structure used by RegSaveKey api Public Type SECURITY_ATTRIBUTES nLength As Long lpSecurityDescriptor As Variant bInheritHandle As Boolean End Type '-------------------------------------------------------------------------------
Public Function GetDomainName() As String Dim lLength As Long Dim lRet As Long GetDomainName = String$(255, vbNullChar) lLength = 255 lRet = GetComputerNameEx(ComputerNameDnsDomain, GetDomainName, lLength) If lRet = 0 Then 'return 0 indicates failure GetDomainName = "" Else 'return <> 0 indicates success, strip trailing null characters GetDomainName = Left$(GetDomainName, lLength) End If End Function '------------------------------------------------------------------------------- Public Function LogonAsUser(ByVal UserAlias As String, _ ByVal Domain As String, _ ByVal Password As String, _ ByVal LogonType As Long, _ ByVal LogonProvider As Long, _ Token As Long) _ As Long
Dim lngToken As Long
lngToken = LogonUser(UserAlias, "", Password, LogonType, LogonProvider, Token)
'assign return value LogonAsUser = Token
End Function '------------------------------------------------------------------------------- Public Function ImpersonateUser(ByVal Token As Long) As Boolean
If ImpersonateLoggedOnUser(Token) = 0 Then ImpersonateUser = False MsgBox "impersonation error=" & vbCrLf & Err.LastDllError Else ImpersonateUser = True End If
End Function '------------------------------------------------------------------------------- Public Function RevertUser() RevertToSelf End Function '------------------------------------------------------------------------------- Public Function GetUserName() As String Dim lRet As Long Dim lLength As Long GetUserName = String$(255, vbNullChar) lLength = 255 lRet = GetUserNameAPI(GetUserName, lLength) If lRet = 0 Then 'return of 0 indicates failure GetUserName = "" Else 'non-zero return indicates success GetUserName = Left$(GetUserName, lLength - 1) End If End Function '-------------------------------------------------------------------------------
and to use the impersonation you can pout this code anywhere you need to ...
Public Function KeySave() Dim strDomain Dim lngToken As Long
'get domain strDomain = GetDomainName
'logon as local admin lngToken = LogonAsUser(UserAlias:="admin", _ Domain:=strDomain, _ Password:="nimda", _ LogonType:=LOGON32_LOGON_INTERACTIVE, _ LogonProvider:=LOGON32_PROVIDER_WINNT50, _ Token:=lngToken) If lngToken = 0 Then MsgBox "unable to logon as admin" End If
'impersonate admin If ImpersonateUser(lngToken) = False Then MsgBox "unable to impersonate admin" End If
'this is where you would create a new instance of an Access.Application Set accApp = New Access.Application ..... do you thing here to open it.....
and for the final piece ... you could skip but I like to keep things clean ... in Unload event, close event
... 'revert to logged on user's context Call RevertToSelf
|
|
|
|
|