« December 2002 | Main | February 2003 »

January 24, 2003

Remember to install an Application.ThreadException event handler

Exceptions thrown in event handlers of Windows Forms applications will be uncaught unless you install an event handler under Application.ThreadException. 

January 23, 2003

Embedded Resources

Resource files can be made available to an assembly by marking their Build Action property to “Embedded Resource”.

 

If “license.rtf” is in a subfolder “Resources” of an assembly whose default namespace is “Kizmet.JobBlaster”,

the following code will recover the resource as a string:

 

System.Reflection.Assembly a = System.Reflection.Assembly.GetExecutingAssembly();

string rsrcName = “Kizmet.JobBlaster.Resources.license.rtf”;

System.IO.Stream s = a.GetManifestResourceStream(rsrcName);

System.IO.StreamReader sr = new System.IO.StreamReader(s);

string license = sr.ReadToEnd();

 

The example code in the documentation builds the resource name from the assembly’s name:

 

string rsrcName = a.GetName().Name + ".Resources.license.rtf";

 

This doesn’t seem to work in general, since the assembly name can differ from the default namespace.

 

Use ILDASM to view the assembly manifest when in doubt about what a resource is being named.

MSDE Setup & Installers, SCM.exe, Part 3

SCM has a –silent switch you can pass it.

230236 BUG: SCM.EXE Command Line Arguments Not Documented in SQL 7.0 Books

http://support.microsoft.com/?id=230236

For Example

scm.exe -Action 1 -Server myserver -Service MSSQLServer –Silent 1

 

To make a database detachable, the suggested method is set the database option OFFLINE, then detach.

 USE master

GO

ALTER DATABASE pubs SET OFFLINE WITH ROLLBACK IMMEDIATE

GO

sp_detach_db pubs

GO

 Read about OFFLINE database option, and the ROLLBACK clause:

Setting Database Options

http://msdn.microsoft.com/library/en-us/createdb/cm_8_des_03_6ohf.asp

 

See the table of internal and equivalent external properties:

Using SQL Server Desktop Engine Merge Modules

http://msdn.microsoft.com/library/en-us/distsql/distsql_8yeq.asp

For more information about these properties and valid arguments:

http://msdn.microsoft.com/library/en-us/distsql/distsql_84xl.asp

 

A. Use the SETUP.INI in the /settings switch (external property).

Example: D:\MSDE2000\>setup.exe /settings setup.ini D:\MSDE2000\setup.ini /L*v C:\MSDE_setup.log

 

B. You can pass parameters directly to the .msi package (external property) via the command line or place it in the Property table inside the .msi package (internal property).  Passing a public property can be done via the command line such as the REBOOT property above, be sure and use all caps when passing public properties (also discussed in the msi.chm help file).  So here is an example command line I could use to pass the REBOOT public property:

            Msiexec /i MyPackage.msi REBOOT=ReallySuppress

           

If you want to ALWAYS have a property set and run, you can open up the .msi package using an authoring tool, such as Orca included in the SDK Tools directory, and enter the Property name and value in the Property table.  See http://support.microsoft.com/support/kb/articles/q255/9/05.asp  for information on using Orca to make this type change.

 

C. You can run Setup.exe from within another Microsoft® Windows® application through a call to the Win32® CreateProcess() function, passing setup switches in a character string using the lpCommandLine parameter.

 

D. To run other apps from a merge modules, like SCM.exe to start SQL Server, you have to design custom actions and pass parameters, which I know is not easy with Windows Installer.

 

See also

Desktop Engine Installation Samples

http://msdn.microsoft.com/library/en-us/distsql/distsql_7b91.asp

 

 

January 22, 2003

Installer & Setup Projects, Part 2

Adding additional dialog boxes to installer interface:

-         Give the properties uppercase names.

Adding custom actions:

-          Define a class that derives from System.Configuration.Install.Installer. Easiest way to do this is to use the “Installer Class” template when adding an new item.

