473,325 Members | 2,860 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes and contribute your articles to a community of 473,325 developers and data experts.

How to Generate a User List

ADezii
8,834 Expert 8TB
For this Tip, we will show you an extremely handy, multi-user, feature of Jet that allows you to manage Users more effectively. You can create a special, provider-specific Recordset in ADO that supplies information about the current Users in the Database. This is accomplished by using the OpenSchema() Method of the Connection Object, which will fill a recordset with varied sets of different Database Schema information. The output of this OpenSchema() Method will be written to a List Box (lstUsers) with the pre-defined headings of Computer, UserName, Connected?, and Suspect?.

I intentionally decided to display this Tip at this specific point in time because it is intimately related to the prior Tip, Passive Shutdown. They are both extremely helpful, multi-user, features that Jet 4 exposes, and they will greatly assist in the implementation of certain administrative tasks such as: Updates, Backups, etc. There will be certain instances when you, as the administrator of a multi-user Database, will want to be 100% sure that no Users are currently logged on to your back end database. Through the use of Passive Shutdown, when no additional Users will be allowed to log on, and the User List, which will display any currently logged on Users, you will be 100% guaranteed that no currently logged on individual will interfere with a critical process.

The code segment below will demonstrate how you can display this User List in a List Box on a Form. There are ample comments scattered through the code, but if you need any further explanation on any specific area, please feel free to ask.
Expand|Select|Wrap|Line Numbers
  1. 'The User List Schema information requires this magic number. For anyone
  2. 'who may be interested, this number is called a GUID or Globally Unique
  3. 'Identifier - sorry for digressing
  4. Const conUsers = "{947bb102-5d43-11d1-bdbf-00c04fb92675}"
  5.  
  6. Dim cnn As ADODB.Connection, fld As ADODB.Field, strUser As String
  7. Dim rst As ADODB.Recordset, intUser As Integer, varValue As Variant
  8.  
  9. Set cnn = CurrentProject.Connection
  10. Set rst = cnn.OpenSchema(Schema:=adSchemaProviderSpecific, SchemaID:=conUsers)
  11.  
  12. 'Set List Box Heading
  13. strUser = "Computer;UserName;Connected?;Suspect?"
  14.  
  15. With rst    'fills Recordset (rst) with User List data
  16.   Do Until .EOF
  17.     intUser = intUser + 1
  18.       For Each fld In .Fields
  19.         varValue = fld.Value
  20.           'Some of the return values are Null-Terminated Strings, if
  21.           'so strip them off
  22.           If InStr(varValue, vbNullChar) > 0 Then
  23.             varValue = Left(varValue, InStr(varValue, vbNullChar) - 1)
  24.           End If
  25.           strUser = strUser & ";" & varValue
  26.       Next
  27.         .MoveNext
  28.   Loop
  29. End With
  30.  
  31. Me!txtTotalNumOfUsers = intUser        'Total # of Users
  32.  
  33. 'Set up List Box Parameters
  34. Me!lstUsers.ColumnCount = 4
  35. Me!lstUsers.RowSourceType = "Value List"
  36. Me!lstUsers.ColumnHeads = False
  37.   lstUsers.RowSource = strUser       'populate the List Box
  38.  
  39. 'Routine cleanup chores
  40. Set fld = Nothing
  41. Set rst = Nothing
  42. Set cnn = Nothing
OUTPUT:
Expand|Select|Wrap|Line Numbers
  1. Computer     UserName  Connected?  Suspect?
  2. DEZII          Admin       True
  3. IGUANA           Suzanne     True
  4. LIZARD           Paul         True
  5. FINANCE            Leonard     True
