Web Q&A: Scripting Interoperability, Login Cont...

We were unable to locate this content in de-de.

Here is the same content in en-us.

This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.
MSDN Magazine
Scripting Interoperability, Login Control on a Web Farm, Custom Refreshes, App Servers, and More
Robert Hess
Q Can you call a VBScript subprocedure inside a JScript® function? If so, how?

A All functions and variables are defined in a compatible manner by the scripting engine in Microsoft® Internet Explorer, making for one big happy family. For example, the JScript and VBScript functions in Figure 1 each create a string that contains the version of the script engine that is used. I have also written functions in both languages that call both JScript and VBScript functions in order to construct a single message string that contains the results of both version reports. In Figure 1, the buttons I use to fire these reports are defined as using the language opposite the one they are really using. The bottom line is that VBScript and JScript interoperate quite nicely, thanks to the scripting engine.

Q I know how to pass server variables into client-side script, but can I pass a JScript variable into VBScript? If so, how?

A Looking back at Figure 1, you'll see that I've defined a global variable in both the VBScript and JScript sections. In jsWhoAmI I store the result in the js global variable, and in vbWhoAmI I store the result in the VBScript variable.
      Then I add two more buttons, one uses JScript and the other VBScript. Both buttons simply display an alert showing the contents of both global variables, thus showing that each language has access to values stored in the other language's global data space.
      Of course, you'll need to click on at least one of the first two buttons in order to load the version information into the global variables first.

Q I need to prevent a user from logging on to my site from two different machines at the same time using the same account information. I'm storing user ID in a session variable, and the site is running on a Web farm using many Web servers.

A There are a number of ways to accomplish your task, almost all of which will require your Web servers to maintain a state record somewhere that can reference the current login state of an account. Essentially, when a user logs in, you access a database (or some other form of queriable data storage) and set their logged in state to true; when they log out, you set it to false. If a login is attempted and the logged-in state was already true, you deny that login. When this sort of thing happens, you also want to fire up some process that attempts to determine if the account was really in an active session or not. Because synchronization errors can occur, a collision of this type would be an indication that you might want to verify the data for this user.
      The best time to turn the login status on or off is during the Session_OnStart and Session_OnEnd events. But since you are on a Web farm, the two simultaneous sessions might be coming in from two different servers, thus storing the state on one server. This won't do any good when you try testing it from another server. Obviously, you want to make sure that your servers set and retrieve the state from some master server on your farm, but if all servers must request information from a single server, you've negated some of the benefit of using a server farm.
      The solution is to have multiple account databases, with each one responsible for a subset of the account status information. That way, each of the servers in your farm would know how to identify which server was responsible for retaining the state of which accounts. Of course, it could be a bookkeeping nightmare and a source of bottlenecks if each server needed to go to a central repository to find out which server manages which account.
      Luckily, hash codes were designed to solve this problem. Remember hash functions and algorithms from your CompSci classes? In any case, a hash function is used when you want to (evenly) distribute a potentially large number of values (number, string, and so on) into a limited number of storage locations. You apply the hash function to the value, and the result is a number representing the storage location to which it is assigned. For a particular value, the hash function will always return the same storage location. This allows any server on your farm to identify which server is in charge of an account's records by knowing only the user name.
      Let's assume for a minute that you have 26 servers, and that user names always start with a letter from the alphabet. Your hash function simply looks at the first letter of the user name and returns a value from 1 to 26, which indicates the server to use. In actual practice, of course, it is rarely as simple as thisâ€"but you get the idea. In designing your algorithm you must take the valid forms of the user name into account, as well as the number of servers on your Web farm. You should also chart the returned results from hashing all the current user names, checking that you have even distribution of accounts across the servers.

Q I have two frames in my Web page. The top frame is static and the bottom frame contains a dynamic ASP page. I want to reload the current page (which includes all new dynamic content) whenever the user clicks the Refresh button. But, the entire root frameset is refreshed when you click the Refresh button.

A It sounds like you want to have the Refresh button operate on a single frame in your frameset. Unfortunately, the Refresh button refreshes whatever address is listed in the Address bar. In the case of a frameset, that's the frameset itselfâ€"not an individual frame. Not what you want, but you can't override that behavior.
      One workaround is to update the Address bar to reflect the current frame condition.
