jtokach
(Seasoned Scripter)
2002-01-16 06:29 PM
Create/Read/Update MS Access Database

Not be repetative, but I require info on how to create, read, and update an MS Access DB using the new features of Kix 2001 ONLY. I think it would be helpful for all to have an updated source for this information.
(I have searched through the board, and have found that there is indeed a lot of information on this subject. However, a great deal of this info is sort of outdated or requires a ver of kix other than 2001. There are also several methods that accomplish this, making finding the right one difficult...)

I also have a question regarding record/file locking. Using this newer method, can several people update the DB simultaneously? Are records locked or is the entire DB locked while updating?

Alex.H
(Seasoned Scripter)
2002-01-16 08:01 PM
Re: Create/Read/Update MS Access Database

You should get a look here :
Connect to any database with ADO

To connect to an Access db, use this informations (ODBC is used) :
$AdoCon.Provider = "MSDASQL"
$AdoCon.Properties("DSN")="ODBC dsn"
$AdoCon.Properties("UID")="userName"
$AdoCon.Properties("PWD")="password"
$AdoCon.Open
The odbc dsn must be defined through the ODBC icon in the windows control panel (in administratives tools for w2k and XP)

I'm not sure this one will work.

For the record locking, all user can update the DB simultaneously, only if they're :
adding a new entry
changing a single entry that won't be changed by another user

In fact, only the record(s) that had to be changed will be locked for write. all other will be available, and the locked one will only be here for read-only purposes

ShawnAdministrator
(KiX Supporter)
2002-01-16 08:08 PM
Re: Create/Read/Update MS Access Database

Hey jtokach (what`s your first name ?)

Guess we can start at the beginning, how to dynamically define and create a new MS Access table:

1) Go into MS Access and create a new database, call it DB1.MDB

2) Run the following script that will create a table called JTOKACH in DB1.MDB that contains like a small address book schema. Don`t forget to change $DATABASE to point this script to your new database. Hope this is the kind of information you were looking for.


Break On


$=SetOption("wrapateol","on")


$DATABASE = "C:\ACCESS\DB1.MDB" ; <--- change this


$DSN = "DATA SOURCE=$DATABASE; PROVIDER=MICROSOFT.JET.OLEDB.4.0;"


$SQL = "CREATE TABLE JTOKACH (NAME CHAR(50) PRIMARY KEY, ADDRESS CHAR(50), PHONE CHAR(20))"


$Connection = CreateObject("ADODB.Connection")


If $Connection
$Connection.ConnectionString = $DSN
$Connection.Open()
$=$Connection.Execute("$SQL")
If @ERROR
?"@SERROR"
Else
?"Table successfully created."
Endif
$Connection.Close()
$Connection = 0
Else
?"ADODB is not installed on this machine"
Endif


Exit 1

-Shawn

[ 16 January 2002: Message edited by: Shawn ]

**DONOTDELETE**
(Lurker)
2002-01-19 12:32 AM
Re: Create/Read/Update MS Access Database

Shawn

is there any quick way to define the Access workgroup to use.

TIA

jtokach
(Seasoned Scripter)
2002-01-18 05:55 PM
Re: Create/Read/Update MS Access Database

First off, let me thank you for offering your help; I greatly appreciate it. I have tried to send this message to you several times but I don't know if you got it.

My programming abilities are limited to kix and batch files. I am well advanced in both, however I trip when confronted with anything OLEish. With that in mind, I can most certainly lookup on the msdn site all of this information that I require, however, I don't know how to tie the two together. I would very much like to make this a BBS project as you offered! I believe that it would be a great service to myself and others to be able to follow the natural progression of learning this advanced topic from a beginners point of view. I would be happy to do homework and figure some things out on my own.

With all of that in perspective, here it what I would like to accomplish. General Network Engineer/Admins like myself are not well pronounced in programming languages. So we need to make up for this deficiency by using a simpler tool to create the same end effect. Enter Kix. I would like to create a script that runs during the logon that creates, adds or updates records in a database. The primary key will be the hostname of the box. The DB will be flat as relational DBs confuse the hell out of me. We can modify this later I suppose with little impact. The fields will include info such as C: free space, last logon time, current DAT file, etc. We have about 20-30 fields we would like to capture and already have the code to capture them. The requirements are this:

Must be a database. CSV and XLS are far to limited in their abilities.
Must be able to be written to by several users at once. Record locking only, not file locking.
Records should be updated, not overwritten?
The updating process should be as quick as possible.

Given all of that, I have tried your script and it worked flawlessly. However, I have no idea what the code is doing. Can you explain line by line what's happening so that I can learn from this and write my own stuff?

Also, where can I find info on the parameters of the SQL command you used so that I can create more elaborate fields; like how to create a combo box instead of a text field or change the data type from CHAR to YES/NO or NUMBER?


Again, THANK YOU!

ShawnAdministrator
(KiX Supporter)
2002-01-18 06:53 PM
Re: Create/Read/Update MS Access Database

There are really four things (diciplines) to this whole kix oledb thingy:

1) How to use kixtart to talk to COM objects (access,excel,ie,adsi,etc).

2) Understanding the OLEDB object model. Which isn't necessary tied to just Microsoft Access, you can talk SQL to Oracle, SQL7, Foxpro and a host of others. It's a generic object model for interfacing with any DB that provides a driver.

3) Understanding SQL. We use the OLEDB object to establish connections and retrieve recordsets, but formulating SQL queries is a huge subject in itself (not to mention any Access specific extentions to the standards).