Jul 29 '07 #1
30 36941
Does this only list users who are using the same front end MDB? Or will it list users who are using separate front end MDBs linked to the same backend MDB?
Jul 31 '07 #2
ADezii
8,834 Expert 8TB
Does this only list users who are using the same front end MDB? Or will it list users who are using separate front end MDBs linked to the same backend MDB?
In a Multiuser Environment, it will generate a list of Current Users who are logged on to the Back End Database from separate Front End MDBs linked to the same backend. This would be the most practical application.
Jul 31 '07 #3
jqwert
1
For this Tip, we will show you an extremely handy, multi-user, feature of Jet that allows you to manage Users more effectively. You can create a special, provider-specific Recordset in ADO that supplies information about the current Users in the Database. This is accomplished by using the OpenSchema() Method of the Connection Object, which will fill a recordset with varied sets of different Database Schema information. The output of this OpenSchema() Method will be written to a List Box (lstUsers) with the pre-defined headings of Computer, UserName, Connected?, and Suspect?.

I intentionally decided to display this Tip at this specific point in time because it is intimately related to the prior Tip, Passive Shutdown. They are both extremely helpful, multi-user, features that Jet 4 exposes, and they will greatly assist in the implementation of certain administrative tasks such as: Updates, Backups, etc. There will be certain instances when you, as the administrator of a multi-user Database, will want to be 100% sure that no Users are currently logged on to your back end database. Through the use of Passive Shutdown, when no additional Users will be allowed to log on, and the User List, which will display any currently logged on Users, you will be 100% guaranteed that no currently logged on individual will interfere with a critical process.

The code segment below will demonstrate how you can display this User List in a List Box on a Form. There are ample comments scattered through the code, but if you need any further explanation on any specific area, please feel free to ask.
Expand|Select|Wrap|Line Numbers
  1. 'The User List Schema information requires this magic number. For anyone
  2. 'who may be interested, this number is called a GUID or Globally Unique
  3. 'Identifier - sorry for digressing
  4. Const conUsers = "{947bb102-5d43-11d1-bdbf-00c04fb92675}"
  5.  
  6. Dim cnn As ADODB.Connection, fld As ADODB.Field, strUser As String
  7. Dim rst As ADODB.Recordset, intUser As Integer, varValue As Variant
  8.  
  9. Set cnn = CurrentProject.Connection
  10. Set rst = cnn.OpenSchema(Schema:=adSchemaProviderSpecific, SchemaID:=conUsers)
  11.  
  12. 'Set List Box Heading
  13. strUser = "Computer;UserName;Connected?;Suspect?"
  14.  
  15. With rst    'fills Recordset (rst) with User List data
  16.   Do Until .EOF
  17.     intUser = intUser + 1
  18.       For Each fld In .Fields
  19.         varValue = fld.Value
  20.           'Some of the return values are Null-Terminated Strings, if
  21.           'so strip them off
  22.           If InStr(varValue, vbNullChar) > 0 Then
  23.             varValue = Left(varValue, InStr(varValue, vbNullChar) - 1)
  24.           End If
  25.           strUser = strUser & ";" & varValue
  26.       Next
  27.         .MoveNext
  28.   Loop
  29. End With
  30.  
  31. Me!txtTotalNumOfUsers = intUser        'Total # of Users
  32.  
  33. 'Set up List Box Parameters
  34. Me!lstUsers.ColumnCount = 4
  35. Me!lstUsers.RowSourceType = "Value List"
  36. Me!lstUsers.ColumnHeads = False
  37.   lstUsers.RowSource = strUser       'populate the List Box
  38.  
  39. 'Routine cleanup chores
  40. Set fld = Nothing
  41. Set rst = Nothing
  42. Set cnn = Nothing
OUTPUT:
Expand|Select|Wrap|Line Numbers
  1. Computer     UserName  Connected?  Suspect?
  2. DEZII          Admin       True
  3. IGUANA           Suzanne     True
  4. LIZARD           Paul         True
  5. FINANCE            Leonard     True