top.location.href = url-to-current-page;
You can see a slight variation of this by going to http://msdn.microsoft.com/library. In the second toolbar, you'll find a "get page url" button, which will push a url that reflects the current page layout into the Address bar. Then an ASP script reconstructs the frameset layout by passing the URLs of the frames as parameters. You can see this in action by looking at the new address in the Address bar: http://msdn.microsoft.com/library/default.asp?URL=/library/welcome/dsmsdn/msdn1.htm.
      This allows the user to select this framed page as a favorite, and be able to get back to this exact page instead of just the homepage of the frameset.
      You could also put your own Refresh button on the dynamic page itself. If this page is already too busy with other information to make such a button stand out, you could put the button in the other frame.
      However, another rather roundabout way of making the toolbars "refresh" update the view without going all the way back to the initial frame setup is to embed a frameset within a frameset. This is how the pages on http://msdn.microsoft.com/scripting are currently set up, and you'll notice that they do what you appear to be describing.

Q What is an application server? Does Microsoft have one?

A "Application server" was the up-and-coming buzzword on the Web a while back. It simply refers to putting processing logic onto the Web server, and to providing access to that processing power to the client. The translation services provided by AltaVista at http://world.altavista.com is an example of an application running on a server, and thus the Web server and software running that site are considered an application server.
      Microsoft's application server is Internet Information Services (IIS). It allows programmers to develop server-side components that interact with the Web content being sent to the user, as well as process and maintain information stored in databases and other servers on the network. For more information about the application services of IIS, refer to http://www.microsoft.com/windows2000/server/evaluation/features/application.asp. For a listing of application servers supplied by a variety of companies, see http://www.devx.com/appserver/guide.asp.

Q In your December 2000 column, you wrote about Word running in a Microsoft WebBrowser control. I want to use exactly the same technology. If you paste the following into a Word document the way you described it in your column
<frameset cols="100,*">
<frame src="WebInfo.html">
<frame src="WordDoc.doc">
</frameset>
is it possible to "influence" menu items in Word, say, take the Save function and write a Visual Basic for Applications (VBA) macro to save the document on a server? Or will I be able to trigger some functions via native Java-language code or Visual J++®?

A A lot of what you can or can't do, and how difficult it will be to carry it out, depends on exactly what you're trying to accomplish. Since you only mention saving the file back out to the server, I'll just deal with that aspect.
      There isn't any simple way to save the Word document back out to the Web server that it came from. The root of this problem is that HTTP is not a file I/O protocol like FTP. So while it is simple to fetch a file from a server, the protocol does not directly support the notion of allowing that file to be modified, then saved back to its original location.
      The notion of file upload was added to HTML form processing. This allows a user to select a file on their local machine and transfer it back to the server. But even here, you aren't sending a file directly to a location on the server; you are just sending the file information as a datastream. There must be code running on the server that is prepared to accept this, then figure out where it should be saved.
      If you are using Office 2000 and have the Microsoft FrontPage® server extensions loaded onto your Web server, you can allow users to read/write files directly to your Web server. This is not the same thing as opening up the files via
<a href="http://server/file.doc">document</a>
because the Web browser isn't pulling the file down to the local cache storage and then invoking the application on that file.
      There are numerous ways to work around the issues involved here. A relatively simple solution is to write client-side code similar to this:
<script language=vbscript>
sub LoadDocument(strFileName)
    Dim objWord
    Set objWord = CreateObject("Word.Application")
    objWord.Documents.Open strFileName
    objWord.Visible = TRUE
end sub
</script>
<button onclick="LoadDocument
        ('http://Webserver/test.doc')">Load</button>
      Please note that since this is creating an object instance dynamically, this code represents something that ordinarily can't be done because of system security settings. And even when security is set low enough to enable object creation (which is not recommended), a warning message will be sent to the user to notify them that they are about to execute script code that could be dangerous. So while this appears to be a fairly simple solution, it is inappropriate in most cases.
      The previous code can also be written as a Windows® Script Host (WSH) or HTML Application (HTA), but you'll face the same issues. A better solution is to create an ActiveX® control that you embed in your pages. This control could be code-signed, thus providing your users with some level of security control.
      An even better solution is to distribute a Visual Basic®-based application, which again behaves similar to this.
      One way to provide even stronger control over how Word opens or saves files is to write an application in Visual Basic which creates within itself a Word object that the app can then totally control. The user wouldn't see any of the normal Word menu bars or toolbars, only the document itself. The Visual Basic-based application would provide menus and buttons for controlling to any features you want to expose.