-         Add the [RunInstaller(true)] attribute to the class.

-         Override Install():

            public override void Install(System.Collections.IDictionary stateSaver) {

                  base.Install(stateSaver);

                  string nonsense = Context.Parameters["nonsense"];

                  // File appears in c:\Windows\System32

                  StreamWriter sw = File.CreateText("myinstalltest.txt");

                  sw.WriteLine(nonsense);

                  sw.Close();

            }

-         Add a custom action to the installer:

o       Add the action to the root for all four phases, or just to the phase of interest (typically install).

o       Add CustomActionData entries for parameters to be passed to the Installer override:

/nonsense="[NONSENSETEXT]"

 

To run another msi as a custom action from within an msi look here. It isn’t directly supported by a .NET setup project.

 

The default Context.Parameters collection contains information like the following:

Parameters["nonsense"]="Default Nons4ense"

Parameters["logfile"]=""

Parameters["installtype"]="notransaction"

Parameters["action"]="install"

Parameters["assemblypath"]="c:\program files\jobquake\jobquake.exe"

 

The AfterInstall event doesn’t fire as part running “Install” from the IDE, and

the Commit override doesn’t get called.

 

Windows Installer Documentation

dotnetfx documentation Can download self extracting dotnetfxredist.exe from here.

InstMsiA.Exe – Windows Installer Installer

InstMsiW.Exe – Windows Installer Installer

Setup.exe – Bootstrap, verifies Windows Installer, then installs .msi.

Setup.msi – The actual application.

 

Msiexec.exe Installs .msi files. Takes command line options to modify installer’s behavior.

Public installer properties can be changed at the command line or “transformed” within the .msi file(?)

Required Public Properties:

The ProductCode property is a unique identifier for the particular product release, represented as a string GUID, for example "{12345678-1234-1234-1234-123456789012}". Letters used in this GUID must be uppercase. This ID must vary for different versions and languages.

A product upgrade that updates a product into an entirely new product must also change the product code. The 32-bit and 64-bit versions of an application's package must be assigned different product codes.

The ProductCode is advertised as a product property, and is the primary method of specifying the product. This property is REQUIRED.

The value of the ProductVersion property is the version of the product in string format. This property is REQUIRED.

The format of the string is as follows: major.minor.build

The first field is the major version and has a maximum value of 255. The second field is the minor version and has a maximum value of 255. The third field is called the build version or the update version and has a maximum value of 65,535.

At least one of the three fields of ProductVersion must change for an upgrade using the Upgrade table. Any update that changes only the package code, but leaves ProductVersion and ProductCode unchanged is called a small update. The three versions fields are provided primarily for convenience. For example, if you want to change ProductVersion, but don't want to change either the major or minor versions, you can change the build version.

Note that Windows Installer uses only the first three fields of the product version. If you include a fourth field in your product version, the installer ignores the fourth field.

Extension

Description

.msi

Windows Installer Database.

.msm

Windows Installer Merge Module.

.msp

Windows Installer Patch.

.mst

Windows Installer Transform.

.idt

Exported Windows Installer Database Table.

.cub

Validation module.

.pcp

Windows Installer Patch Creation File

 

 

January 15, 2003

Query string parsing using Regex Captures

Repeated captures are accessed through Groups[i].Captures[j].

Using non-capturing groups (?:) simplifies access by eliminating unused groups from the results.

 

Match m = Regex.Match(uri, @"(?'url'[^\?]+)(?:\?(?:(?'arg'[^=&]+)=(?'value'[^&]+)&?)*)?");

 

StringBuilder sb = new StringBuilder();

sb.Append("<html><body ><form id='f' method='post' action='");

sb.Append(m.Groups["url"].Value);

sb.Append("'>\n");

 

for (int i=0; i < m.Groups["arg"].Captures.Count; i++)

      sb.AppendFormat("<input type='string' name='{0}' value='{1}'>\n"

            , m.Groups["arg"].Captures[i].Value

            , System.Web.HttpUtility.UrlDecode(m.Groups["value"].Captures[i].Value));

 