4) Understanding how to Automate Microsoft Access (the application). It's easy to confuse the two (automating queries vs automating the app that services the queries). Automating the app (building forms and databases (not tables), changing settings and customizing the GUI is something I would suggest is out of scope and usually not required. One would normally just manually start the app and customize the gui that way.

So having said all that, where would you like to start ? (Whew)

-Shawn

jtokach
(Seasoned Scripter)
2002-01-18 07:01 PM
Re: Create/Read/Update MS Access Database

Shawn,
Step 1 - Understanding COM objects and their usage.

I assume this should build a foundataion from which to build upon varying object models. I really don't know how build the code or can't really understand the pre-written code to interpret its usage...

-Jim

ShawnAdministrator
(KiX Supporter)
2002-01-18 09:18 PM
Re: Create/Read/Update MS Access Database

Ok, that makes sense. Good place to start.

Sometimes it helps to have an abstract mental picture of how things work. I'll tell you my mental picture in terms of how KiXtart COM works. I think of COM objects as sort of like smart DOS programs. For example, lets say you wanted to add a new user account to your local workstation. There are two ways to do it in kixtart:

1) Shell-out to the NET command
2) Use the ADSI COM object

So looking at the first method, we would code:

shell "%comspec% /c net user john.doe /add"

and what happens here ? net.exe is loaded into memory and run. net.exe then queries the command line for the parameters passed to it then simply creates the account. Then it exits, the process is unloaded from memory and your kixtart script carrys on. Pretty basic stuff eh ? If you wanted to create another user, you would have to shell out again and create another running instance of net.exe and so it goes, again and again. And the only way to communicate with these programs (specify what we want done) is with commandline parameters on the inbound side. And to extract information on the outbound side, use temporary textfiles and read them back into our script. You know the whole story

With COM, things are a little different. Instead of shelling-out and running the program every time you need it, you create an instance of the running program that is always "running" in the background, waiting at all times to recieve (service) our requests. And sending information in and out of the "program" is handled much, much more eloquently. Oh yeah, and instead of calling them programs, we call them objects

So with COM, instead of using the SHELL command, we use a kixtart function called CreateObject("progid"). For example, if I wanted to create a running instance of Internet Explorer, I would code this:

$IE = CreateObject("InternetExplorer.Application")

This one function does a whole lot. Here's the blow-by-blow play (might want to start regedit for this):

1) COM first looks in the registry for a key in HKEY_CLASSES_ROOT called "InternetExplorer.Application" (try it yourself manually to see if you can find it). If you crack open that key, there's a key called a CLSID which is basically an unique identifer for this application. Every COM object has one and they are all differnet from one another. They have to be or else COM couldn't locate your object. The string "InternetExplorer.Application" is just like a shortcut, or a friendly name for the object.

2) If you select this key into your clipboard, then go back up to the top and select HKEY_CLASSES_ROOT again, then do a find on this identifier, it should take you to a very strange place in the registry where all the identifiers are kept. Crack it open and look for LocalSever32 - whats the value there ? Look familiar ?

3) So then COM starts Internet Explorer but it puts it into a mode where it is continually running, in the background. If you look at taskmgr, you will see iexplore.exe running. So like using the SHELL command, CreateObject() just starts the program. But then here's where the fun starts.

So now iexplore.exe is running in the background, along side your kix script and it's just waiting for requests (from your script). How does one talk to the object ? Well if you remember, the CreateObject() function returns a variable, here it is again:

$ie = CreateObject("InternetExplorer.Application")

What is $ie ? $ie is a pointer to your running instance of Internet Explorer that you just created. It's like a channel or a pipe to the process (proper term is an address to an interface). Sometimes for whatever reason, the object your trying to create doesn't get created. We can test for this by querying the value of the pointer like this:

$ie = CreateObject("InternetExplorer.Application")
If $ie = 0
?"Some error occurred"
Endif

CreateObject() will either return the address of the object, or return a 0 (zero) if it fails. Try creating an object that doesn't exist and see what i mean. So this object pointer or interface pointer, in simple terms, consists of the following two things:

1) Properties
2) Methods


Properties are "attributes" of the currently running object. The syntax is like this:

Setting a property:

$objectname.propertyname = 1

Querying a property:

$kixvariable = $objectname.propertyname ; query a property

So we can set these attributes and/or we can query them. For example, IE has a property called "Visible" that tells wether the browser window is actually visible to the user or not (by default, when you create an IE object, it is *not* visible). I tend to think of properties as simply variables maintained by the object, inside the object itself. And in order for us to get at them, we have to specifically ask the object to set or get them for us. So, to make IE visible we must "set the Visible property", in this case to TRUE (1)

$ie = CreateObject("InternetExplorer.Application")
$ie.visible = 1

So not only does IE set it's internal variable "Visible" to 1 (on our behalf), it actually went ahead and made itself visible. So now that its visible, we can query the value of this property (read it back in) to see if it really did set it.

If $ie.Visible = 1
?"Yup, it is..."
Endif

or, since the value 1 is "true", we could just as easily code it this way:

If $ie.Visible
?"Yup, it is..."
Endif

Methods calls are simply function calls that you can invoke within the running instance of IE. The syntax of invoking a method call is like this:

$objectname.methodname(parm1,parm2,...)

So for example, continuing our IE script:

$ie = CreateObject("InternetExplorer.Application")

$ie.navigate("http://www.kixtart.org")

so we have just told IE to navigate to the best little KiXtart board on the Internet. There just like any other function call, but they are implemented inside the object.

And since the IE object is always running in the background, we need a way to stop it. We do that in kixtart like this:

$ie.quit() ; another method call - gracefully closes the browser
$ie = 0

Just set the variable to 0 (zero). What that does is to stop the running instance of iexplore.exe and unload it from memory.

