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
Random Solutions  
 
programming4us programming4us