Thank you for supplying the code above, can you give me some more information regarding the basics of setting it up. Do you need to place the code into a module? from which a list box named "1stUsers" placed on a form displays data from another table with the pre-defined headings of Computer, UserName, Connected?, and Suspect? Thanks you for any assistance you may be able to provide.
Nov 3 '07 #4
ADezii
8,834 Expert 8TB
Thank you for supplying the code above, can you give me some more information regarding the basics of setting it up. Do you need to place the code into a module? from which a list box named "1stUsers" placed on a form displays data from another table with the pre-defined headings of Computer, UserName, Connected?, and Suspect? Thanks you for any assistance you may be able to provide.
This is exactly how I would incorporate this functionality in my Database:
  1. Create a Form dedicated solely to the display of this User List. It should not serve any other function.
  2. Create a Private Sub Procedure in your Form and name it GenerateUserList. Copy and Paste the User List code to this Procedure as in:
    Expand|Select|Wrap|Line Numbers
    1. Private Sub GenerateUserList()
    2. 'The User List Schema information requires this magic number. For anyone
    3. 'who may be interested, this number is called a GUID or Globally Unique
    4. 'Identifier - sorry for digressing
    5. Const conUsers = "{947bb102-5d43-11d1-bdbf-00c04fb92675}"
    6.  
    7. Dim cnn As ADODB.Connection, fld As ADODB.Field, strUser As String
    8. Dim rst As ADODB.Recordset, intUser As Integer, varValue As Variant
    9.  
    10. Set cnn = CurrentProject.Connection
    11. Set rst = cnn.OpenSchema(Schema:=adSchemaProviderSpecific, SchemaID:=conUsers)
    12.  
    13. 'Set List Box Heading
    14. strUser = "Computer;UserName;Connected?;Suspect?"
    15.  
    16. With rst    'fills Recordset (rst) with User List data
    17.   Do Until .EOF
    18.     intUser = intUser + 1
    19.       For Each fld In .Fields
    20.         varValue = fld.Value
    21.           'Some of the return values are Null-Terminated Strings, if
    22.           'so strip them off
    23.           If InStr(varValue, vbNullChar) > 0 Then
    24.             varValue = Left(varValue, InStr(varValue, vbNullChar) - 1)
    25.           End If
    26.           strUser = strUser & ";" & varValue
    27.       Next
    28.         .MoveNext
    29.   Loop
    30. End With
    31.  
    32. Me!txtTotalNumOfUsers = intUser        'Total # of Users
    33.  
    34. 'Set up List Box Parameters
    35. Me!lstUsers.ColumnCount = 4
    36. Me!lstUsers.RowSourceType = "Value List"
    37. Me!lstUsers.ColumnHeads = False
    38.   lstUsers.RowSource = strUser       'populate the List Box
    39.  
    40. 'Routine cleanup chores
    41. Set fld = Nothing
    42. Set rst = Nothing
    43. Set cnn = Nothing
    44. End Sub
  3. Create a List Box on this Form and name it lstUsers. Set no properties for this List Box, they will be set programmatically. It's Name, however, must be lstUsers.
  4. Create a Text Box on the Form and name it txtTotalNumOfUsers.
  5. Set the Form's Timer Interval to 10000 (10 seconds). This can be readjusted later if you so desire.
  6. Place the following code in the Form's Timer() Event:
    Expand|Select|Wrap|Line Numbers
    1. Private Sub Form_Timer()
    2.   Call GenerateUserList
    3. End Sub
    4.  
  7. Place the following code in the Form's Open() Event:
    Expand|Select|Wrap|Line Numbers
    1. Private Sub Form_Open(Cancel As Integer)
    2.   Call GenerateUserList
    3. End Sub
  8. When you initially Open the Form the List Box will be populate with all the Users currently logged on to the Database and this List will be Refreshed every 10 seconds (Timer Interval = 10000 / Timer() Event call to GenerateUserList).
  9. If you have any further questions whatsoever on anything that I have outlined, please feel free to ask.
Nov 3 '07 #5
I was having trouble implementing this on my front end but then I figured it out! It has to be on the back end for this to work.