So here's our little example script in it's full form:

break on
$ie = CreateObject("InternetExplorer.Application")
$ie.visible=1
$ie.navigate("http://www.kixtart.org")
gets$ ; just pause for now
$ie.quit
$ie = 0


My fingers hurt

-Shawn

[ 18 January 2002: Message edited by: Shawn ]

MadDawgMike
(Fresh Scripter)
2002-01-18 10:30 PM
Re: Create/Read/Update MS Access Database

Shawn,
You are AWESOME !! Please, please, please keep it up!!! I have learned more about this subject here (or at least Understood more...) than ever.

Thanks again!
Mike

Alex.H
(Seasoned Scripter)
2002-01-18 11:29 PM
Re: Create/Read/Update MS Access Database

And so God ... hem... Shawn speaks
Shawn, put yours hands in cold water, after in hot one, and restart typing


jtokach
(Seasoned Scripter)
2002-01-19 12:09 AM
Re: Create/Read/Update MS Access Database

You should charge! That was the most informative 10 minutes of my tech career! And it was so simple...

I can conclude that I can find the various properties and methods for any given application from a website, say MSDN. I have access to Visual Studio where I have seen these but I don't remember seeing an explanation of what they do. I think I can scrounge up a copy of the MSDN Library if that will help. Do you have any useful links?

Again that was phenomenal. Lesson 2 here we come! Have a nice weekend all!

Bryce
(KiX Supporter)
2002-01-19 01:01 AM
Re: Create/Read/Update MS Access Database

For ADSI I use the ADSI SDK that you can get here 3rd option down.

Bryce

New Mexico Mark
(Hey THIS is FUN)
2002-01-19 03:38 AM
Re: Create/Read/Update MS Access Database

Good job, Shawn.

If I were to recommend any one book on scripting, it would be "Windows Scripting Secrets" by Weltner.

His approach is both practical and fun. While he primarily uses VBScript, with KiXtart's new features, most scripts translate pretty easily. Almost all his scripts are oriented toward either exploring resources or accomplishing real administrative tasks.

One of the cooler things he explores is how to dump properties from objects. The nice thing about this is that any documentation on a particular object always seems to be a day late and a dollar short. By digging into the objects themselves with a few simple scripts, you can find out what features (say) IE 6.x has added. The core properties and methods will stay pretty much the same, but you will often find some very cool undocumented features -- and in this case I don't mean bugs.

New Mexico Mark

Breaker
(Hey THIS is FUN)
2002-01-22 07:08 PM
Re: Create/Read/Update MS Access Database

Evening, all.

I've been lurking on the edges of this board for a few months now - so some rather belated thanks are due to Shawn, Bryce, CJ and others. Cheers!

My first post has been occasioned by trying to get my head around COM/OLE with Kix2001 - I can see its caused others some stress as well , so I figured you were the guys to turn to.

I'm basically trying to write logon info to an Access 2000 database. There are two separate tables, one for user-related info, and one for machine-related. Based on Shawn's code earlier in this thread, I'm simply executing two SQL statements like this:

code:
 $SQL1 = "INSERT INTO TBL_USERS (USERNAME,FULLNAME,WORKSTATION,PRIVILEGELEVEL,HOMEDRIVE,LASTUPDATE) VALUES ('@USERID','@FULLNAME','@WKSTA','@PRIV','@HOMESHR','@DATE @TIME');"
$SQL2 = "INSERT INTO TBL_COMPUTERS (WORKSTATION,DOMAIN,IPADDRESS,MACADDRESS,OS,LOGGEDONUSER,LASTUPDATE) VALUES ('@WKSTA','@DOMAIN','@IPADDRESS0','@ADDRESS','@PRODUCTTYPE','@USERID','@DATE @TIME');"

Now the first statement works fine. However the second produces the following error:

Error: COM exception error "Execute" (Microsoft JET Database Engine - Syntax error in INSERT INTO statement.) [1/1]

I've been banging my head against this for a couple of hours now, so any advice would be appreciated.

Thanks in advance,

Breaker
(Hey THIS is FUN)
2002-01-22 07:48 PM
Re: Create/Read/Update MS Access Database

Hmmm....

Well, I've resolved the issue, though I have no idea why it should have been a problem.

After testing each field individually, it turned out that DOMAIN was causing the problem. Renaming that particular field to NTDOMAIN seems to have done the job.

Maybe some kind of Access OLE naming constraint...? Glad I'm not a proper programmer...!!

G'night, y'all.

ShawnAdministrator
(KiX Supporter)
2002-01-22 08:03 PM
Re: Create/Read/Update MS Access Database

Breaker,

This is waht I do when I get into a KiXtart
SQL bind:

Within Microsoft Access (2000):

1) Bring up the Dialog box that has the
menus for Tables, Queries, Forms, etc.. Know what I mean ?

2) Select the Queries "button"

3) Select "New" from the menu

4) Select "Design View"

5) Select your troublesome table
(TBL_COMPUTERS?) and "Add" and "Close"

6) In the main MS Access menubar,
select "View" and "SQL View"

7) This is an emmediate mode SQL query
builder. Paste your select statement from
the script into this window, then make
some adjustments like pluggin some dummy data for values list, etc ... then close the
window, give your query a name then execute
it.

This is a real handy way to formulate and
tryout (debug) queries before using them in
your script ... give it a go ... apoligies
if you've already tired this !

-Shawn

cj
(MM club member)
2002-01-23 03:46 AM
Re: Create/Read/Update MS Access Database

Breaker, I found the same problem with a column called DATE. I spent probably as long as you did until I put a "j" in front of all the column names in desperation. jDATE worked.

