Thursday, August 9, 2007
Diablopup.net
I am in the process of consolidating these nerdy tidbits in a dedicated site, Diablopup.net. I found at the outset that blogspot was bad for displaying code snippets unless you spend a lot of time formatting your template. I'm simply not that smart. To get around this, I often forwarded you to my live spaces blog. What a pain, I agree.
So, it may take awhile, but look for this blog to shrink and the new site to grow. The live spaces blog will go away, and you can bookmark diablopup.net . For now, I have created a feed to the site, down below (near the Google ads ;)).
Thanks for visiting!
Monday, July 30, 2007
Friday, July 27, 2007
Tuesday, July 24, 2007
Friday, July 20, 2007
File Attribute in Web.Config
Another option is the File attribute. An example is provided in the following blog. I think this attribute has more going for it than the configSource attribute.
Default + Optional Override
The file attribute allows you to keep default settings in your web.config. If .NET finds the specified configuration specified by the file attribute, it overrides your defaults. This provides you with the option to decouple your configuration from web.config:
If asp.net finds a "user.config" in my application directory, it uses those settings.
Available in ASP.NET 1.1
Given the file attribute's availability in asp.net 1.1, I don't see the added value that the configSource attribute provides in asp.net 2.0. Comments?
File Must Reside within the Application's Physical Directory Structure
To further decouple the application from configuration, I tried specifying the file in a virtual location. This would allow me to stage configuration updates separately from application updates. Like the configSource attribute, it was no dice. Rats.
Wednesday, July 18, 2007
Product Recommendation: Beyond Compare
Use Beyond Compare to verify. It quickly surfaces file system differences in a nice GUI.
Side By Side Directory Comparison
The directory comparision displays a side-by-side listing of the "source" and "compare to" directories. Use the "<>" option to display only the differences:
Line by Line File Comparision
Differences will be highlighted via color codes. When you want to drill down into a specific file difference, simply double-click to view a line-by-line file comparison:
Options
Use the referee icon to enable/disable compare options. For instance, an extract from Visual Sourcesafe will yield a new date/time stamp, even if you know the file on the compare directory is identical. Unflagging the "Timestamp" folder comparison criteria will remove this comparison "noise" and allow you to spot more meaningful differences.
Monday, July 16, 2007
Tuesday, July 10, 2007
VBScript - Read From Registry
- function readFromRegistry (strRegistryKey, strDefault )
- Dim WSHShell, value
- On Error Resume Next
- Set WSHShell = CreateObject("WScript.Shell")
- value = WSHShell.RegRead( strRegistryKey )
- if err.number <> 0 then
- readFromRegistry= strDefault
- else
- readFromRegistry=value
- end if
- set WSHShell = nothing
end function
Usage:
- str = readfromRegistry("HKEY_LOCAL_MACHINE\SOFTWARE\Adobe\ESD\Install_Dir", "ha")
- wscript.echo "returned " & str
Monday, July 9, 2007
BlogSpot Title Entry Bug
Wednesday, June 27, 2007
Beware of Nested Web.Config's!
If your web servers host a complex IIS tree, beware of nested ASP.NET applications and their respective web.config's. If a "parent" ASP.NET application declares a type (and therefore a dependency on an assembly), the "child" application inherits this declaration. See the following msdn article for lengthy discussion.
What this means, ultimately, is that your child application will be looking for a dll in its /bin folder. When it doesn't find it, the child application throws a yellow screen.
Here is an example. I've set up http://localhost/MyApp, a do-nothing app that happens to implement the ASP.NET 1.1 URL Mapping Module discussed in a previous blog. I've built another do-nothing app, and for demonstration purposes created a virtual directory hosting this app under the do-nothing parent, http://localhost/MyApp/MySubApp.
See what happens when I try to run the child app from a browser...
Solutions
To resolve the error above, you can take one of the following approaches:
- Copy the assembly to the child's /bin folder. This works, but it's sloppy configuration. Why xcopy dll's across your file system, introducing redundancy and superfluousness?
- GAC the assembly. That way it's available to the child, and any other application, whether or not it's needed.
- Restructure IIS to avoid the problem.
Friday, June 22, 2007
SourceForge.NET's Telnet Library Rocks
- Telnet mySQLServer 1433
- Telnet myOracleServer 1521
- Telnet myMailServer 25
- etc.
Enter SourceForge.NET's Telnet .NET library. Download this library, add it to your application's references, write a simple web form that tests remote host and port combinations from user input, and you have a helpful diagnostics tool. It is presently saving my life.
Thursday, June 21, 2007
Attaching Lotus Notes links to Outlook Mail
...Yeah, it's that kind of place. If you've been around awhile and know where things are, you are indispensable :).
Anyway, the great thing about using Notes for email and work was that you could embed all kinds of referral links in your email using "copy as link" at the Notes data and then ctrl+v paste in the email. The ctrl+v doesn't work in Outlook, which is a drag. So here's a work around...
Step 1 - Copy as Link
Go to your Notes document or database (shown below), right click and select "copy as link"
Step 2 - Paste Ctrl+V to a Text Editor
Note the interesting markup
Step 3 - Save the Text File with an .NDL ExtensionStep 4 - Attach the .NDL file to your Email Message
...as shown. When the recipient double-clicks the attachment, they go right to Notes!
Tuesday, June 19, 2007
VS.NET 2005 - Where are the Binaries?
In VS.NET 2003 when you set up a web application, an IIS virtual directory was automatically created, most commonly pointing to a file system folder in c:\inetpub\wwwroot.
When you compiled your application, a single binary, appname.dll, was created in c:\inetpub\wwwroot\appname
VS.NET 2005 - Where did the Binary go?
If you just started developing in VS.NET 2005, you may be oblivious, happily leveraging your new master pages and themes. Just wait until you try to deploy your application to another server. You'll come to find:
- While developing, your application was running under Webdev.webserver.exe, not IIS.
- There is no /bin directory. In fact, there is not c:\inetpub\wwwroot\appname directory.
To find your development artifacts, visit C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files . The structure may confuse you -- it's more esoteric then appname/bin probably consisting of files with a .compiled extension. VS.NET 2005 has a new compilation model, a subject for another day.
To move your application into IIS:
- Use the Build/Publish Website interface to create a "release directory".
- Create a virtual directory that points to the release directory.
- Make sure the virtual directory is configured to run under ASP.NET 2.0
Monday, June 18, 2007
ASP.NET 1.1 - URL Mapping
Just add the custom HTTPModule's dll to your application's bin folder, then tailor your web.config appropriately, and you have what ASP.NET 2.0 provides!
Friday, June 15, 2007
ASP.NET 2.0 - URL Mapping
Say for instance you have an online store, offering a new product to a segment of customers. The path to the catalog item is
- http://AcmeCorp.com/store/catalog.aspx?productid=TY3466a&customerid=143044&branch=south
- http://AcmeCorp.com/store/MultiVitamins.aspx
The highlighted section specifies the url mapping. The vanity url's (Diablo_Config.aspx and Diablo_Config.aspx?loc=test) are actually just as complicated as the actual paths (testconfig.aspx and test/testconfig.aspx), but it illustrates what's possible. The following screenshots illustrate what the "customer" sees:
The aspx page that outputs the appSettings is simply copied to the application root and /Test folder for illustrative purposes. If you're interested in aspx (not code-behind) that references app settings, see the following link.
Sunday, June 10, 2007
ASP.NET Deployment Error
It happens when a developer tries to deploy their first ASP.NET application to an ISP's or employer's shared web server environment. Take a close look at the graphic above, particularly the highlighted section. It's a helpful clue, though in most cases it's not exactly correct.
What's most likely is that the application folder was copied to the site on the production server, without configuring the folder as a virtual directory at all. See earlier IIS posts on automating the creation and configuration of virtual directories with VBScript. You can hand these off to your site administrator.
Wednesday, June 6, 2007
"Shredding" your Outlook Documents
Deleting Items
You delete email all the time, and are probably familiar with the Outlook "deleted items" folder: (deleted items folder)
To clear space for you mailbox (most administrators enforce a size limit) on the mail server, you probably clear this folder routinely. You do this by deleting all items from the "deleted items" folder, kind of like clearing the recycling bin on your file system.
(emptied deleted items)
Clearing Deleted Items, for Good
To remove the items "for good", go to the Tools/Recover Deleted Items menu option and delete all Outlook documents for a third and final time. The "X" icon takes care of it for you. CYA!Monday, June 4, 2007
C# Console App Displaying Remote ASP.NET Configuration
- Machine Name - the network machine you wish to query
- Site Name - the IIS site node you wish to query
- User Name - user id to log into the remote machine
- Password - user password to log into the remote machine
- The app uses System.DirectoryServices.DirectoryEntry to navigate the IIS Tree and recurse through virtual directories, seeking configuration
- The app uses the static WebConfigurationManager class to open and read the AppSettings collections
- The main function is overloaded such that user name and password are optional. When not supplied, the logged in credentials of the executing machine are used.
- In order to read remote configuration, you must run "aspnet_regiis config+" on the remote server.
Thursday, May 31, 2007
Site Monitoring - Simple Tool
- Create a "KeepAlive" page; a simple page with a static, predictable response. I have created a simple page that displays the Site Name, Web Server Name, and Site IP Address:
- Implement a VBScript which makes an http request of the Keep Alive page, returning the response string. The script implements the Microsoft.XMLHTTP object. If the request does not resolve or returns an unexpected result, the script sends an email to the stakeholder (you).
- Implement an NT Scheduled Task to run the VBScript (#2) every five minutes. Hopefully, you'll never hear from the tool :)
Tuesday, May 29, 2007
ASPBufferingLimit - IIS5 vs. IIS6
First I ruled out the most obvious and usual offenders during a migration - code and data. Configuring the app on my development machine (IIS5), pulling down the production code and pointing to the production db, the app functioned swimmingly.
Moving on, I researched and came across an IIS ADSI property, "ASPBufferingLimit". Apparently IIS6 sets a lower constraint on the ASP Buffer than IIS5. Good for a healthy web server, but bad for some legacy apps.
The issue was resolved by upping the buffer limit on the IIS6 server. The server administrator accomplished this by running:
- c:\inetpub\adminscripts\adsutil.vbs set w3svc/aspbufferinglimit value
Friday, May 25, 2007
Enable IIS 6.0 Extensions using VBScript
- Set IIsWebServiceObj = GetObject("IIS://localhost/W3SVC")IIsWebServiceObj.EnableWebServiceExtension "ASP.NET v1.1.4322" IIsWebServiceObj.SetInfo
- Option explicit
dim IIsWebServiceObj
Set IIsWebServiceObj = GetObject("IIS://localhost/W3SVC")
'Enable Proprietary Extention
IISWebServiceObj.AddExtensionFile "c:\mydll.dll", true, "MyDLL", true, _ "MyProprietaryExtensions"
IIsWebServiceObj.SetInfo
wscript.echo "success!"
Wednesday, May 23, 2007
"Visual studio could not identify the version of ASP.NET on the Web server. Do you want to continue?"
- (Copy Project Interface; Options I chose to create a lean deployment directory...)
- (...And the mysterious warning)
Browsing Google and various Forums, I was led to believe that my .NET Framework/ASP.NET installs were somehow corrupt, and I would have to reinstall or run the aspnet_regiis.exe utility. This didn't sound right to me. I have functioning 1.1/2.0 apps in my development environment, and was able to execute the Copy Project for other 1.1 projects.
I beat myself up about this a bit, and then finally selected "Yes". VS.NET went ahead and built the deployment directory as specified, but not before presenting me with the following popup:
This prompt was familiar to me; it's what you see when an application does not have anonymous access enabled in IIS. Enabling anonymous access eliminated the original VS.NET error!
Hopefully this tip will save someone troubleshooting time or scalp hair.
Monday, May 21, 2007
Overriding Web.config Using Location Tag
Use the <location> tag in web.config to describe the settings for folders within the application.
Web.config Snippet
I have a web application set up in c:\inetpub\myapp, aka http://localhost/myapp. A snippet from web.config is illustrated here:
The application reads settings from the
MyApp Settings
The following screen shot illustrates the default behavior:
And here are the overrides, using the same test page under the /Test folder:
Piece of cake, huh? For the brief testconfig.aspx source code, visit the following link.
Friday, May 18, 2007
Developers: Friendly HTTP Errors can be Unfriendly
These "friendly" errors can mask a problem when troubleshooting. This is prevalent in ASP applications. The following app is missing a virtual directory, and the client has friendly errors turned on:
That doesn't really tell you much, does it? Now here's what we get with the option turned off:
That's a little more informative (minus the proprietary details), isn't it? Keep it unfriendly!
Thursday, May 17, 2007
Wednesday, May 16, 2007
Get To Know Your Hosts File
It is a plain text file located within your system directory. It has no file extension.
- Windows 2000 - c:\winnt\system32\drivers\etc\hosts
- Windows XP, 2003 - c:\windows\system32\drivers\etc\hosts
- You'll find equivalent files in other OS's (e.g. Unix)
Your Hosts file overrides DNS, forcing HTTP requests to route the way you specify.
Why is it Useful?
There are all kinds of uses for Hosts, depending on your problem at hand. Here are some examples:
- You set up numerous IIS sites (e.g. http://mysite.com) in a development environment (server OS), and want to test them via a browswer.
- You are developing a single site with multiple behaviors based on domain name (e.g. http://myBlueSite.com has a blue background; http://myRedSite.com has a red background). You want to be able to test these behaviors.
- Your are troubleshooting your company's load-balanced server farm. Customers are complaining about a site/application, but you are having difficulty recreating. If the problem is isolated to a specific server, you can force http requests to each server in the farm, provided you have the list of IP addresses.
- You want to block various ad/banner nuisances.
You are developing a fictional site to IIS, running Windows XP. Call this site http://diablolovessteak.com.
- Open c:\windows\system32\drivers\etc\hosts in a text editor
- Add the following line:
- 127.0.0.1 diablolovessteak.com
- Save the file.
- Close any open internet browsers.
- Open a browser and go to http://diablolovessteak.com
The request will open the home page of your default web site. If you've never used Hosts, give it a shot!
Monday, May 14, 2007
DNS For Dummies
If you are like me, application-heavy and network-light, then DNS is a relative mystery to you. A friend (network guy) gave me the following high level explanation.
You type and enter an address into your browser, e.g. http://diablopup.blogspot.com.
The first thing that happens is your computer asks your ISP's (e.g. AT&T's) DNS server (1) "do you know the IP address for this website?" If it does, it will tell your computer what it is, and you connect directly to the Website Server (3).
If your ISP's DNS server doesn't know, it will ask (in a roundabout way) the website owner’s DNS server for the IP address(2). Then it connects to the website server (3).
Once your ISP's DNS server knows the IP address, it keeps it in cache so it doesn't have to ask again, thereby making the connection quicker on subsequent requests. This is why you sometimes experience a slow page load when visiting a website for the first time, but then witness quicker connection on subsequent visits.
There are more "nuts and bolts" to DNS, but this is an intuitive picture for people who can't work with DNS directly.
Thursday, May 3, 2007
Installing a Windows Service
A few weeks ago I wrote a brief entry on Lewis Moten's Visual SourceSafe Journal Monitor. This tool runs as a windows service, polling the specified journal.txt every few minutes and updating a data source with the latest VSS changes.
This got me interested in windows services in general and how you set them up using VS.NET. Here is a link to another CodeProject article focusing on setting up a Windows Service project. It details:
- How to set up and build a simple Windows Service project.
- How to create a setup package (.msi) to install the Windows service.
I work for an organization where the administrators will not accept an .msi package. They want more visibility into what exactly you are trying to do to their production machines, since they are ultimately responsible for keeping them up and running.
Here's how you can install/uninstall a windows service .exe using VBScript .
Tuesday, May 1, 2007
Monday, April 30, 2007
Our Vendor Skipped the Gym to Help Us Out
As part of the transition to a "cheaper" solution, we moved a bunch of our web servers from our data centers (which were once run by in-house employees with domain knowledge) to the vendors. Lo and behold, stuff stopped working, particularly applications' ability to connect and perform database operations.
So that's all the back story. Here was the kicker...this dba for the vendor wanted us to know that she skipped the gym to get our products, that our customers rely on, up and running again.
Never ever tell a customer that you are really put out by their request. Some analogies:
- "I'll have you know I'm missing my high colonic to make you this bagel"
- "I skipped my nap to perform this hysterectomy"
Friday, April 27, 2007
Implementing a "Click Through" in Classic ASP
Both the "referrer" (click.asp) and the "target" (servervars.asp) are illustrated here.
Here's How you Force SSL in Creaky Old ASP
Use the ASP ServerVariables collection to check the current connection, then redirect appropriately.
Copy/Paste the following into a text file and name it ForceSSL.asp:
<%
If UCase(Request.ServerVariables("HTTPS")) = "OFF" Then
'''get page
- sRedirect = "https://" & Request.ServerVariables("SERVER_NAME") &
- Request.ServerVariables("PATH_INFO") & "?" & Request.Querystring
- Response.Redirect sRedirect
%>
For each page in the site/application, add a server-side include that looks like this:
<!--#include virtual="/ForceSSL.asp"-->
AG, hope this helps you out. I'm probably weeks too late.
Wednesday, April 25, 2007
Tuesday, April 24, 2007
Tuesday, April 17, 2007
Web.config - Using an External File
Say, for instance, you want to manage a single code base (one web.config file) but you want the application to behave differently on different servers (development, QA, production).
ASP.NET 2.0 allows you to modularize a configuration section using the configSource attribute. The following is an illustrative example:
MyApp has a web.config file that specifies an external source for the appSettings section:
You can store the external file, appSettings.config, anywhere within the application, provided the configSource attribute must specifies a virtual path. Sorry, physical paths or paths outside the application are prohibited.
Getting back to the example, appSettings.config contains a well-formed <appSettings> section:
That's all there is to it! To test the retrieval of these settings, here is a simple .aspx form, testconfig.aspx:
Finally, here's what the output looks like when you visit http://localhost/myapp/testconfig.aspx:
Monday, April 16, 2007
Google Driving Directions
- Go to Google and select "Maps"
- Select "Get Directions"
- Get directions from "New York, New York" to "London, England" or other major European city.
- Read the instructions very carefully.
Friday, April 13, 2007
Aspnet_regiis -c
It is most common in production environments that host multiple IIS sites and applications.
ASPNET_CLIENT
If your ASP.NET 1.1 application implements dynamic validation controls, it is dependent on the existence of an /aspnet_client directory. This directory must be a child folder of the site's home directory. Here is a sample scenario:
- We have a site on a production server, abc.com.
- abc.com serves web pages residing on the server's file system at c:\abc. This is the home directory.
- I have an asp.net application hosted at abc.com/newapp
- My application serves web forms residing at c:\myapps\newapp
My "newapp", which uses validation controls, depends on the existence of c:\abc\aspnet_client. If the ABC site is managed by someone else (some other department in your company), you may not be comfortable with this dependency! E.G, what if someone managing the site content in abc.com ignorantly deletes /aspnet_client, fearing it to be malicious?
Furthermore, while /aspnet_client is handled for you in VS.NET, it is not automatically created for new sites added to IIS. So if you are launching a new site and a new ASP.NET 1.1 application, you will have to include a step to build the /aspnet_client directory. This step is:
Aspnet_regiis -c
This creates the /asnet_client folder under EVERY website node in IIS. So you are safe until the next time some fool deletes it or renames it on the shared server.
Alternative to /aspnet_client
You can remove the dependency of your app on the parent root by overriding the location of the ASP.NET client scripts in web.config. First, copy the scripts folder from the parent root (e.g. c:\abc\aspnet_client) to the application root (e.g. c:\myapps\newapp\aspnet_client). For clarity, rename the folder from aspnet_client to aspnet_override. Then, set the override in web.config:
- <system.web>
<!-- WEB CONTROLS
This section is settings to enable client-side validation code.
-->
<webControls clientScriptsLocation="aspnet_override\\"/>
...
Now you manage the client scripts yourself!
Monday, April 9, 2007
Aspnet_Regiis - Encrypt/Decrypt Web.config
IIS/ASP.NET will not serve direct requests to Web.config, which protects possibly sensitive information (e.g. connection strings, email addresses) from the public...at least in theory.
You can further protect web.config information via encryption. Out of the box, the aspnet_regiis.exe utility will encrypt web.config according to your preferences.
Here is a sample <appsettings> section:
Assume that this application runs under http://localhost/myApp, we could run the following command to encrypt:
- aspnet_regiis -pe "appSettings" -app "/myApp"
Implementing Code to Retrieve Configuration Settings
What's great is that the code that accesses the configuration settings need not change, e.g.:
- string strGUID = ConfigurationSettings.AppSettings["ROOTGUID"];
...would work before and after encryption.
Decryption
To decrypt the configuration settings, just substitute a "-pd" switch for "-pe":
- aspnet_regiis -pd "appSettings" -app "/myApp"
...Finally, I came across a good article about handling this encryption/decryption programmatically (e.g. via an ASP.NET page or a Console App). Here's the 4gfr link.
Friday, April 6, 2007
Intro to Aspnet_Regiis.exe
Aspnet_regiis.exe is a command line utility that installs ASP.NET features to Internet Information Server (IIS). You find it in your c:\windows\microsoft.net\framework\v#.### directory. Installable components include such things as:
- An ISAPI Filter - used by IIS to direct incoming requests to the appropriate asp.net
runtime engine based on the extension (e.g. .asp, .aspx) - Script Maps - configuration settings in each IIS node that specify how various extensions are processed (see Figure 1).
- Client Validation Scripts - /aspnet_client Javascripts that provide dynamic behavior to web form validation controls (see Figure 2)
- Options for encrypting asp.net configuration (*.config) files.
- etc
(figure 1 - aspx script mapping)
(figure 2 - client validation scripts)
HOW DO I USE IT?
Very carefully :). Read the various options by typing "aspnet_regiis.exe -?". Run them on a development server to get familiar with them, backing up the IIS metabase appropriately.
CAUTION: Using the "-i" Switch
If you run the utility with "-i", you will install the ASP.NET version specified by the utility's parent directory (e.g. "v1.1.4322"). This includes the ISAPI filter and script maps for all nodes in the IIS tree...
Think about that, because it could get you in to trouble, say, if you are running the utility from the v2.0.50727 directory of a web server that currently runs a bunch of older 1.1 applications. Those applications will be forced to the 2.0 version of the asp.net processing engine (aspnet_isapi.dll) and could very well stop working. Better to leave well enough alone!
To leave existing asp.net scripts as-is, use the combination switch "-ir". Per the documentation, this installs the specified version of ASP.NET without updating script maps. Then to set assign applications to the appropriate version, set them manually in IIS or use script explained in this earlier blog.
Wednesday, April 4, 2007
VBScript Fun - Create a File System Directory
So, an example...
Say you want to automate the creation of a file system hierarchy, with folders that don't currently exist, and branch pretty deeply. Using the following function, you can pass a long path and the File System Object will create each layer:
makeDirectory "c:\diablopup\testing\a"
- '''''''''''''''''''''''''''''''''''''''''''''''''''
- ' This method is responsible for creating a directory
- ' The directory can be several layers deep, and if the
- ' parent directories don't exist, it creates them.
- ' If the directory already exists, it is left alone
- ''''''''''''''''''''''''''''''''''''''''''''''''
- sub makeDirectory (newPath)
- Dim myArray,length,count,path,outputFileObject
- Set outputfileObject = CreateObject("Scripting.FileSystemObject")
- if outputfileObject.FolderExists(newPath) then
- wscript.echo "Dir: "&newPath&" already exists <-- makeDirectory() "
- exit sub
- end if
- path = ""
- count = 0
- myArray = split(newPath, "\")
- length = ubound(myArray)
- while count <= length
- path = path + myArray(count) + "\"
- count = count + 1
- if not outputfileObject.FolderExists(path) then
- end if
- outputfileObject.CreateFolder(path)
- wend
- wscript.echo "Created Dir: "&newPath&" <-- makeDirectory() "
Tuesday, April 3, 2007
VB.NET - Visual SourceSafe Journal Monitor Service
He remarked that while VSS provides solid version control facilities, the reporting was lacking. How do you get a snapshot of the VSS activity for a time period, or for a person?
VSS is project-centric, providing history for a project. If you want info on activity for a time period or a person, you are left to eyeball the journal (text file), provided you have one configured.
This guy brought up a good point, and it was clear from the discussion that he was used to working with the tool. But I got to thinking. The VSS Journal is a list of entries like the following:
$/MyApp/bin/MyApp.dll
Version: 10
User: diablopup Date: 4/03/07 Time: 4:10p
Checked in
Couldn't we parse this file into a normalized database, indexed, say, by VSS Path, User, DateTime? Then I thought, I bet someone has done this before. A little Google research, and...Thank you, Lewis Moten!
He created this neat Windows Service. Not only does it parse the journal data into a database, it keeps the database up to date by polling the journal file on a regular basis.
You can also configure it to send you notifications as a project is updated, or even to send you an instant message from MSN Messenger (I found this feature distracting, and removed it). Team Foundation Server is supposed to have these features built-in, but you (like me) may not be using it at your company for awhile.
Monday, April 2, 2007
C# Reflection Example - Debug or Release?
For example, to verify whether the current application was compiled in release or debug mode:
- Inspect the Attributes collection of the Assembly object specified by a dll path.
- Find the Attribute of type DebuggableAttribute.
- Check that Attribute's IsJITTrackingEnabled property.
Here is a link to the code.
I used it to display the compile mode in an About screen:Friday, March 30, 2007
C# Class for Routine Registry Lookups
The idea may seem kind of archaic, but you may work with web servers that have been around a long time, where legacy ASP and ASP.NET applications cohabitate. Different applications that live on these servers were probably written by different groups separate by geography and time. Standards become important in such an environment! Registry use is not an uncommon standard.
Okay, that's the long scenario explanation... Should you need to make repeated trips to a registry key or its subkeys, here is a C# class to facilitate. The functions make use of the static Microsoft.Win32.Registry object.
Example of usage:
Thursday, March 29, 2007
CDOSYS/CDOSYS - an Email Function that Works with Either
Stuff that worked in IIS4-5 doesn't always work in IIS6. Emailing using the old CDONTS.NewMail object is trouble.
To prepare for the migration, you want a single code base that works on the old and the new server. The following functions , based on the "SERVER_SOFTWARE" server variable, will help.
Wednesday, March 28, 2007
Internet Explorer Web Controls - Simple TreeView Implementation
Code moved to Live Spaces blog for readability.
Here is the result:
Tuesday, March 27, 2007
IT Jargon - "Time Stamp"
"Time Stamping" is a behavior common in matrixed, distributed organizations. E.G., you work for a technical department with say, 100 "resources", 1-2 directors who actually sign off on budgets and merit increases, and many project managers with some accountability and little authority.
For the "resources" in such an organization, it can be easy to hide and live by "time stamping" while working from home, shopping online and engaging in self-abuse. Look around, you probably know some "Time Stampers". Or maybe you are one. If so, good for you! Hopefully you are saving the money you are stealing, because the free ride won't last forever.
Monday, March 26, 2007
C# Console App to Update Machine.config
Unfortunately, I am not an administrator on the servers. No, we have outsourced that privilege to a vendor without accountability. Sound like an accident waiting to happen? That's a story for another day...
Anyway I can send a ticket to their help desk to have someone add the <appsettings> section if it doesn't exist, and then add my "Environment" key. But how do I trust that the person who picks up the ticket knows the first thing about where the appSettings section goes within Machine.config or its case-sensitive nature? I CAN'T.
The following is code for a console app that will update Machine.config according to your command line arguments:
Code snippet moved to my Windows Live Spaces Blog, for better readability.
Friday, March 23, 2007
IE Web Controls - Tree View - Client Scripts
During installation (addressed in an earlier blog), a "/webctrl_client" directory is added to your default web site (c:\inetpub\wwwroot\webctrl_client). By default, the treeview component uses this location to reference the client-side scripts for image rendering and click behavior.
If you have a shared server environment with multiple web sites (Win2k Server or Win2k3 server), you have to copy this webctrl_client folder to the home directories of each site using the controls.
Alternatively, you can define a custom location in your web.config. This would allow you to set up a virtual directory and maintain the webctrl_client stuff in a SINGLE PLACE.
Here is close to the syntax to add to your web.config, directly within the section.
<configSections>
<section name="MicrosoftWebControls" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.3300.0,Culture=neutral,PublicKeyToken=b77a5c561934e089"/>
</configSections>
<MicrosoftWebControls>
<add key="CommonFiles" value="/iistreeprint.net/webctrl_client/1_0/" />
</MicrosoftWebControls>
Thursday, March 22, 2007
Wednesday, March 21, 2007
Random Google Tip
-inurl (htm|html|php) intitle:"index of" +"last modified" +"parent directory" +description +size +(wmamp3) "Beatles"
If you have the time or inclination, this could be useful. Thanks to straight-A for pointing this out.
Enjoy
Sorting Arrays in VBScript - Part 2
Hope this helps somebody!
'******************************************************************************************
' SortObjectArrayByName - sort an array of objects by their name attributes
' arrObj - incoming array of unsorted objects
'******************************************************************************************
function SortObjectArrayByName(arrObj)
dim i, j, temp
dim name0, name1, obj
for i = UBound(arrObj) - 1 To 0 Step -1
for j= 0 to i
set obj = arrObj(j)
name0 = obj.name
set obj = arrObj(j+1)
name1 = obj.Name
if name0 > name1 then
set temp = arrObj(j+1)
set arrObj(j+1) = arrObj(j)
set arrObj(j) = temp
end if
next
next
SortObjectArrayByName = arrObj
end function
Tuesday, March 20, 2007
Sorting Arrays in VBScript
'****************************************************************************************** ' SortArray - sort a string or numeric array
'****************************************************************************************** function SortArray(arrShort)
dim i, j, temp
for i = UBound(arrShort) - 1 To 0 Step -1
for j= 0 to i
if arrShort(j)>arrShort(j+1) then
temp=arrShort(j+1)
arrShort(j+1)=arrShort(j)
arrShort(j)=temp
end if
next
next
SortArray = arrShort
end function
Internet Explorer Web Controls - Installation
http://www.microsoft.com/downloads/details.aspx?FamilyID=FAC6350C-8AD6-4BCA-8860-8A6AE3F64448&displaylang=en
It mentions that the controls are specifically for Content Management Server. Don't be fooled. They are the same controls. The CMS team seems to have taken it upon themselves to create a more user friendly install package.
Programmatic IIS Administration - Selecting a Virtual Directory
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' This sub will pass back a VirtualDirectory from a given Website Name, Virtual Directory Child 'Name
' Paramters: WebSite = Website Name
' VirDirName = Virtual Directory Name
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
function GetVirtualDirectory(WebSite,VirDirName)
dim adspath,rootobj,WebSiteObj
set WebSiteObj=GetWebSiteByName(WebSite)
set rootObj=getObject(WebSiteObj.adsPath&"/root")
adspath=rootobj.adspath
set GetVirtualDirectory=getObject(adspath&"/"&VirDirName)
end function
Monday, March 19, 2007
Assign an Application Pool using VBScript
Note that it relies on a helper function to check if the pool exists.
It also makes sure that the current machine is Win2003 -- you can't specify pools in prior OS's. This OS check function was detailed in a previous blog
'****************************************************************************************** ' Name: SetAppPool
' Description: Assign the IIS Object to an Application Pool (IIS 6 only)
' Inputs: ObjApp (IIS Object), strAppPool (Pool to assign to)
'******************************************************************************************
sub SetAppPool(ObjApp, strAppPool)
if instr(GetOS_Remote("."), "2K3") <> 0 then
if AppPoolExists(strAppPool) then
ObjApp.AppPoolId = strAppPool
ObjApp.SetInfo
logmsg "Set App Pool to " & strAppPool
else
logmsg "Error: App Pool " & strAppPool & " Not Found"
end if
else
logmsg "Skip app pool setting; not a 2003 server"
end if
end sub
'******************************************************************************************
' Name: AppPoolExists
' Description: See if the application pool exists (IIS 6 only)
' Inputs: strAppPool
'******************************************************************************************
function AppPoolExists(strAppPool)
dim objPool
on error resume next
Set objPool = GetObject("IIS://localhost/w3svc/AppPools/" & strAppPool)
if err.number <> 0 then
AppPoolExists = false
else
AppPoolExists = true
end if
end function
Friday, March 16, 2007
Setting ASP.NET Version via Script
Here is a function for setting the version using ADSI automation:
Code snippet moved to a dedicated blog for readability
CDONTS, CDOSys, and a Blank Email Address
Code must be migrated from using CDONTS.NewMail to CDOSys.Message. Required changes are fairly straightforward.
Here's a subtle difference: your ASP application under CDONTS will not visibly fail if you provide an empty string "" for the email address. Rather, the email message will fall into your ISP's bad mail bin. CDOSys, on the other hand, will throw an error, and the application will quit on the end user if the error is unhandled.
Here are proof of concept scripts to show you the variance. You can run these from a command prompt:
CDONTS(Won't fail)
wscript.echo "creating cdonts object!"
dim mailObj : set mailObj = CreateObject ("CDONTS.NewMail")
wscript.echo "created"
mailObj.From = "TestAddress@blogger.com"
mailObj.To = ""
mailObj.Subject = "hallo"
mailObj.Body = "hello there"
mailObj.BodyFormat = 1
mailObj.MailFormat = 0
mailObj.Send()
wscript.echo "mail sent, supposedly"
set mailObj = Nothing
CDOSys(Will Fail)
dim objCDOMailer : Set objCDOMailer = CreateObject("CDO.Message")
objCDOMailer.To = ""
objCDOMailer.From = "TestAddress@blogger.com"
objCDOMailer.Subject = "hallo"
objCDOMailer.TextBody = "hello there"
objCDOMailer.Send set
objCDOMailer=nothing
wscript.echo "Message sent successfully!"
Thursday, March 15, 2007
Apologies for Code Snippet Formatting
I clearly haven't mastered the posting editor. I hope to improve, or find a blog host with a better editor.
Query a Machine's OS Using WMI
For example, you can't set up an IIS Application Pool on Windows 2000, which does not run IIS 6, but you still want to install web applications and manage a similar IIS tree.
Here is a function that returns an OS indicator. You can query a remote machine's OS, provided you have administrative access. To query the local machine, use "." for the machine argument.
'***************************************************************
' Get System OS from a Remote Machine
'***************************************************************
Function GetOS_Remote(strMachine)
'WMI is required for this script to function
Dim strComputer, strWMIOS
Dim objWmiService : Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strMachine &
"\root\cimv2")
Dim strOsQuery : strOsQuery = "Select * from
Win32_OperatingSystem"
Dim colOperatingSystems : Set colOperatingSystems =
objWMIService.ExecQuery(strOsQuery)
Dim objOs
Dim strOsVer
For Each objOs in colOperatingSystems
strWmios = objOs.Caption & " " & objOs.Version
Next
Select Case True
'Add more info to the 98 and 95 to get the specific version. i.e. 98SE 95 a,b,or c
Case InStr(strWmiOS, "2000 Server") > 1 : GetOS_Remote = "2KSRV"
Case InStr(strWmiOS, "2003, Standard") > 1 : GetOS_Remote = "2K3SRV"
Case InStr(strWmiOS, "2003, Enterprise") > 1 : GetOS_Remote = "2K3ENTSRV"
Case InStr(strWmiOS, "2000 Advanced Server") > 1 : GetOS_Remote = "2KADVSRV"
Case InStr(strWmiOS, "Windows NT") > 1 : GetOS_Remote = "NT4"
Case InStr(strWmiOS, "Windows 2000") > 1 : GetOS_Remote = "W2K"
Case InStr(strWmiOS, "Windows XP") > 1 : GetOS_Remote = "WXP"
Case Else : GetOS_Remote = "Unknown"
End Select
End Function
Wednesday, March 14, 2007
Programmatic IIS Administration - Selecting a Site
And what happens if the server catches on fire? It may be a good idea to script the configuration. VBScript and the IIS ADSI objects offer a multitude of possibilities.
Here is a simple VBscript function for selecting a site by name (which you can then configure with proper directory security, isolation level, host headers, etc...)
Function GetWebSiteByName(WebSiteName)
dim rootObj,count,website
set rootObj=GetObject("IIS://LocalHost/W3SVC")
for each website in rootObj
if LCase(website.class) = LCase("IIsWebServer") then
if LCase(website.ServerComment)=LCase(WebSiteName) then
set GetWebSiteByName=website
exit function
end if
end if
next
end Function
Refer back for more Automated IIS Administration examples, using low-tech script :)
Running your Web Application under the Wrong ASP.NET Version?
- You've built an ASP.NET 2.0 app in your c:\inetpub\wwwroot directory.
- The app runs smashingly in VS.NET 2005 and when you run it from http://localhost/yourapp .
- When you upload it to your host or deploy it to your company's production server, it doesn't work!
Does this sound like a problem you've encountered? It's a familiar scenario.
Your application, built to ASP.NET 2.0, may be running under ASP.NET 1.1 or earlier. Symptoms include an inability for the ASP.NET engine to properly parse your web.config file. Or more specifically, yellow screens that include statements like:
- Parser Error Message: Unrecognized attribute 'xmlns'.
- Parser Error Message: Unrecognized configuration section "xhtmlconformance"
I would include the yellow screens, but the blog host won't upload my gifs. More later.