Q I need to know what features digital wallets provide. Can you point me to information about them?

A Some form of digital wallet is going to be a component of virtually every e-commerce solution, so the number of offerings and differences between each could be huge, and I'm not familiar with all the options available today.
      Microsoft's primary offering in this field is through Passport.com. For information about what the Passport.com wallet service provides, check out http://www.microsoft.com/myservices/passport/default.asp.
      You may also want to check with ECML (Electronic Commerce Modeling Language) at http://www.ecml.org to keep up to date on industry development.

Q I want to know how to disable the Back button from the navigation bar. I found the disableback function, but it is just used for Netscape Navigator.

A Disabling the Back button from script code running on a Web page really isn't something you should do. Most users don't know the exact URL they're visiting, so they rely heavily on the Back button to navigate.
      Realizing, of course, that you simply want to disable the Back button as part of a solution to some bigger problem you are facing, I've tried to think about a scenario in which this might be useful. If you are dealing with a form submission page and a user clicks the back button to go back and change some of the values after filling out the form, your process might get messed up. In this case it makes sense that you want to take more control over the process and prevent users from shooting themselves in the foot.
      One simple method is to use window.open to open your form in a new window that has no toolbars enabled, and hence no Back button (see Figure 2), however, the user could still go back by pressing the Alt + � (left arrow) key.
      There are other ways to accomplish this as well. Here is a link to an article that describes one possible solution: http://www.4guysfromrolla.com/Webtech/121698-1.shtml.

Q I would like to create an ActiveX control in Visual Basic that I would place on a Web site. The control would allow the user to navigate to a preset list of Web sites. I want to allow the user to select from the list (a simple listbox will do) and have the selected Web site launch into a new browser window. I've tried using ShellExecute, but it launches into the same window as the control. I've tried various ways to interact with the Internet Explorer container, but with no such luck.

A Take a look at the sample code in Figure 3, which comes from http://support.microsoft.com/default.aspx?scid=kb;EN-US;q174156.
      This code uses ShellExecute for launching a browser window. When I do this as part of a simple ActiveX control that I embed within a Web page, it works perfectly fine, launching a new window every time. You might also want to include the -new command-line switch to force a new instance. This would go in the string in which you have the URL. For example:
"-new http://www.microsoft.com"
Q I am developing a site that uses the Windows Media® Player throughout, but every time I go to a new page I have to keep resetting the volume from the default. I would like to know if it is possible to set the volume of the player in the <OBJECT> tag. Better still, is it possible to let the user set the volume the first time they see an embedded player, and then take that variable and pass it elsewhere?

A As it turns out, the Windows Media Player object exposes a volume property. It's a little strange and awkward to use (in version 6.4 of the Media Player). Max volume is 0, min volume is -10000, and the perceived volume ramp is not a linear progression between those two values.
      When you embed the Windows Media Player object on your page, you can specify a volume with
<param name="volume" value="-600">
and you can then get/set the volume by accessing the volume property of the object. Note that if you display the default Windows Media Player controls and the user modifies the volume with the displayed slider, this value does not appear to get reported back via that volume property (in version 6.4).
      The code in Figure 4 illustrates how a MIDI file might be embedded in a page for playback, and how it allows the user to change its volume. It would be simple for the Web page to retain that volume value and use it on subsequent pages, either through a client-side cookie, passing it in the URL, or some other mechanism.
      Placing a Windows Media Player object on every page forces a hard stop/start of not only the object, but the playback as well. If you want the sound to be continuous, then you would need to implement your site as a frame-based site and store the Windows Media Player object in one of the frames that doesn't get updated. It could even be an invisible frame. This would definitely retain volume as the user moved around the site. You could even change the music from page to page by having the new page reach out to the frame that held the Windows Media Player object and reset the file being played.

Got a question? Send questions and comments to webqa@microsoft.com.
Robert Hess is currently the host of "The .NET Show" and is a regular contributor to various areas of MSDN.

From the February 2001 issue of MSDN Magazine

Page view tracker