I suspect that you are right in that there are reserved words that you can't use, like Domain and Date etc.

cj

p.s. Welcome to the board!

Breaker
(Hey THIS is FUN)
2002-01-23 02:57 PM
Re: Create/Read/Update MS Access Database

CJ,

Yep, that's right. You can go here for a full(ish!) list of the reserved words:

SQL reserved word list

Thank you for the response.

Now I just have to figure out how to tie in the rest of this stuff my boss wants.... I suspect I'll be back again soon!

Radimus
(KiX Supporter)
2002-01-23 03:12 PM
Re: Create/Read/Update MS Access Database

Thanks Shawn...
I have been writing these little scripts for a while now, and still had no idea what it was doing or how it worked (I apparently still believe in magic, or cut and paste )

Keep 'em coming.

Perhaps this type of thread could be incorporated into the manual... RTFM only works if there is something in the FM to R

jtokach
(Seasoned Scripter)
2002-01-23 06:46 PM
Re: Create/Read/Update MS Access Database

Shawn,

Seems to be a popular subject! Anyway, moving along... I think I'm ready to start scripting. How do I go about adding new records and updating old records? Is the SQL the same for both? How does the SQL know to update an existing record rather than write a new one? Your DB1.MDB should make for a fine example.

Thanks!

-Jim

Breaker
(Hey THIS is FUN)
2002-01-23 07:42 PM
Re: Create/Read/Update MS Access Database

Question for Shawn,

What are the constraints of the code you've demonstrated above? I can pretty much see how that works, but how much differentiation between my desktops would it take into account without any modification?

I'm dealing with 95/98/Me/NT4.0/2000 on the desktop, most of which run Access 97 - but some will have Access 2000, and some won't have Access at all. Do I need a consistent set of components (ADO, Access, MDAC, etc) on each desktop?

I ask because while testing the script on an NT4.0 box with Access 97 (I'm working on Win2k, Office2k) the $Connection.Open() method call fails. Should there be a different provider specified in the $DSN variable? Or am I being incredibly stupid? (It wouldn't be the first time...)

Yours increasingly-frustratedly,

Breaker

ShawnAdministrator
(KiX Supporter)
2002-01-23 08:01 PM
Re: Create/Read/Update MS Access Database

Breaker

Two things you might check for:

1) Check for the existence of the key "ADODB.Connection" in HKEY_CLASSES_ROOT

2) If yes, might have to create a DSN for the connection. Look in Control Panel for the ODBC Data Sources applet and have a quick boo.

Let me know what you find.

-Shawn

Breaker
(Hey THIS is FUN)
2002-01-23 08:13 PM
Re: Create/Read/Update MS Access Database

Shawn,

Wow! Quick draw response - thanks. In answer to your queries:

1. ADODB.Connection is present in the registry.

2. On my NT box there is no Access DSN specified. So I have created one - but I am still getting the same error.

I'm not really sure where the problem might lie. Any ideas?

Thanks in advance,

Breaker

ShawnAdministrator
(KiX Supporter)
2002-01-23 08:33 PM
Re: Create/Read/Update MS Access Database

What do you get when you display the error message to the console ?

...

$=SetOption("wrapateol","on") ; see big msgs

$Connection.Open()

?"@ERROR; @SERROR"

-Shawn

ShawnAdministrator
(KiX Supporter)
2002-01-23 09:33 PM
Re: Create/Read/Update MS Access Database

Hey Breaker,

How about trying this $DSN

$DSN="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DATABASE"

Im in a bummer mood ... nothing to do with this thread ...

-Shawn

Breaker
(Hey THIS is FUN)
2002-01-24 03:26 PM
Re: Create/Read/Update MS Access Database

Shawn,

The error message receieved when executing the Open() method is:
COM Exception error "Open" (ADODB.Connection - ADO could not find the specified provider.) [1/1]

I've checked the registry, and although I can find ADODB.Connection under HKCR, there's no sign of the Microsoft.Jet.OLEDB.4.0, only Microsoft.Jet.OLEDB.3.51. I think this is the difference between Access versions installed.

Testing with the new value for the $DSN you suggested gives the error:

COM exception error "Open" (Microsoft OLE DB Provider for ODBC Drivers - [Microsoft][ODBC Microsoft Access 97 Driver] Can't open database '(unknown)'. It may not be a database that your application recognises, or the file may be corrupt.)[1/1]

However, upgrading the test system to Access 2000 allows both the suggested values for $DSN to work OK. I suspect the problem is that the native database format for Access 2000 is not recognised by Access 97.

So, recreating the database in Access 97 and using the native Microsoft Access Driver DSN is doing the trick. At least now all my workstations (with Access installed) will write to the database. Now I need to test what components I should install on my non-Access workstations to allow them to write info as well, I'm not even sure if this will be possible.

Before I came across this thread I was planning to run a scheduled script daily or weekly to parse the text files that my current production script generates, and import that into a database. Obviously I have been seduced by the COM/OLE Dark Side ("You don't know the power of the Dark Side!") and would prefer to write directly to the database and cut out the text files altogether, but this may require a degree of sophistication that I fear is beyond me.

At least I'm getting somewhere now - many many thanks go to Shawn for his patience and persistence with us lesser mortals. When I finally get this finished, I'll post the whole thing here for all to see and deride at their leisure. Hopefully that'll be next week, if I don't get swamped by other stuff.

A Bientot, mes amis!

Breaker
(Hey THIS is FUN)
2002-02-05 02:06 PM
Re: Create/Read/Update MS Access Database

Well, it took long enough (the suspected swamping by other stuff did indeed take place!) but here is the final script that is now happily collecting info from my network and merrily keeping my inventory database right up-to-the-minute.

In the end I decided to start playing with WMI as well to pull info, and credit goes to Radimus and Kent for the WMIQuery UDF, which gets a fair outing. I have since expanded the working version to pick up some other WMI info, but this is the basic code. Hopefully it'll save someone else from the same headbanging that a few people seem to have gone through in pursuit of a similar outcome...

Shawn and others - many thanks for all your advice on this. I'm sure I'll be back soon - AD is creeping nearer!

Breaker

code:
 ;WMI script to write info to database at logon
;Created Feb 2002 by Neil Moran

Break On
CLS

;Time script execution
;? @TIME

;Query WMI to obtain info not available through standard KiXtart macros
;Many thanks to the authors of the WMIQuery UDF for this - two gents known as Radimus and Kent
FUNCTION WMIQuery($what,$where,)
dim $strQuery, $objEnumerator, $value
$strQuery = "Select $what From $where"
$SystemSet = GetObject("winmgmts:{impersonationLevel=impersonate}!//@WKSTA")
$objEnumerator = $SystemSet.ExecQuery($strQuery)
For Each $objInstance in $objEnumerator
If @Error = 0 and $objInstance <> ""
$x=execute("$$value = $$objInstance.$what")
$WMIQuery="$value"+"|"+"$WMIQuery"
EndIf
Next
$WMIQuery=left($WMIQuery,len($WMIQuery)-1)
exit @error
ENDFUNCTION

;Retrieve info by calls to WMIQuery() function
$SystemManufacturer = WMIQuery("Manufacturer","Win32_ComputerSystem")
$SystemModel = WMIQuery("Model","Win32_ComputerSystem")
$SerialNo = WMIQuery("SerialNumber","Win32_BIOS")
$PhysicalMemory = val(WMIQuery("TotalPhysicalMemory","Win32_LogicalMemoryConfiguration"))/1024
$ProcessorSpeed = WMIQuery("CurrentClockSpeed","Win32_Processor") + " Mhz"
$PagefileSpace = val(WMIQuery("TotalPageFileSpace","Win32_LogicalMemoryConfiguration"))/1024

;Enumerate all disk info into arrays, then cross-reference for required info
$arrDeviceIDs = Split(WMIQuery("DeviceID","Win32_LogicalDisk"),"|",-1)
$arrFreeSpaces = Split(WMIQuery("FreeSpace","Win32_LogicalDisk"),"|",-1)
$arrTotalSizes = Split(WMIQuery("Size","Win32_LogicalDisk"),"|",-1)
$arrFormats = Split(WMIQuery("FileSystem","Win32_LogicalDisk"),"|",-1)

For $Counter = 0 To UBound($arrDeviceIDs)
If $arrDeviceIDs[$Counter] = "C:"
$C_DriveFormat = $arrFormats[$Counter]
$C_DriveFreeSpace = $arrFreeSpaces[$Counter]
$C_DriveTotalSize = $arrTotalSizes[$Counter]
$Counter = UBound($arrDeviceIDs) + 1
Endif
Next

;Sort the returned disk spaces values into MB
;$C_DriveFreeSpace = Val($C_DriveFreeSpace)/1048576
;$C_DriveTotalSize = Val($C_DriveTotalSize)/1048576

;First, set variables for the connection to the database and other general options
$=SetOption("WrapAtEOL","On")

$DATABASE = "\\corpfs01\rollout$$\logon.mdb"
$DSN="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DATABASE"

;Create SQL statements to check/write/update database
$CHECK_ENTRY_USERS = "SELECT * FROM TBL_USERS WHERE USERNAME='@USERID';"
$CHECK_ENTRY_COMPUTERS = "SELECT * FROM TBL_COMPUTERS WHERE WORKSTATION='@WKSTA';"

$Connection = CreateObject("ADODB.Connection")
$Command = CreateObject("ADODB.Command")
$Recordset = CreateObject("ADODB.Recordset")

;Check for connection object
if $Connection

;Open connection to database
$Connection.ConnectionString = $DSN
$Connection.Open()

;Check for existing records for the current workstation/user
;Add new record or update existing as required

;Check for User details first
$Command.ActiveConnection = $Connection
$Recordset.CursorType = 3
$Recordset.LockType = 3
$Recordset.ActiveCommand = $Command
$Command.CommandText = $CHECK_ENTRY_USERS
$Recordset.Open($Command)

;Create new record if none exists to update
If $Recordset.RecordCount < 1
$Recordset.AddNew
Endif

;Write user values into database field by field
$Recordset.Fields("UserName").Value = @USERID
$Recordset.Fields("FullName").Value = @FULLNAME
$Recordset.Fields("Workstation").Value = @WKSTA
$Recordset.Fields("PrivilegeLevel").Value = @PRIV
$Recordset.Fields("HomeDrive").Value = @HOMESHR
$Recordset.Fields("LastUpdate").Value = @DATE + " " + @TIME

;Update the new record and close the recordset object
$Recordset.Update
$Recordset.Close()

;Check Computer details next - refresh $Recordset object with new query
$Command.CommandText = $CHECK_ENTRY_COMPUTERS
$Recordset.Open($Command)

;Check for existing record to update
If $Recordset.RecordCount < 1
$Recordset.AddNew
Endif

;Write values into table
$Recordset.Fields("Workstation").Value = @WKSTA
$Recordset.Fields("NTDomain").Value = @DOMAIN
$Recordset.Fields("SystemManufacturer").Value = $SystemManufacturer
$Recordset.Fields("SystemModel").Value = $SystemModel
$Recordset.Fields("SerialNo").Value = $SerialNo
$Recordset.Fields("IPAddress").Value = @IPADDRESS0
$Recordset.Fields("MACAddress").Value = @ADDRESS
$Recordset.Fields("OS").Value = @PRODUCTTYPE
$Recordset.Fields("ServicePack").Value = @CSD
$Recordset.Fields("PhysicalMemory").Value = $PhysicalMemory
$Recordset.Fields("ProcessorSpeed").Value = $ProcessorSpeed
$Recordset.Fields("PagefileSpace").Value = $PagefileSpace
$Recordset.Fields("C riveFormat").Value = $C_DriveFormat
$Recordset.Fields("C riveFreeSpace").Value = $C_DriveFreeSpace
$Recordset.Fields("C riveTotalSize").Value = $C_DriveTotalSize
$Recordset.Fields("LoggedOnUser").Value = @USERID
$Recordset.Fields("LastUpdate").Value = @DATE + " " + @TIME

;Update and close recordset object
$Recordset.Update
$Recordset.Close()

;Close connection to database
$Connection.Close()

;Tidy up by releasing COM objects from memory
$Connection = 0
$Recordset = 0
$Command = 0
else
Goto error
endif

:end
;? @TIME
exit 321

:error
exit


Apologies if this isn't readable.

Radimus
(KiX Supporter)
2002-02-05 02:17 PM
Re: Create/Read/Update MS Access Database

You are more than welcome to code and I'm glad you could use it...

Especially, since I was looking to convert my current inventory (in CSV format) into an access MDB format...



Kdyer
(KiX Supporter)
2002-02-05 03:49 PM
Re: Create/Read/Update MS Access Database

Rad,

What you need to do now is create an ASP Page that queries this data back to your Intranet..

- Kent

[ 05 February 2002: Message edited by: kdyer ]

ShawnAdministrator
(KiX Supporter)
2002-02-05 04:03 PM
Re: Create/Read/Update MS Access Database

That actually reminds me of another way to collect login telemetry. Setup an asp or cgi script on a Web Server and use IE to send (post) telemetry data to the page during login ... Paul Berquam and (I think) CJ were working on such a scheme once ... nice thing about this approach is that minimal stuff (components) is required on the workstation - and no sticky issues surrounding privs and rights are involved. Just another way to skin this cat I guess.

-Shawn

Breaker
(Hey THIS is FUN)
2002-02-05 04:14 PM
Re: Create/Read/Update MS Access Database

Of course, for this code to work properly, you do need to have the requisite ADO/WMI components available on all your workstations. This isn't really a problem as such, though...

Radimus
(KiX Supporter)
2002-02-05 06:18 PM
Re: Create/Read/Update MS Access Database

I have a problem with this...

It connects, does this...

code:

If $Recordset.RecordCount < 1
? "adding record"
$Recordset.AddNew
Endif

There are no errors, but also no data.

I made a DB and pointed the script to the right place, made 2 tables; TBL_USERS and TBL_COMPUTERS, then made the columns as specified here

code:

$Recordset.Fields("UserName").Value = @USERID
$Recordset.Fields("FullName").Value = @FULLNAME
$Recordset.Fields("Workstation").Value = @WKSTA
$Recordset.Fields("PrivilegeLevel").Value = @PRIV
$Recordset.Fields("HomeDrive").Value = @HOMESHR
$Recordset.Fields("LastUpdate").Value = @DATE + " " + @TIME


and so for the computer table

Are the com commands for access2000 different?

Breaker
(Hey THIS is FUN)
2002-02-05 06:25 PM
Re: Create/Read/Update MS Access Database

Radimus,

I've had no difference in behaviour between systems with Access 97 or 2000, or even without Access at all, since the "Microsoft Access Driver" File DSN is installed by default on all Win32 OSes (someone correct me on this if it's just a wild generalisation!)