Thanks,
Chris
Dec 6 '07 #6
Randoz
27
This works great, thanks. But, why are all the UserNames "Admin"?
Dec 20 '07 #7
ADezii
8,834 Expert 8TB
This works great, thanks. But, why are all the UserNames "Admin"?
If you do not have a Security System in place all Users are defined as Admin with no Password. I'm assuming that this is your case.
Dec 20 '07 #8
Randoz
27
If you do not have a Security System in place all Users are defined as Admin with no Password. I'm assuming that this is your case.
Yes, that is the case, thanks for the help. At least I can get the computer name.
Dec 21 '07 #9
patjones
931 Expert 512MB
This works great, except that in addition to getting "Admin" for all the UserNames, I get something like "C05-4235" under Computer.

We use Novell NetWare Services to log in to our computers. Is there anyway that I can get it to display the Novell user name in the list box?

Thanks!
Feb 14 '08 #10
neosam
47
Hi there,

i created a macro wher in it pulls the data from an excel sheet (a report).

i got the data, but the problem is the output is scattered..

can anyone gimme a code to get the outputs aligned?

thanks
Apr 22 '08 #11
MarkH2
5
@zepphead80

Don't know if you still need this, but my project is the same, and with a bit of fiddling, I've got it sort of working. Huge thanks to ADezii for the original code.

The bits in bold are additional

Expand|Select|Wrap|Line Numbers
  1. 'Set List Box Heading
  2. strUser = "Computer;User;Connected?;Suspect?;ID"
  3.  
  4. With rst    'fills Recordset (rst) with User List data
  5.   Do Until .EOF
  6.     intUser = intUser + 1
  7.       For Each fld In .Fields
  8.         varValue = fld.Value
  9.           'Some of the return values are Null-Terminated Strings, if
  10.           'so strip them off
  11.           If InStr(varValue, vbNullChar) > 0 Then
  12.             varValue = Left(varValue, InStr(varValue, vbNullChar) - 1)
  13.           End If
  14.           strUser = strUser & ";" & varValue
  15.                 Next
  16.       strUser = strUser & ";" & GetUserName()
  17.         .MoveNext
  18.   Loop
  19. End With
  20. Me!txtTotalNumOfUsers = intUser        'Total # of Users
  21.  
  22. 'Set up List Box Parameters
  23. Me!lstUsers.ColumnCount = 5
  24. Me!lstUsers.RowSourceType = "Value List"
  25. Me!lstUsers.ColumnHeads = True
  26.   lstUsers.RowSource = strUser     'populate the List Box
It does leave it slightly messy with the Admin user still being displayed, but that doesn't matter for my purposes, so I've left it in.

The GetUserName() function I found elsewhere on the web, but not sure where, so can't acknowledge the original creator, however, it's not mine.

Expand|Select|Wrap|Line Numbers
  1. Public Function GetUserName()
  2.  
  3.       ' Buffer size for the return string.
  4.       Const lpnLength As Integer = 255
  5.  
  6.       ' Get return buffer space.
  7.       Dim status As Integer
  8.  
  9.  
  10.       ' For getting user information.
  11.       Dim lpName, lpUserName As String
  12.  
  13.       ' Assign the buffer size constant to lpUserName.
  14.       lpUserName = Space$(lpnLength + 1)
  15.  
  16.       ' Get the log-on name of the person using product.
  17.       status = WNetGetUser(lpName, lpUserName, lpnLength)
  18.  
  19.       ' See whether error occurred.
  20.       If status = NoError Then
  21.          ' This line removes the null character. Strings in C are null-
  22.          ' terminated. Strings in Visual Basic are not null-terminated.
  23.          ' The null character must be removed from the C strings to be used
  24.          ' cleanly in Visual Basic.
  25.          lpUserName = Left$(lpUserName, InStr(lpUserName, Chr(0)) - 1)
  26.         GetUserName = lpUserName
  27.         Exit Function
  28.       Else
  29.  
  30.          ' An error occurred.
  31.          MsgBox "Unable to get the name."
  32.          Exit Function
  33.          End
  34.       End If
  35.  
  36.       ' Display the name of the person logged on to the machine.
  37.       MsgBox "The person logged on this machine is: " & lpUserName
  38.    End Function