sb.Append("<input type='submit' name='Do' value='It'></form></body></html>");

Client side HTTP Redirect syntax

The following example triggers a client side HTTP redirect:

string html = String.Format(@"<META HTTP-EQUIV='REFRESH' CONTENT='0; URL={0}'>", uri);

 

January 14, 2003

MSDE Auto-Start, Windows 98

Deploying Database Solutions

net start mssql$jobquake

sqlservr -c -s jobquake in "binn" folder

MenuItems MergeMenu MergeOrder MergeType

Not sure if these comments reflect reality or just the way things should be. Generally found the behavior very confusing, under documented, and most likely improperly implemented.

 

So I ended up writing my own menu merging functions.

 

MergeType as MenuMerge property of a MenuItem:

Add – The item will be added in a merge. Items appear in order, after existing items of the same or higher order.

Remove – The item is ignored in a merge.

Replace – Each replace item will appear after the Add/Remove items with equal order and replace the first Replace item with equal order.

MergeItems – The submenu items of the item are merged.

 

MergeOrder as int, zero based

Can’t use a MenuItem in more than one menu – use CloneMenu.

 

Menu.MergeMenu(Menu) – The order of the menu doesn’t matter. The order of the menuItems does.

 

MSDE Detach Tricks

Closing and disposing SqlConnection objects isn’t sufficient to guarantee that you’ll be able to sp_detach_db a database your done working with. A trick that seems to work is to preceed calls to Close() with a call to ChangeDatabase(“master”).

Use exec sp_who & sp_lock with QueryAnalyzer to monitor the locks as you step through the program.

January 11, 2003

MSDE management using OSQL

HOW TO: Manage the SQL Server Desktop Engine (MSDE 2000) by Using the Osql Utility

C:\>osql -?

usage: osql              [-U login id]          [-P password]

  [-S server]            [-H hostname]          [-E trusted connection]

  [-d use database name] [-l login timeout]     [-t query timeout]

  [-h headers]           [-s colseparator]      [-w columnwidth]

  [-a packetsize]        [-e echo input]        [-I Enable Quoted Identifiers]

  [-L list servers]      [-c cmdend]            [-D ODBC DSN name]

  [-q "cmdline query"]   [-Q "cmdline query" and exit]

  [-n remove numbering]  [-m errorlevel]

  [-r msgs to stderr]    [-V severitylevel]

  [-i inputfile]         [-o outputfile]

  [-p print statistics]  [-b On error batch abort]

 

C:\>osql –Q -S (local)\JobQuake -U sa -P

C:\>osql –Q -S (local)\JobQuake -E

 

C:\>osql -S (local)\JobQuake -U sa -P

 

exec sp_password null, 'bojekauq', 'sa'

create database JobSearch on (NAME='js_data', FILENAME='c:\js.mdf', SIZE=1, FILEGROWTH=10%) LOG ON (NAME='js_log', FILENAME='c:\js.ldf', SIZE=1, FILEGROWTH=10%) COLLATE SQL_Latin1_General_CP1_CI_AS

create database JobSearch on (NAME='js_data', FILENAME='c:\js.mdf', SIZE=1, FILEGROWTH=10%) COLLATE SQL_Latin1_General_CP1_CI_AS

Creates the file c:\js_log.LDF as the log file.

backup database JobSearch TO DISK='c:\js.bak'

restore database JobSearch from disk='c:\js.bak'

exec sp_detach_db 'JobSearch'

exec sp_attach_single_file_db 'JobSearch', 'c:\js.mdf'

C:\>osql -L

 

Servers:

    (local)

    BLASTER

    KIRA\JOBQUAKE

    OSIRIS\VSdotNET

    PELL

    PELL\JOBQUAKE

    PELL\VSdotNET

 

January 10, 2003

Redistributing MSDE and the .NET Framework

2003-05-19 15:41 Mon