If you post the full code you're trying to use it might be easier to spot anything amiss... I'll try to help if I can.

Radimus
(KiX Supporter)
2002-02-05 06:35 PM
Re: Create/Read/Update MS Access Database

basically it is your code almost verbatim... with the DB name changed to protect the innocent. I figured once I make it work then I can customize it.

code:

Break On

;Retrieve info by calls to WMIQuery() function
$SystemManufacturer = WMIQuery("Manufacturer","Win32_ComputerSystem")
$SystemModel = WMIQuery("Model","Win32_ComputerSystem")
$SerialNo = WMIQuery("SerialNumber","Win32_BIOS")
$PhysicalMemory = val(WMIQuery("TotalPhysicalMemory","Win32_LogicalMemoryConfiguration"))/1024
$ProcessorSpeed = WMIQuery("CurrentClockSpeed","Win32_Processor") + " Mhz"
$PagefileSpace = val(WMIQuery("TotalPageFileSpace","Win32_LogicalMemoryConfiguration"))/1024
;Enumerate all disk info into arrays, then cross-reference for required info
$arrDeviceIDs = Split(WMIQuery("DeviceID","Win32_LogicalDisk"),"|",-1)
$arrFreeSpaces = Split(WMIQuery("FreeSpace","Win32_LogicalDisk"),"|",-1)
$arrTotalSizes = Split(WMIQuery("Size","Win32_LogicalDisk"),"|",-1)
$arrFormats = Split(WMIQuery("FileSystem","Win32_LogicalDisk"),"|",-1)
For $Counter = 0 To UBound($arrDeviceIDs)
If $arrDeviceIDs[$Counter] = "C:"
$C_DriveFormat = $arrFormats[$Counter]
$C_DriveFreeSpace = $arrFreeSpaces[$Counter]
$C_DriveTotalSize = $arrTotalSizes[$Counter]
$Counter = UBound($arrDeviceIDs) + 1
Endif
Next
;Sort the returned disk spaces values into MB
;$C_DriveFreeSpace = Val($C_DriveFreeSpace)/1048576
;$C_DriveTotalSize = Val($C_DriveTotalSize)/1048576
;First, set variables for the connection to the database and other general options
$=SetOption("WrapAtEOL","On")
$DATABASE = "$logon\inventory\inventory.mdb"
$DSN="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DATABASE"
;Create SQL statements to check/write/update database
$CHECK_ENTRY_USERS = "SELECT * FROM TBL_USERS WHERE USERNAME='@USERID';"
$CHECK_ENTRY_COMPUTERS = "SELECT * FROM TBL_COMPUTERS WHERE WORKSTATION='@WKSTA';"
$Connection = CreateObject("ADODB.Connection")
$Command = CreateObject("ADODB.Command")
$Recordset = CreateObject("ADODB.Recordset")
;Check for connection object
if $Connection
? "i'm in there"
;Open connection to database
$Connection.ConnectionString = $DSN
$Connection.Open()
;Check for existing records for the current workstation/user
;Add new record or update existing as required
;Check for User details first
$Command.ActiveConnection = $Connection
$Recordset.CursorType = 3
$Recordset.LockType = 3
$Recordset.ActiveCommand = $Command
$Command.CommandText = $CHECK_ENTRY_USERS
$Recordset.Open($Command)
;Create new record if none exists to update
If $Recordset.RecordCount < 1
? "adding new user record"
$Recordset.AddNew
Endif
;Write user values into database field by field
$Recordset.Fields("UserName").Value = @USERID
$Recordset.Fields("FullName").Value = @FULLNAME
$Recordset.Fields("Workstation").Value = @WKSTA
$Recordset.Fields("PrivilegeLevel").Value = @PRIV
$Recordset.Fields("HomeDrive").Value = @HOMESHR
$Recordset.Fields("LastUpdate").Value = @DATE + " " + @TIME
;Update the new record and close the recordset object
$Recordset.Update
$Recordset.Close()
;Check Computer details next - refresh $Recordset object with new query
$Command.CommandText = $CHECK_ENTRY_COMPUTERS
$Recordset.Open($Command)
;Check for existing record to update
If $Recordset.RecordCount < 1
? "adding new computer record"
$Recordset.AddNew
Endif
;Write values into table
$Recordset.Fields("Workstation").Value = @WKSTA
$Recordset.Fields("NTDomain").Value = @DOMAIN
$Recordset.Fields("SystemManufacturer").Value = $SystemManufacturer
$Recordset.Fields("SystemModel").Value = $SystemModel
$Recordset.Fields("SerialNo").Value = $SerialNo
$Recordset.Fields("IPAddress").Value = @IPADDRESS0
$Recordset.Fields("MACAddress").Value = @ADDRESS
$Recordset.Fields("OS").Value = @PRODUCTTYPE
$Recordset.Fields("ServicePack").Value = @CSD
$Recordset.Fields("PhysicalMemory").Value = $PhysicalMemory
$Recordset.Fields("ProcessorSpeed").Value = $ProcessorSpeed
$Recordset.Fields("PagefileSpace").Value = $PagefileSpace
$Recordset.Fields("C_DriveFormat").Value = $C_DriveFormat
$Recordset.Fields("C_DriveFreeSpace").Value = $C_DriveFreeSpace
$Recordset.Fields("C_DriveTotalSize").Value = $C_DriveTotalSize
$Recordset.Fields("LoggedOnUser").Value = @USERID
$Recordset.Fields("LastUpdate").Value = @DATE + " " + @TIME
;Update and close recordset object
$Recordset.Update
$Recordset.Close()
$Connection.Close()
$Connection = 0
$Recordset = 0
$Command = 0
else
Goto error
endif
:end