Hope that helps.
May 5 '09 #12
Stepan
1
Is it possible to generate a similar list with user permissions?
Jun 27 '11 #13
ADezii
8,834 Expert 8TB
I'm actually on Vacation now, Stephan, but when I return I'm sure that I can drum up some Code for you that will display Permissions for each User. Is this what ou are looking for?
Jun 28 '11 #14
Can someone please explain how to configure this to connect to my back end database?
Nov 2 '11 #15
I have figured that part out. Now I need to know why it shows my computers connection twice and all others only once. This happens from each computer you bring up the user list form.
Nov 2 '11 #16
ADezii
8,834 Expert 8TB
@Wesley:
Where, exactly, are you executing this Code from?
Nov 3 '11 #17
I have a form called Frm_Con_Users. The above code is executed in the Form_Load event and the Form_Timer event. The function which I call List_Users contains the above code and is also in the forms code container (not sure if I referenced that correctly).
Nov 3 '11 #18
ADezii
8,834 Expert 8TB
@Wesley:
Are you executing the Code from the Front or Back End DB?
Nov 3 '11 #19
From the front end. I want an "Administrator" to see who is connected, while using the Front End Database. I had to do some tweaking to get this code to recognize my back end db connection.
Nov 3 '11 #20
ADezii
8,834 Expert 8TB
@Wesley:
I could not duplicate your Error. Download the Attachment which I know works, then compare it to your configuration.
Attached Files
File Type: zip Generate User List.zip (19.3 KB, 805 views)
Nov 3 '11 #21
Thank you for the code and your time! The only difference between your form and mine are the connection properties. I am running my form from the Front End DB and connecting to the Back End DB using:
Expand|Select|Wrap|Line Numbers
  1.  cnn.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
  2.               "Data Source="
  3.  
I have determined the problem is because I have multiple forms open that open recordsets in the Back End DB.

Again, Thank you for your time. I will live with the current results.
Nov 3 '11 #22
ADezii
8,834 Expert 8TB
@Wesley:
You are quite welcome. You could actually write Code, parsing strUser and eliminating the Duplicates, since it is nothing more than a Semi-Colon Delimited String. Actually, assuming the Recordset is mirroring this Duplication, we should only process the Odd Number Rows and build strUser accordingly. I'm assuming the Even Rows would represent the Duplicates, but only you can test this for sure. Modify the GenerateUserList() Function slightly (Lines 12 and 14).
Expand|Select|Wrap|Line Numbers
  1. '*************************** Code Intentionally Omitted ***************************
  2. With rst    'fills Recordset (rst) with User List data
  3.   Do Until .EOF
  4.     intUser = intUser + 1
  5.       For Each fld In .Fields
  6.         varValue = fld.Value
  7.           'Some of the return values are Null-Terminated Strings, if
  8.           'so strip them off
  9.           If InStr(varValue, vbNullChar) > 0 Then
  10.             varValue = Left(varValue, InStr(varValue, vbNullChar) - 1)
  11.           End If
  12.           If intUser Mod 2 <> 0 Then     'Process ODD Rows only
  13.             strUser = strUser & ";" & varValue
  14.           End If
  15.       Next
  16.         .MoveNext
  17.   Loop
  18. End With
  19. '*************************** Code Intentionally Omitted *************************** 
  20.  