Visual Studio .NET 2003 does not include Microsoft SQL Server Desktop Engine (MSDE). To download MSDE, go to http://go.microsoft.com/fwlink/?linkid=13962.

Setup.exe /qb+ INSTANCENAME=VSDOTNET DISABLENETWORKPROTOCOLS=1 SAPWD=<YOUR SA PASSWORD>

Modified the setup.ini file for a vanilla VSDOTNET install, zipped and put on web site as msde.exe.

Tested on KIRA (Windows XP) works. Unzips to an odd folder that you have to go track down…

Tested on Virtual PC Windows 98. Works. Install has some warts.

2003-05-12 11:57 Mon

Copied from MSDN’s “Installing MSDE”:

Installing the SQL Server Desktop Engine (MSDE)

During setup, you can choose to copy the installation files for MSDE to your computer; this gives you the option of manually installing MSDE at a later time.

Installing MSDE involves three steps:

  • Setting a custom MSDE instance name. This step is optional.
  • Running setup for MSDE.
  • Starting the MSDE service.

You can skip the following procedure if you intend to use the default instance name, "VsdotNet2003".

To create a custom MSDE instance name

  1. On the Start menu, choose Run.
  2. In the Open box, type c:\Program Files\Microsoft Visual Studio .NET 2003\Setup\MSDE\ and then click OK.
  3. Double-click the file setup.ini to edit the file in Notepad.
  4. Replace VSdotNET2003 in INSTANCENAME=VSdotNET with the instance name of your choice.
  5. On the File menu, choose Save and then choose Exit.

You can install MSDE simply by running the appropriate setup file from the location where Setup copied the file.

To install MSDE

  1. On the Start menu, choose Run.
  2. In the Open box, type c:\Program Files\Microsoft Visual Studio .NET 2003\Setup\MSDE\ and click OK.
  3. Double-click the file setup.exe.

After you have installed MSDE, you must then start the MSDE service.

To start the MSDE service

  1. On the Start menu, choose Run.
  2. In the Open box, type NET START MSSQL$<instance name> and click OK.

For example, if you chose to use the default instance name, you would enter NET START MSSQL$VSdotNET2003.

 

2003-01-10 16:27

After upgrading to the MSDE SP3 .msm files:

1. These changes are still need.

After building a MSDE installer (.msi), you must edit the file with orca.exe (right click menu) to make the following changes:

InstallExecuteSequence table: 104->105,103->104,205->103,1525->6601

InstallUISequence table: 104->105,103->104,205->103

Property table:

Add Row SqlInstanceName = JobQuake

Add Row SqlProgramDir = c:\Program Files\JobQuake\

Add Row SqlSaPwd = KzSqlMsde

2. Don’t add these changes.

// Add Row SqlSecurityMode = SQL

// Add Row SqlDataDir = c:\Program Files\JobQuake Database\Data

 

Deploying .NET Applications: Lifecycle Guide

dotnetfx.exe requires Administrator account, 98,Me,NT,2000,XP okay.

 

HOW TO: Obtain and Install SQL Server 2000 Desktop Engine (MSDE 2000) (includes requirements)

HOW TO: Connect to Microsoft Desktop Engine (for 98, must use SQL. sa initially blank) 

Choosing and Using MSDE 2000 as the Database Engine for Your Application (links to using OSQL & backups using T-SQL)

 

Embedding MSDE 2000 Setup into the Setup of Custom Applications

 

Cannot Specify Instance Name Using SQL Server 2000 Merge Modules

 

HOW TO: Author MSDE 2000 Setup Packages by Using Visual Studio .NET

 

PRB: The MSDE Installation May Fail and Error 126 Is Logged When You Are Using Windows Installer Software

Run Setup.exe with /L*v [filename] for installation details logging. (*v is verbose logging, 10x the size. Try just /L first.)

HOWTO: Use the Orca Database Editor to Edit Windows Installer Files

This downloaded the Installer SDK 1.2 into c:\Program Files\MsiIntel.SDK, then ran the orca.msi in the tools directory.