exit 321
:error
exit\




Breaker
(Hey THIS is FUN)
2002-02-05 06:51 PM
Re: Create/Read/Update MS Access Database

You might want to chuck a few @SERROR's in there to try and get a feel for where it might be failing.

If the connection is OK and the SQL query is returning a valid recordset object, then it may well be the $Recordset.AddNew() method that is failing... ...not sure why, though. MSDN says you can use the Supports() method to check whether your current Recordset object will support various methods, based on the cursor and lock types. You can check here for that. You'll need to look under ADO Reference -> ADO Methods.

I'm off home now, so I'll print this off and rack my tiny brain a little.

[ 05 February 2002: Message edited by: Breaker ]

Radimus
(KiX Supporter)
2002-02-05 07:09 PM
Re: Create/Read/Update MS Access Database

the @serror did the trick...

One of the recordset objects was a NULL/zero length and bombed it...

I changed the value, and away it goes...

Thanks much.

jtokach
(Seasoned Scripter)
2002-02-05 07:32 PM
Re: Create/Read/Update MS Access Database

I ran your script above with no error? What value have you changed?

Radimus
(KiX Supporter)
2002-02-05 08:59 PM
Re: Create/Read/Update MS Access Database

My network doesn't specify a home drive, and it wouldn't write the @homedrive macro... I changed it to a variable that we do use and it worked fine.

Breaker
(Hey THIS is FUN)
2002-02-06 10:51 AM
Re: Create/Read/Update MS Access Database

Whoa... didn't think of that one. Obviously I'm only grabbing info that would be of use to us here, but I figured that any NULL values would simply write empty fields to the database.

I'm gonna have to be more careful when error handling in future...

Glad you got it sorted.