P.S. - This Logic is useless if the Duplication does not exist!
Nov 4 '11 #23
You got it! That omits the duplicate entry! Thanks again!!
Nov 4 '11 #24
ADezii
8,834 Expert 8TB
You are quite welcome, but remember that the Code is only applicable in your unique circumstance.
Nov 4 '11 #25
tgrace
3
This is GREAT... Really appreciate sharing all this info. The code works great for me (am using the updated code with GetUserName and ID)except when I test it with another User and I open the User List Form I will see 2 users on but with an ID showing myself twice. When I have the other user load the User List Form he sees himself twice. Very Odd.... We are opening the form in the back end.
Thanks for any assistance.........
Nov 10 '11 #26
ADezii
8,834 Expert 8TB
You are quite welcome, tgrace.
Nov 10 '11 #27
tgrace
3
Adezii..... Perhaps u did not read my entire content..... When I run the form it will show the total number of users in the back end but the ID (windows username) will all be mine on every line entry... Any thoughts? Thanks.....
Nov 10 '11 #28
ADezii
8,834 Expert 8TB
Any thoughts?
Unfortunately, I do not at the moment, and I have no means of simulating your conditions right now. I'll put my Thinking Cap back on and see what I can come up with.
Nov 10 '11 #29
tgrace
3
Thanks.... No problem... This is not time sensitive but am wondering if it has to do with the Citrix network that we are on. THanks again for responding so quickly.... Tim
Nov 10 '11 #30
kpus
1
This is FANTASTIC code. I too had the issue with needing to find out the users in a back end database. I attempted to use the code of:

cnn.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & GetLinkPath & ";"
However, my backend database is password protected.

My GetLinkPath code is:

Public Function GetLinkPath()
On Error GoTo Err_GetLinkPath

Dim tdf As TableDef

For Each tdf In CurrentDb.TableDefs
If tdf.Name = "tblCo" Then
GetLinkPath = Mid(tdf.Connect, 11)
End If
Next tdf
Set tdf = Nothing
Exit_GetLinkPath:
Exit Function

Err_GetLinkPath:
MsgBox "An '" & Err.Description & "' error occurred. ", vbOKOnly + vbCritical, "Error in GetLinkPath"
Resume Exit_GetLinkPath


This gets the password along with the table name, but i'm still getting "An 'Object variable or With block variable not set' error occurred.

Is anyone using this code to get a list of users, from a Front End database where the back end database is password protected?
Sep 14 '16 #31

Sign in to post your reply or Sign up for a free account.

Similar topics

5
by: glin | last post by:
Hi there, does anyone know how to use smarty to generate a selection list without PHP assigning a array? eg. a list for selection minutes, but without php to assign a 1~60 array into smarty. ...
1
by: The Blob | last post by:
Hi all, I have a problem trying to generate the u/m list of customer. I am trying to generate a list of customer whoes last commence date is jan 04 to current. It is part of a billing...
2
by: one | last post by:
greetings i am just wondering if some expert here can either show me how to do this or point me to the right direction (url... i want to use c# to generate a list of alphabet e.g A B C ... AA...
2
by: Joe User | last post by:
QUESTION for the experts out there :) Is it possible to write a query that would list the datafields by each table in a database? How would I do that?!?! TIA Joe
6
by: Dustin Wilson | last post by:
I'm looking for a way with Visual Basic to generate a list of all the forms, reports and modules within a database. I can currently generate a list of tables and queries with the following code...
12
by: one | last post by:
greetings i am just wondering if some expert here can either show me how to do this or point me to the right direction (url... i want to use c# to generate a list of alphabet e.g A B C ... AA...
2
by: Kim Bach Petersen | last post by:
Is it possible to generate a list of classes within a namespace? Fx as a function of the name of the namespace, returning an array or the like: Function GetClasses(strNamespace As String) As...
8
by: dohyohdohyoh | last post by:
I have a programming question to generate an ordered list of alphanumeric strings of length 4. two alphabets rest numberst, etc. EG 0000-9999 then A000-Z999 then AA00 to ZZ99 then AAA0 - ZZZ9...
10
by: =?utf-8?B?5Lq66KiA6JC95pel5piv5aSp5rav77yM5pyb5p6B | last post by:
Is there a simple function to generate a list like ? The range() just can generate the numeric list.
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.