To avoid 126 problem, modified the InstallExecuteSequence sequence numbers: 104->105, GetSqlState 103->104, StreamSupportFiles 206->103.

Didn’t see anything to fix in InstallUISequence.

 

Got new MSM files…..now the Setup project builds cleanly and the dependencies prior to the 1033 folder are complete. But it still fails….looks like the 126 bug.

            InstallExecuteSequence InstallUISequence

GetSqlState      103      103

StreamSupportFiles      205      205

104->105, 103->104, 205->103

Now it complains about an invalid instance name…. so let’s try using Orca to add the guys below:

SqlInstanceName = JQ

Man it was looking so good! Then error code 2613….. turn on logging and look it up.

Called Dwayne Lanclos @ SQL Server Support…469-775-8400 he had an other persons case notes which said:

InstallExecuteSequence: Move RemoveExistingProducts (1525->6601) after InstallFinalize (6600) Note that this doubles up 6601, but it seems okay.

 

Putting the external properties below under an [Options] section in a Setup.ini file works when running setup.exe and also via Orca as internal property table entries.

It appends MSSQL$[SqlInstanceName] to the paths specified for SqlDataDir and SqlProgramDir.

 

The setup author could add an entry to the Property table by using a Windows Installer database editing tool such as Orca.exe to assign the specific internal properties used in the SQL Server 2000 MSDE merge modules to a specific value. For example, to set the instance name to be used, you would add an entry to the Property table and assign the SqlInstanceName property a specific value.

The following internal properties are used by the SQL Server 2000 MSDE merge modules and can be set in this manner. The corresponding external properties are listed for reference; however, they are available only in the SQL Server 2000 Desktop Engine install package, not the SQL Server 2000 MSDE merge modules.

External Property                                                                Internal Property

CALLBACK                                                                           SqlCallback

COLLATION                                                                         SqlCollation

DATADIR                                                                             SqlDataDir                 [TargetDir]\Data

TARGETDIR                                                                         SqlProgramDir           [TargetDir]\Sql        

INSTANCENAME                                                                 SqlInstanceName       JobQuake

SECURITYMODE                                                                 SqlSecurityMode        Sql

UPGRADE                                                                             SqlUpgrade

UPGRADEUSER                                                                    SqlUpgradeUser


Some of the above properties must be specific values. The value of SECURITYMODE or SqlSecurityMode should be SQL in order to allow SQL Server authentication. For upgrading, UPGRADE or SqlUpgrade should be 1, and UPGRADEUSER or SqlUpgradeUser should be SA.

STATUS

This behavior is by design.

REFERENCES

255905 HOWTO: Use Orca to Edit Windows Installer Files

 

 

January 08, 2003

ASP.NET, Event Log Access, Creating new category entries in HKLM

Succeeded by modifying machine.config to change account from machine (ASPNET) to SYSTEM.

Problem is special permission is needed to create a new category key in the HKLM hive.

For more info see: http://www.gotdotnet.com/team/upgrade/v1/aspnet_account_readme.doc

Restarting IIS might be necessary after modifying machine.config.

Switching back to the “machine” account after adding entries as “SYSTEM” works. The category key exists? And now it just stopped working! So back to system on PELL. Yam has never had a problem…

January 07, 2003

MD5 Password Hash Pattern

Here's a little code snippet that hashes the plain-text customer password for storage in a database table:

 

sqlConnection.Open();

SqlCommand cmd = sqlCmdCustomerAdd;

cmd.Parameters["@guid"].Value = Guid.NewGuid();

cmd.Parameters["@email"].Value = tbEmail.Text;

byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes(tbPassword.Text);   

byte[] passwordHash = ((HashAlgorithm) CryptoConfig.CreateFromName("MD5")).ComputeHash(passwordBytes);

cmd.Parameters["@password"].Value = Convert.ToBase64String(passwordHash);

cmd.ExecuteNonQuery();

sqlConnection.Close();