Alex.H
(Seasoned Scripter)
2002-02-06 02:08 PM
Re: Create/Read/Update MS Access Database

Breaker,
You can use NULL values, but you need to explicitly allow it in the field


Radimus
(KiX Supporter)
2002-02-07 06:51 AM
Re: Create/Read/Update MS Access Database

anyone figure out how to script the build of the tables??

Like to have that automated to make it easier to archive the old ones and then the next logged on user can create the tables (and DB) before populating it.

Breaker
(Hey THIS is FUN)
2002-02-07 03:05 PM
Re: Create/Read/Update MS Access Database

You can use the SQL statement "CREATE TABLE", and specify fields and data types within this, eg "CREATE TABLE SOFTWARE (SOFTWARE_ID INTEGER NOT NULL, SOFTWARE CHAR(40) NOT NULL, PUBLISHER CHAR(40), LICENCES INTEGER);".

This would create a table called Software, with four fields - Software_ID, Software, Publisher, Licences. The type of the data allowed is specified as well - integer, text(CHAR) where the entry length is also specified, and the NOT NULL expression shows that certain fields must be populated.

For more info on SQL functions look here, or try the Access docs if you'll be using Access.

I would have thought, given the example above, that the most efficient way to perform any DB admin would be independent of the data-gathering process. I suppose it depends on the size and complexity of your network...

HTH

That might not be exactly what you meant. Whoops! Are you thinking more of the archival process and the rebuilding of new tables, identical to the archived data?

If so, building the tables, as shown above is not such a problem. The trickier part would be identifying your criteria for archival, and actually performing this process. I think (no SQL guru, me!) that you can rename a table, so maybe it would be a case of deciding when there was enough data, either by:

code:
 If $Recordset.RecordCount > 1000 ;too many records!
ArchiveTable($CurrentTable) ;possible set of DB admin UDF's coming on!
Endif

Or parsing the Date field and deciding to archive when the data covers three months (or whatever!)

HTH as well.

[ 07 February 2002: Message edited by: Breaker ]

Radimus
(KiX Supporter)
2002-02-07 09:24 PM
Re: Create/Read/Update MS Access Database

You had it right the first time... periodically, net admin would collect the MDB and archive it for historical purposes.

It would be convienient if the script would note that the MDB was absent and make a new mdb and recreate the table structure.

JSchroeder
(Fresh Scripter)
2002-06-25 11:50 AM
Re: Create/Read/Update MS Access Database

Ups ... your script is exiting at the point "if $Connection"

Any Ideas ?

Thanx


ShawnAdministrator
(KiX Supporter)
2002-06-25 01:59 PM
Re: Create/Read/Update MS Access Database

Exiting, as in bombing-out (ie script error) or exiting as in evaluating FALSE and circumventing the IF logic ? What version of Kixtart ? There was a change made with 4.10 that may impact this logic (default properties).

Ghost
(Starting to like KiXtart)
2002-06-25 05:30 PM
Re: Create/Read/Update MS Access Database

I have a question:

Here's what I want to do...

The Sports teacher would like to poll the students with a number of questions regarding the out of school activities they are in to.

Once the user has entered the details, which will be performed during login, it should not as them ever again.

Question:

How do I search the database to see if the user has already filled in the poll?

I've got the rest sorted, however, this part is baffling me.

[Smile]


BrianTX
(Korg Regular)
2002-06-25 08:46 PM
Re: Create/Read/Update MS Access Database

It can depend on how your database is set up. I assume you require an answer for each question, so you can check to see if there is a value for the questions you asked, or you can create a new field that is set whenever information is written to the database for a certain user. Generically, the easiest way to check to see if someone has taken a poll is to check if their record exists (assuming you are generating a record when they take the poll.)

Brian


jtokach
(Seasoned Scripter)
2002-06-25 08:50 PM
Re: Create/Read/Update MS Access Database

Ghost,

If you read through the above scripts by Rad, you can see where he checks if the record exists and either creates a new or updates and existing record. Rather than the update code, your logic can exit.


Jhawk
(Fresh Scripter)
2003-03-31 11:23 PM
Re: Create/Read/Update MS Access Database

A couple of quick things.. first off, big thanks to Breaker! I ran into this script earlier today because someone asked for a script like this and he linked to this thread.

I put this script in place w/ a few minor variations, and I thought I would add one that a lot of people might have a need for.

Here goes.. I don't post much, so don't hate me if something goes wrong [Smile]

The majority of our PC's are Dell, and dell likes to use "Service Tags"... these tags weren't being displayed in the serial number field, so I added the following statements.

Variables:

$ServiceTag = WMIQuery("serialNumber","Win32_SystemEnclosure")
$AssetTag = WMIQuery("SmBiosAssetTag","Win32_SystemEnclosure"

Writes to the DB:

$Recordset.Fields("ServiceTag").Value = $ServiceTag
$Recordset.Fields("AssetTag").Value = $AssetTag

At any rate, like I mentioned thanks a ton for the hard work it took to get this together Breaker!


masken
(MM club member)
2003-04-02 01:15 PM
Re: Create/Read/Update MS Access Database

Good thing I found this thread!

I'm just like jtokach, who started this thread. I often don't do things at all before I full understand how they work.

Shawn, the description you did regarding objects kicked it. Short (relatively [Wink] ), nothing missing for the understanding of the concepts, informative, and very educationalistic, thanks!  -


Sealeopard
(KiX Master)
2003-04-02 04:28 PM
Re: Create/Read/Update MS Access Database

It is recommended to use the DB...() UDFs as a database interface. See e.g. DBCommand() - Executes a SQL statement and returns a recordset if applicable